view org/test-creature.org @ 114:9d0fe7f54e14

merged image viewing code to cortex.util
author Robert McIntyre <rlm@mit.edu>
date Thu, 19 Jan 2012 22:19:24 -0700
parents 128fa71ee188
children 247860e25536
line wrap: on
line source
1 #+title: First attempt at a creature!
2 #+author: Robert McIntyre
3 #+email: rlm@mit.edu
4 #+description:
5 #+keywords: simulation, jMonkeyEngine3, clojure
6 #+SETUPFILE: ../../aurellem/org/setup.org
7 #+INCLUDE: ../../aurellem/org/level-0.org
9 * objectives
10 - [X] get an overall bitmap-like image for touch
11 - [X] write code to visuliaze this bitmap
12 - [ ] directly change the UV-pixels to show touch sensor activation
13 - [ ] write an explination for why b&w bitmaps for senses is appropiate
14 - [ ] clean up touch code and write visulazation test
15 - [ ] do the same for eyes
17 * Intro
18 So far, I've made the following senses --
19 - Vision
20 - Hearing
21 - Touch
22 - Proprioception
24 And one effector:
25 - Movement
27 However, the code so far has only enabled these senses, but has not
28 actually implemented them. For example, there is still a lot of work
29 to be done for vision. I need to be able to create an /eyeball/ in
30 simulation that can be moved around and see the world from different
31 angles. I also need to determine weather to use log-polar or cartesian
32 for the visual input, and I need to determine how/wether to
33 disceritise the visual input.
35 I also want to be able to visualize both the sensors and the
36 effectors in pretty pictures. This semi-retarted creature will be my
37 first attempt at bringing everything together.
39 * The creature's body
41 Still going to do an eve-like body in blender, but due to problems
42 importing the joints, etc into jMonkeyEngine3, I'm going to do all
43 the connecting here in clojure code, using the names of the individual
44 components and trial and error. Later, I'll maybe make some sort of
45 creature-building modifications to blender that support whatever
46 discreitized senses I'm going to make.
48 #+name: body-1
49 #+begin_src clojure
50 (ns cortex.silly
51 "let's play!"
52 {:author "Robert McIntyre"})
54 ;; TODO remove this!
55 (require 'cortex.import)
56 (cortex.import/mega-import-jme3)
57 (use '(cortex world util body hearing touch vision))
59 (rlm.rlm-commands/help)
60 (import java.awt.image.BufferedImage)
61 (import javax.swing.JPanel)
62 (import javax.swing.SwingUtilities)
63 (import java.awt.Dimension)
64 (import javax.swing.JFrame)
65 (import java.awt.Dimension)
66 (import com.aurellem.capture.RatchetTimer)
67 (declare joint-create)
68 (use 'clojure.contrib.def)
70 (defn points->image
71 "Take a sparse collection of points and visuliaze it as a
72 BufferedImage."
74 ;; TODO maybe parallelize this since it's easy
76 [points]
77 (if (empty? points)
78 (BufferedImage. 1 1 BufferedImage/TYPE_BYTE_BINARY)
79 (let [xs (vec (map first points))
80 ys (vec (map second points))
81 x0 (apply min xs)
82 y0 (apply min ys)
83 width (- (apply max xs) x0)
84 height (- (apply max ys) y0)
85 image (BufferedImage. (inc width) (inc height)
86 BufferedImage/TYPE_BYTE_BINARY)]
87 (dorun
88 (for [index (range (count points))]
89 (.setRGB image (- (xs index) x0) (- (ys index) y0) -1)))
91 image)))
93 (defn test-data
94 []
95 (vec
96 (for [a (range 0 1000 2)
97 b (range 0 1000 2)]
98 (vector a b))
99 ))
101 (defn average [coll]
102 (/ (reduce + coll) (count coll)))
104 (defn collapse-1d
105 "One dimensional analogue of collapse"
106 [center line]
107 (let [length (count line)
108 num-above (count (filter (partial < center) line))
109 num-below (- length num-above)]
110 (range (- center num-below)
111 (+ center num-above))
112 ))
114 (defn collapse
115 "Take a set of pairs of integers and collapse them into a
116 contigous bitmap."
117 [points]
118 (if (empty? points) []
119 (let
120 [num-points (count points)
121 center (vector
122 (int (average (map first points)))
123 (int (average (map first points))))
124 flattened
125 (reduce
126 concat
127 (map
128 (fn [column]
129 (map vector
130 (map first column)
131 (collapse-1d (second center)
132 (map second column))))
133 (partition-by first (sort-by first points))))
134 squeezed
135 (reduce
136 concat
137 (map
138 (fn [row]
139 (map vector
140 (collapse-1d (first center)
141 (map first row))
142 (map second row)))
143 (partition-by second (sort-by second flattened))))
144 relocate
145 (let [min-x (apply min (map first squeezed))
146 min-y (apply min (map second squeezed))]
147 (map (fn [[x y]]
148 [(- x min-x)
149 (- y min-y)])
150 squeezed))]
151 relocate
152 )))
154 (defn load-bullet []
155 (let [sim (world (Node.) {} no-op no-op)]
156 (doto sim
157 (.enqueue
158 (fn []
159 (.stop sim)))
160 (.start))))
162 (defn load-blender-model
163 "Load a .blend file using an asset folder relative path."
164 [^String model]
165 (.loadModel
166 (doto (asset-manager)
167 (.registerLoader BlenderModelLoader (into-array String ["blend"])))
168 model))
170 (defn meta-data [blender-node key]
171 (if-let [data (.getUserData blender-node "properties")]
172 (.findValue data key)
173 nil))
175 (defn blender-to-jme
176 "Convert from Blender coordinates to JME coordinates"
177 [#^Vector3f in]
178 (Vector3f. (.getX in)
179 (.getZ in)
180 (- (.getY in))))
182 (defn jme-to-blender
183 "Convert from JME coordinates to Blender coordinates"
184 [#^Vector3f in]
185 (Vector3f. (.getX in)
186 (- (.getZ in))
187 (.getY in)))
189 (defn joint-targets
190 "Return the two closest two objects to the joint object, ordered
191 from bottom to top according to the joint's rotation."
192 [#^Node parts #^Node joint]
193 ;;(println (meta-data joint "joint"))
194 (.getWorldRotation joint)
195 (loop [radius (float 0.01)]
196 (let [results (CollisionResults.)]
197 (.collideWith
198 parts
199 (BoundingBox. (.getWorldTranslation joint)
200 radius radius radius)
201 results)
202 (let [targets
203 (distinct
204 (map #(.getGeometry %) results))]
205 (if (>= (count targets) 2)
206 (sort-by
207 #(let [v
208 (jme-to-blender
209 (.mult
210 (.inverse (.getWorldRotation joint))
211 (.subtract (.getWorldTranslation %)
212 (.getWorldTranslation joint))))]
213 (println-repl (.getName %) ":" v)
214 (.dot (Vector3f. 1 1 1)
215 v))
216 (take 2 targets))
217 (recur (float (* radius 2))))))))
219 (defn world-to-local
220 "Convert the world coordinates into coordinates relative to the
221 object (i.e. local coordinates), taking into account the rotation
222 of object."
223 [#^Spatial object world-coordinate]
224 (let [out (Vector3f.)]
225 (.worldToLocal object world-coordinate out) out))
227 (defn local-to-world
228 "Convert the local coordinates into coordinates into world relative
229 coordinates"
230 [#^Spatial object local-coordinate]
231 (let [world-coordinate (Vector3f.)]
232 (.localToWorld object local-coordinate world-coordinate)
233 world-coordinate))
236 (defmulti joint-dispatch
237 "Translate blender pseudo-joints into real JME joints."
238 (fn [constraints & _]
239 (:type constraints)))
241 (defmethod joint-dispatch :point
242 [constraints control-a control-b pivot-a pivot-b rotation]
243 (println-repl "creating POINT2POINT joint")
244 (Point2PointJoint.
245 control-a
246 control-b
247 pivot-a
248 pivot-b))
250 (defmethod joint-dispatch :hinge
251 [constraints control-a control-b pivot-a pivot-b rotation]
252 (println-repl "creating HINGE joint")
253 (let [axis
254 (if-let
255 [axis (:axis constraints)]
256 axis
257 Vector3f/UNIT_X)
258 [limit-1 limit-2] (:limit constraints)
259 hinge-axis
260 (.mult
261 rotation
262 (blender-to-jme axis))]
263 (doto
264 (HingeJoint.
265 control-a
266 control-b
267 pivot-a
268 pivot-b
269 hinge-axis
270 hinge-axis)
271 (.setLimit limit-1 limit-2))))
273 (defmethod joint-dispatch :cone
274 [constraints control-a control-b pivot-a pivot-b rotation]
275 (let [limit-xz (:limit-xz constraints)
276 limit-xy (:limit-xy constraints)
277 twist (:twist constraints)]
279 (println-repl "creating CONE joint")
280 (println-repl rotation)
281 (println-repl
282 "UNIT_X --> " (.mult rotation (Vector3f. 1 0 0)))
283 (println-repl
284 "UNIT_Y --> " (.mult rotation (Vector3f. 0 1 0)))
285 (println-repl
286 "UNIT_Z --> " (.mult rotation (Vector3f. 0 0 1)))
287 (doto
288 (ConeJoint.
289 control-a
290 control-b
291 pivot-a
292 pivot-b
293 rotation
294 rotation)
295 (.setLimit (float limit-xz)
296 (float limit-xy)
297 (float twist)))))
299 (defn connect
300 "here are some examples:
301 {:type :point}
302 {:type :hinge :limit [0 (/ Math/PI 2)] :axis (Vector3f. 0 1 0)}
303 (:axis defaults to (Vector3f. 1 0 0) if not provided for hinge joints)
305 {:type :cone :limit-xz 0]
306 :limit-xy 0]
307 :twist 0]} (use XZY rotation mode in blender!)"
308 [#^Node obj-a #^Node obj-b #^Node joint]
309 (let [control-a (.getControl obj-a RigidBodyControl)
310 control-b (.getControl obj-b RigidBodyControl)
311 joint-center (.getWorldTranslation joint)
312 joint-rotation (.toRotationMatrix (.getWorldRotation joint))
313 pivot-a (world-to-local obj-a joint-center)
314 pivot-b (world-to-local obj-b joint-center)]
316 (if-let [constraints
317 (map-vals
318 eval
319 (read-string
320 (meta-data joint "joint")))]
321 ;; A side-effect of creating a joint registers
322 ;; it with both physics objects which in turn
323 ;; will register the joint with the physics system
324 ;; when the simulation is started.
325 (do
326 (println-repl "creating joint between"
327 (.getName obj-a) "and" (.getName obj-b))
328 (joint-dispatch constraints
329 control-a control-b
330 pivot-a pivot-b
331 joint-rotation))
332 (println-repl "could not find joint meta-data!"))))
334 (defn assemble-creature [#^Node pieces joints]
335 (dorun
336 (map
337 (fn [geom]
338 (let [physics-control
339 (RigidBodyControl.
340 (HullCollisionShape.
341 (.getMesh geom))
342 (if-let [mass (meta-data geom "mass")]
343 (do
344 (println-repl
345 "setting" (.getName geom) "mass to" (float mass))
346 (float mass))
347 (float 1)))]
349 (.addControl geom physics-control)))
350 (filter #(isa? (class %) Geometry )
351 (node-seq pieces))))
352 (dorun
353 (map
354 (fn [joint]
355 (let [[obj-a obj-b]
356 (joint-targets pieces joint)]
357 (connect obj-a obj-b joint)))
358 joints))
359 pieces)
361 (defn blender-creature [blender-path]
362 (let [model (load-blender-model blender-path)
363 joints
364 (if-let [joint-node (.getChild model "joints")]
365 (seq (.getChildren joint-node))
366 (do (println-repl "could not find joints node")
367 []))]
368 (assemble-creature model joints)))
370 (def hand "Models/creature1/one.blend")
372 (def worm "Models/creature1/try-again.blend")
374 (def touch "Models/creature1/touch.blend")
376 (defn worm-model [] (load-blender-model worm))
378 (defn x-ray [#^ColorRGBA color]
379 (doto (Material. (asset-manager)
380 "Common/MatDefs/Misc/Unshaded.j3md")
381 (.setColor "Color" color)
382 (-> (.getAdditionalRenderState)
383 (.setDepthTest false))))
385 (defn colorful []
386 (.getChild (worm-model) "worm-21"))
388 (import jme3tools.converters.ImageToAwt)
390 (import ij.ImagePlus)
392 ;; Every Mesh has many triangles, each with its own index.
393 ;; Every vertex has its own index as well.
395 (defn tactile-sensor-image
396 "Return the touch-sensor distribution image in BufferedImage format,
397 or nil if it does not exist."
398 [#^Geometry obj]
399 (if-let [image-path (meta-data obj "touch")]
400 (ImageToAwt/convert
401 (.getImage
402 (.loadTexture
403 (asset-manager)
404 image-path))
405 false false 0)))
407 (import ij.process.ImageProcessor)
408 (import java.awt.image.BufferedImage)
410 (def white -1)
412 (defn filter-pixels
413 "List the coordinates of all pixels matching pred, within the bounds
414 provided. Bounds -> [x0 y0 width height]"
415 {:author "Dylan Holmes"}
416 ([pred #^BufferedImage image]
417 (filter-pixels pred image [0 0 (.getWidth image) (.getHeight image)]))
418 ([pred #^BufferedImage image [x0 y0 width height]]
419 ((fn accumulate [x y matches]
420 (cond
421 (>= y (+ height y0)) matches
422 (>= x (+ width x0)) (recur 0 (inc y) matches)
423 (pred (.getRGB image x y))
424 (recur (inc x) y (conj matches [x y]))
425 :else (recur (inc x) y matches)))
426 x0 y0 [])))
428 (defn white-coordinates
429 "Coordinates of all the white pixels in a subset of the image."
430 ([#^BufferedImage image bounds]
431 (filter-pixels #(= % white) image bounds))
432 ([#^BufferedImage image]
433 (filter-pixels #(= % white) image)))
435 (defn triangle
436 "Get the triangle specified by triangle-index from the mesh within
437 bounds."
438 [#^Mesh mesh triangle-index]
439 (let [scratch (Triangle.)]
440 (.getTriangle mesh triangle-index scratch)
441 scratch))
443 (defn triangle-vertex-indices
444 "Get the triangle vertex indices of a given triangle from a given
445 mesh."
446 [#^Mesh mesh triangle-index]
447 (let [indices (int-array 3)]
448 (.getTriangle mesh triangle-index indices)
449 (vec indices)))
451 (defn vertex-UV-coord
452 "Get the uv-coordinates of the vertex named by vertex-index"
453 [#^Mesh mesh vertex-index]
454 (let [UV-buffer
455 (.getData
456 (.getBuffer
457 mesh
458 VertexBuffer$Type/TexCoord))]
459 [(.get UV-buffer (* vertex-index 2))
460 (.get UV-buffer (+ 1 (* vertex-index 2)))]))
462 (defn triangle-UV-coord
463 "Get the uv-cooridnates of the triangle's verticies."
464 [#^Mesh mesh width height triangle-index]
465 (map (fn [[u v]] (vector (* width u) (* height v)))
466 (map (partial vertex-UV-coord mesh)
467 (triangle-vertex-indices mesh triangle-index))))
469 (defn same-side?
470 "Given the points p1 and p2 and the reference point ref, is point p
471 on the same side of the line that goes through p1 and p2 as ref is?"
472 [p1 p2 ref p]
473 (<=
474 0
475 (.dot
476 (.cross (.subtract p2 p1) (.subtract p p1))
477 (.cross (.subtract p2 p1) (.subtract ref p1)))))
479 (defn triangle-seq [#^Triangle tri]
480 [(.get1 tri) (.get2 tri) (.get3 tri)])
482 (defn vector3f-seq [#^Vector3f v]
483 [(.getX v) (.getY v) (.getZ v)])
485 (defn inside-triangle?
486 "Is the point inside the triangle?"
487 {:author "Dylan Holmes"}
488 [#^Triangle tri #^Vector3f p]
489 (let [[vert-1 vert-2 vert-3] (triangle-seq tri)]
490 (and
491 (same-side? vert-1 vert-2 vert-3 p)
492 (same-side? vert-2 vert-3 vert-1 p)
493 (same-side? vert-3 vert-1 vert-2 p))))
495 (defn triangle->matrix4f
496 "Converts the triangle into a 4x4 matrix: The first three columns
497 contain the vertices of the triangle; the last contains the unit
498 normal of the triangle. The bottom row is filled with 1s."
499 [#^Triangle t]
500 (let [mat (Matrix4f.)
501 [vert-1 vert-2 vert-3]
502 ((comp vec map) #(.get t %) (range 3))
503 unit-normal (do (.calculateNormal t)(.getNormal t))
504 vertices [vert-1 vert-2 vert-3 unit-normal]]
505 (dorun
506 (for [row (range 4) col (range 3)]
507 (do
508 (.set mat col row (.get (vertices row)col))
509 (.set mat 3 row 1))))
510 mat))
512 (defn triangle-transformation
513 "Returns the affine transformation that converts each vertex in the
514 first triangle into the corresponding vertex in the second
515 triangle."
516 [#^Triangle tri-1 #^Triangle tri-2]
517 (.mult
518 (triangle->matrix4f tri-2)
519 (.invert (triangle->matrix4f tri-1))))
521 (defn point->vector2f [[u v]]
522 (Vector2f. u v))
524 (defn vector2f->vector3f [v]
525 (Vector3f. (.getX v) (.getY v) 0))
527 (defn map-triangle [f #^Triangle tri]
528 (Triangle.
529 (f 0 (.get1 tri))
530 (f 1 (.get2 tri))
531 (f 2 (.get3 tri))))
533 (defn points->triangle
534 "Convert a list of points into a triangle."
535 [points]
536 (apply #(Triangle. %1 %2 %3)
537 (map (fn [point]
538 (let [point (vec point)]
539 (Vector3f. (get point 0 0)
540 (get point 1 0)
541 (get point 2 0))))
542 (take 3 points))))
544 (defn convex-bounds
545 "Dimensions of the smallest integer bounding square of the list of
546 2D verticies in the form: [x y width height]."
547 [uv-verts]
548 (let [xs (map first uv-verts)
549 ys (map second uv-verts)
550 x0 (Math/floor (apply min xs))
551 y0 (Math/floor (apply min ys))
552 x1 (Math/ceil (apply max xs))
553 y1 (Math/ceil (apply max ys))]
554 [x0 y0 (- x1 x0) (- y1 y0)]))
556 (defn sensors-in-triangle
557 "Find the locations of the touch sensors within a triangle in both
558 UV and gemoetry relative coordinates."
559 [image mesh tri-index]
560 (let [width (.getWidth image)
561 height (.getHeight image)
562 UV-vertex-coords (triangle-UV-coord mesh width height tri-index)
563 bounds (convex-bounds UV-vertex-coords)
565 cutout-triangle (points->triangle UV-vertex-coords)
566 UV-sensor-coords
567 (filter (comp (partial inside-triangle? cutout-triangle)
568 (fn [[u v]] (Vector3f. u v 0)))
569 (white-coordinates image bounds))
570 UV->geometry (triangle-transformation
571 cutout-triangle
572 (triangle mesh tri-index))
573 geometry-sensor-coords
574 (map (fn [[u v]] (.mult UV->geometry (Vector3f. u v 0)))
575 UV-sensor-coords)]
576 {:UV UV-sensor-coords :geometry geometry-sensor-coords}))
578 (defn-memo locate-feelers
579 "Search the geometry's tactile UV image for touch sensors, returning
580 their positions in geometry-relative coordinates."
581 [#^Geometry geo]
582 (let [mesh (.getMesh geo)
583 num-triangles (.getTriangleCount mesh)]
584 (if-let [image (tactile-sensor-image geo)]
585 (map
586 (partial sensors-in-triangle image mesh)
587 (range num-triangles))
588 (repeat (.getTriangleCount mesh) {:UV nil :geometry nil}))))
590 (use 'clojure.contrib.def)
592 (defn-memo touch-topology [#^Gemoetry geo]
593 (vec (collapse (reduce concat (map :UV (locate-feelers geo))))))
595 (defn-memo feeler-coordinates [#^Geometry geo]
596 (vec (map :geometry (locate-feelers geo))))
598 (defn enable-touch [#^Geometry geo]
599 (let [feeler-coords (feeler-coordinates geo)
600 tris (triangles geo)
601 limit 0.1
602 ;;results (CollisionResults.)
603 ]
604 (if (empty? (touch-topology geo))
605 nil
606 (fn [node]
607 (let [sensor-origins
608 (map
609 #(map (partial local-to-world geo) %)
610 feeler-coords)
611 triangle-normals
612 (map (partial get-ray-direction geo)
613 tris)
614 rays
615 (flatten
616 (map (fn [origins norm]
617 (map #(doto (Ray. % norm)
618 (.setLimit limit)) origins))
619 sensor-origins triangle-normals))]
620 (vector
621 (touch-topology geo)
622 (vec
623 (for [ray rays]
624 (do
625 (let [results (CollisionResults.)]
626 (.collideWith node ray results)
627 (let [touch-objects
628 (set
629 (filter #(not (= geo %))
630 (map #(.getGeometry %) results)))]
631 (if (> (count touch-objects) 0)
632 1 0))))))))))))
634 (defn touch [#^Node pieces]
635 (filter (comp not nil?)
636 (map enable-touch
637 (filter #(isa? (class %) Geometry)
638 (node-seq pieces)))))
641 ;; human eye transmits 62kb/s to brain Bandwidth is 8.75 Mb/s
642 ;; http://en.wikipedia.org/wiki/Retina
644 (defn test-eye []
645 (.getChild (worm-model) "worm-11"))
648 (defn retina-sensor-image
649 "Return a map of pixel selection functions to BufferedImages
650 describing the distribution of light-sensitive components on this
651 geometry's surface. Each function creates an integer from the rgb
652 values found in the pixel. :red, :green, :blue, :gray are already
653 defined as extracting the red green blue and average components
654 respectively."
655 [#^Geometry eye]
656 (if-let [eye-map (meta-data eye "eye")]
657 (map-vals
658 #(ImageToAwt/convert
659 (.getImage (.loadTexture (asset-manager) %))
660 false false 0)
661 (read-string
662 eye-map))))
665 (defn enable-vision
667 ;; need to create a camera based on uv image,
668 ;; update this camera every frame based on the position of this
669 ;; geometry. (maybe can get cam to follow the object)
671 ;; use a stack for the continuation to grab the image.
674 [#^Geometry eye]
677 ;; Here's how vision will work.
679 ;; Make the continuation in scene-processor take FrameBuffer,
680 ;; byte-buffer, BufferedImage already sized to the correct
681 ;; dimensions. the continuation will decide wether to "mix" them
682 ;; into the BufferedImage, lazily ignore them, or mix them halfway
683 ;; and call c/graphics card routines.
685 ;; (vision creature) will take an optional :skip argument which will
686 ;; inform the continuations in scene processor to skip the given
687 ;; number of cycles; 0 means that no cycles will be skipped.
689 ;; (vision creature) will return [init-functions sensor-functions].
690 ;; The init-functions are each single-arg functions that take the
691 ;; world and register the cameras and must each be called before the
692 ;; corresponding sensor-functions. Each init-function returns the
693 ;; viewport for that eye which can be manipulated, saved, etc. Each
694 ;; sensor-function is a thunk and will return data in the same
695 ;; format as the tactile-sensor functions; the structure is
696 ;; [topology, sensor-data]. Internally, these sensor-functions
697 ;; maintain a reference to sensor-data which is periodically updated
698 ;; by the continuation function established by its init-function.
699 ;; They can be queried every cycle, but their information may not
700 ;; necessairly be different every cycle.
702 ;; Each eye in the creature in blender will work the same way as
703 ;; joints -- a one dimensional object with no geometry whose local
704 ;; coordinate system determines the orientation of the resulting
705 ;; eye. All eyes will have a parent named "eyes" just as all joints
706 ;; have a parent named "joints". The resulting camera will be a
707 ;; ChaseCamera or a CameraNode bound to the geo that is closest to
708 ;; the eye marker. The eye marker will contain the metadata for the
709 ;; eye, and will be moved by it's bound geometry. The dimensions of
710 ;; the eye's camera are equal to the dimensions of the eye's "UV"
711 ;; map.
714 )
716 (defn debug-window
717 "creates function that offers a debug view of sensor data"
718 []
719 (let [vi (view-image)]
720 (fn
721 [[coords sensor-data]]
722 (let [image (points->image coords)]
723 (dorun
724 (for [i (range (count coords))]
725 (.setRGB image ((coords i) 0) ((coords i) 1)
726 ({0 -16777216
727 1 -1} (sensor-data i)))))
728 (vi image)))))
731 ;;(defn test-touch [world creature]
734 (defn test-creature [thing]
735 (let [x-axis
736 (box 1 0.01 0.01 :physical? false :color ColorRGBA/Red)
737 y-axis
738 (box 0.01 1 0.01 :physical? false :color ColorRGBA/Green)
739 z-axis
740 (box 0.01 0.01 1 :physical? false :color ColorRGBA/Blue)
741 creature (blender-creature thing)
742 touch-nerves (touch creature)
743 touch-debug-windows (map (fn [_] (debug-window)) touch-nerves)
744 ]
745 (world
746 (nodify [creature
747 (box 10 2 10 :position (Vector3f. 0 -9 0)
748 :color ColorRGBA/Gray :mass 0)
749 x-axis y-axis z-axis
750 ])
751 standard-debug-controls
752 (fn [world]
753 (light-up-everything world)
754 (enable-debug world)
755 ;;(com.aurellem.capture.Capture/captureVideo
756 ;; world (file-str "/home/r/proj/ai-videos/hand"))
757 ;;(.setTimer world (RatchetTimer. 60))
758 ;;(speed-up world)
759 ;;(set-gravity world (Vector3f. 0 0 0))
760 )
761 (fn [world tpf]
762 ;;(dorun
763 ;; (map #(%1 %2) touch-nerves (repeat (.getRootNode world))))
765 (dorun
766 (map #(%1 (%2 (.getRootNode world)))
767 touch-debug-windows touch-nerves)
768 )
770 )
771 ;;(let [timer (atom 0)]
772 ;; (fn [_ _]
773 ;; (swap! timer inc)
774 ;; (if (= (rem @timer 60) 0)
775 ;; (println-repl (float (/ @timer 60))))))
776 )))
786 ;;; experiments in collisions
790 (defn collision-test []
791 (let [b-radius 1
792 b-position (Vector3f. 0 0 0)
793 obj-b (box 1 1 1 :color ColorRGBA/Blue
794 :position b-position
795 :mass 0)
796 node (nodify [obj-b])
797 bounds-b
798 (doto (Picture.)
799 (.setHeight 50)
800 (.setWidth 50)
801 (.setImage (asset-manager)
802 "Models/creature1/hand.png"
803 false
804 ))
806 ;;(Ray. (Vector3f. 0 -5 0) (.normalize (Vector3f. 0 1 0)))
808 collisions
809 (let [cr (CollisionResults.)]
810 (.collideWith node bounds-b cr)
811 (println (map #(.getContactPoint %) cr))
812 cr)
814 ;;collision-points
815 ;;(map #(sphere 0.1 :position (.getContactPoint %))
816 ;; collisions)
818 ;;node (nodify (conj collision-points obj-b))
820 sim
821 (world node
822 {"key-space"
823 (fn [_ value]
824 (if value
825 (let [cr (CollisionResults.)]
826 (.collideWith node bounds-b cr)
827 (println-repl (map #(.getContactPoint %) cr))
828 cr)))}
829 no-op
830 no-op)
832 ]
833 sim
835 ))
840 #+end_src
842 #+results: body-1
843 : #'cortex.silly/test-creature
846 * COMMENT purgatory
847 #+begin_src clojure
848 (defn bullet-trans []
849 (let [obj-a (sphere 0.5 :color ColorRGBA/Red
850 :position (Vector3f. -10 5 0))
851 obj-b (sphere 0.5 :color ColorRGBA/Blue
852 :position (Vector3f. -10 -5 0)
853 :mass 0)
854 control-a (.getControl obj-a RigidBodyControl)
855 control-b (.getControl obj-b RigidBodyControl)
856 swivel
857 (.toRotationMatrix
858 (doto (Quaternion.)
859 (.fromAngleAxis (/ Math/PI 2)
860 Vector3f/UNIT_X)))]
861 (doto
862 (ConeJoint.
863 control-a control-b
864 (Vector3f. 0 5 0)
865 (Vector3f. 0 -5 0)
866 swivel swivel)
867 (.setLimit (* 0.6 (/ Math/PI 4))
868 (/ Math/PI 4)
869 (* Math/PI 0.8)))
870 (world (nodify
871 [obj-a obj-b])
872 standard-debug-controls
873 enable-debug
874 no-op)))
877 (defn bullet-trans* []
878 (let [obj-a (box 1.5 0.5 0.5 :color ColorRGBA/Red
879 :position (Vector3f. 5 0 0)
880 :mass 90)
881 obj-b (sphere 0.5 :color ColorRGBA/Blue
882 :position (Vector3f. -5 0 0)
883 :mass 0)
884 control-a (.getControl obj-a RigidBodyControl)
885 control-b (.getControl obj-b RigidBodyControl)
886 move-up? (atom nil)
887 move-down? (atom nil)
888 move-left? (atom nil)
889 move-right? (atom nil)
890 roll-left? (atom nil)
891 roll-right? (atom nil)
892 force 100
893 swivel
894 (.toRotationMatrix
895 (doto (Quaternion.)
896 (.fromAngleAxis (/ Math/PI 2)
897 Vector3f/UNIT_X)))
898 x-move
899 (doto (Matrix3f.)
900 (.fromStartEndVectors Vector3f/UNIT_X
901 (.normalize (Vector3f. 1 1 0))))
903 timer (atom 0)]
904 (doto
905 (ConeJoint.
906 control-a control-b
907 (Vector3f. -8 0 0)
908 (Vector3f. 2 0 0)
909 ;;swivel swivel
910 ;;Matrix3f/IDENTITY Matrix3f/IDENTITY
911 x-move Matrix3f/IDENTITY
912 )
913 (.setCollisionBetweenLinkedBodys false)
914 (.setLimit (* 1 (/ Math/PI 4)) ;; twist
915 (* 1 (/ Math/PI 4)) ;; swing span in X-Y plane
916 (* 0 (/ Math/PI 4)))) ;; swing span in Y-Z plane
917 (world (nodify
918 [obj-a obj-b])
919 (merge standard-debug-controls
920 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
921 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
922 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
923 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
924 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
925 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
927 (fn [world]
928 (enable-debug world)
929 (set-gravity world Vector3f/ZERO)
930 )
932 (fn [world _]
934 (if @move-up?
935 (.applyForce control-a
936 (Vector3f. force 0 0)
937 (Vector3f. 0 0 0)))
938 (if @move-down?
939 (.applyForce control-a
940 (Vector3f. (- force) 0 0)
941 (Vector3f. 0 0 0)))
942 (if @move-left?
943 (.applyForce control-a
944 (Vector3f. 0 force 0)
945 (Vector3f. 0 0 0)))
946 (if @move-right?
947 (.applyForce control-a
948 (Vector3f. 0 (- force) 0)
949 (Vector3f. 0 0 0)))
951 (if @roll-left?
952 (.applyForce control-a
953 (Vector3f. 0 0 force)
954 (Vector3f. 0 0 0)))
955 (if @roll-right?
956 (.applyForce control-a
957 (Vector3f. 0 0 (- force))
958 (Vector3f. 0 0 0)))
960 (if (zero? (rem (swap! timer inc) 100))
961 (.attachChild
962 (.getRootNode world)
963 (sphere 0.05 :color ColorRGBA/Yellow
964 :physical? false :position
965 (.getWorldTranslation obj-a)))))
966 )
967 ))
969 (defn transform-trianglesdsd
970 "Transform that converts each vertex in the first triangle
971 into the corresponding vertex in the second triangle."
972 [#^Triangle tri-1 #^Triangle tri-2]
973 (let [in [(.get1 tri-1)
974 (.get2 tri-1)
975 (.get3 tri-1)]
976 out [(.get1 tri-2)
977 (.get2 tri-2)
978 (.get3 tri-2)]]
979 (let [translate (doto (Matrix4f.) (.setTranslation (.negate (in 0))))
980 in* [(.mult translate (in 0))
981 (.mult translate (in 1))
982 (.mult translate (in 2))]
983 final-translation
984 (doto (Matrix4f.)
985 (.setTranslation (out 1)))
987 rotate-1
988 (doto (Matrix3f.)
989 (.fromStartEndVectors
990 (.normalize
991 (.subtract
992 (in* 1) (in* 0)))
993 (.normalize
994 (.subtract
995 (out 1) (out 0)))))
996 in** [(.mult rotate-1 (in* 0))
997 (.mult rotate-1 (in* 1))
998 (.mult rotate-1 (in* 2))]
999 scale-factor-1
1000 (.mult
1001 (.normalize
1002 (.subtract
1003 (out 1)
1004 (out 0)))
1005 (/ (.length
1006 (.subtract (out 1)
1007 (out 0)))
1008 (.length
1009 (.subtract (in** 1)
1010 (in** 0)))))
1011 scale-1 (doto (Matrix4f.) (.setScale scale-factor-1))
1012 in*** [(.mult scale-1 (in** 0))
1013 (.mult scale-1 (in** 1))
1014 (.mult scale-1 (in** 2))]
1022 (dorun (map println in))
1023 (println)
1024 (dorun (map println in*))
1025 (println)
1026 (dorun (map println in**))
1027 (println)
1028 (dorun (map println in***))
1029 (println)
1031 ))))
1034 (defn world-setup [joint]
1035 (let [joint-position (Vector3f. 0 0 0)
1036 joint-rotation
1037 (.toRotationMatrix
1038 (.mult
1039 (doto (Quaternion.)
1040 (.fromAngleAxis
1041 (* 1 (/ Math/PI 4))
1042 (Vector3f. -1 0 0)))
1043 (doto (Quaternion.)
1044 (.fromAngleAxis
1045 (* 1 (/ Math/PI 2))
1046 (Vector3f. 0 0 1)))))
1047 top-position (.mult joint-rotation (Vector3f. 8 0 0))
1049 origin (doto
1050 (sphere 0.1 :physical? false :color ColorRGBA/Cyan
1051 :position top-position))
1052 top (doto
1053 (sphere 0.1 :physical? false :color ColorRGBA/Yellow
1054 :position top-position)
1056 (.addControl
1057 (RigidBodyControl.
1058 (CapsuleCollisionShape. 0.5 1.5 1) (float 20))))
1059 bottom (doto
1060 (sphere 0.1 :physical? false :color ColorRGBA/DarkGray
1061 :position (Vector3f. 0 0 0))
1062 (.addControl
1063 (RigidBodyControl.
1064 (CapsuleCollisionShape. 0.5 1.5 1) (float 0))))
1065 table (box 10 2 10 :position (Vector3f. 0 -20 0)
1066 :color ColorRGBA/Gray :mass 0)
1067 a (.getControl top RigidBodyControl)
1068 b (.getControl bottom RigidBodyControl)]
1070 (cond
1071 (= joint :cone)
1073 (doto (ConeJoint.
1074 a b
1075 (world-to-local top joint-position)
1076 (world-to-local bottom joint-position)
1077 joint-rotation
1078 joint-rotation
1082 (.setLimit (* (/ 10) Math/PI)
1083 (* (/ 4) Math/PI)
1084 0)))
1085 [origin top bottom table]))
1087 (defn test-joint [joint]
1088 (let [[origin top bottom floor] (world-setup joint)
1089 control (.getControl top RigidBodyControl)
1090 move-up? (atom false)
1091 move-down? (atom false)
1092 move-left? (atom false)
1093 move-right? (atom false)
1094 roll-left? (atom false)
1095 roll-right? (atom false)
1096 timer (atom 0)]
1098 (world
1099 (nodify [top bottom floor origin])
1100 (merge standard-debug-controls
1101 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
1102 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
1103 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
1104 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
1105 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
1106 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
1108 (fn [world]
1109 (light-up-everything world)
1110 (enable-debug world)
1111 (set-gravity world (Vector3f. 0 0 0))
1114 (fn [world _]
1115 (if (zero? (rem (swap! timer inc) 100))
1116 (do
1117 ;; (println-repl @timer)
1118 (.attachChild (.getRootNode world)
1119 (sphere 0.05 :color ColorRGBA/Yellow
1120 :position (.getWorldTranslation top)
1121 :physical? false))
1122 (.attachChild (.getRootNode world)
1123 (sphere 0.05 :color ColorRGBA/LightGray
1124 :position (.getWorldTranslation bottom)
1125 :physical? false))))
1127 (if @move-up?
1128 (.applyTorque control
1129 (.mult (.getPhysicsRotation control)
1130 (Vector3f. 0 0 10))))
1131 (if @move-down?
1132 (.applyTorque control
1133 (.mult (.getPhysicsRotation control)
1134 (Vector3f. 0 0 -10))))
1135 (if @move-left?
1136 (.applyTorque control
1137 (.mult (.getPhysicsRotation control)
1138 (Vector3f. 0 10 0))))
1139 (if @move-right?
1140 (.applyTorque control
1141 (.mult (.getPhysicsRotation control)
1142 (Vector3f. 0 -10 0))))
1143 (if @roll-left?
1144 (.applyTorque control
1145 (.mult (.getPhysicsRotation control)
1146 (Vector3f. -1 0 0))))
1147 (if @roll-right?
1148 (.applyTorque control
1149 (.mult (.getPhysicsRotation control)
1150 (Vector3f. 1 0 0))))))))
1154 (defprotocol Frame
1155 (frame [this]))
1157 (extend-type BufferedImage
1158 Frame
1159 (frame [image]
1160 (merge
1161 (apply
1162 hash-map
1163 (interleave
1164 (doall (for [x (range (.getWidth image)) y (range (.getHeight image))]
1165 (vector x y)))
1166 (doall (for [x (range (.getWidth image)) y (range (.getHeight image))]
1167 (let [data (.getRGB image x y)]
1168 (hash-map :r (bit-shift-right (bit-and 0xff0000 data) 16)
1169 :g (bit-shift-right (bit-and 0x00ff00 data) 8)
1170 :b (bit-and 0x0000ff data)))))))
1171 {:width (.getWidth image) :height (.getHeight image)})))
1174 (extend-type ImagePlus
1175 Frame
1176 (frame [image+]
1177 (frame (.getBufferedImage image+))))
1180 #+end_src
1183 * COMMENT generate source
1184 #+begin_src clojure :tangle ../src/cortex/silly.clj
1185 <<body-1>>
1186 #+end_src