view org/test-creature.org @ 115:247860e25536

added eye to creature in blender
author Robert McIntyre <rlm@mit.edu>
date Thu, 19 Jan 2012 22:26:16 -0700
parents 9d0fe7f54e14
children 947bef5d6670
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 average [coll]
94 (/ (reduce + coll) (count coll)))
96 (defn collapse-1d
97 "One dimensional analogue of collapse"
98 [center line]
99 (let [length (count line)
100 num-above (count (filter (partial < center) line))
101 num-below (- length num-above)]
102 (range (- center num-below)
103 (+ center num-above))))
105 (defn collapse
106 "Take a set of pairs of integers and collapse them into a
107 contigous bitmap."
108 [points]
109 (if (empty? points) []
110 (let
111 [num-points (count points)
112 center (vector
113 (int (average (map first points)))
114 (int (average (map first points))))
115 flattened
116 (reduce
117 concat
118 (map
119 (fn [column]
120 (map vector
121 (map first column)
122 (collapse-1d (second center)
123 (map second column))))
124 (partition-by first (sort-by first points))))
125 squeezed
126 (reduce
127 concat
128 (map
129 (fn [row]
130 (map vector
131 (collapse-1d (first center)
132 (map first row))
133 (map second row)))
134 (partition-by second (sort-by second flattened))))
135 relocate
136 (let [min-x (apply min (map first squeezed))
137 min-y (apply min (map second squeezed))]
138 (map (fn [[x y]]
139 [(- x min-x)
140 (- y min-y)])
141 squeezed))]
142 relocate)))
144 (defn load-bullet []
145 (let [sim (world (Node.) {} no-op no-op)]
146 (doto sim
147 (.enqueue
148 (fn []
149 (.stop sim)))
150 (.start))))
152 (defn load-blender-model
153 "Load a .blend file using an asset folder relative path."
154 [^String model]
155 (.loadModel
156 (doto (asset-manager)
157 (.registerLoader BlenderModelLoader (into-array String ["blend"])))
158 model))
160 (defn meta-data [blender-node key]
161 (if-let [data (.getUserData blender-node "properties")]
162 (.findValue data key)
163 nil))
165 (defn blender-to-jme
166 "Convert from Blender coordinates to JME coordinates"
167 [#^Vector3f in]
168 (Vector3f. (.getX in)
169 (.getZ in)
170 (- (.getY in))))
172 (defn jme-to-blender
173 "Convert from JME coordinates to Blender coordinates"
174 [#^Vector3f in]
175 (Vector3f. (.getX in)
176 (- (.getZ in))
177 (.getY in)))
179 (defn joint-targets
180 "Return the two closest two objects to the joint object, ordered
181 from bottom to top according to the joint's rotation."
182 [#^Node parts #^Node joint]
183 ;;(println (meta-data joint "joint"))
184 (.getWorldRotation joint)
185 (loop [radius (float 0.01)]
186 (let [results (CollisionResults.)]
187 (.collideWith
188 parts
189 (BoundingBox. (.getWorldTranslation joint)
190 radius radius radius)
191 results)
192 (let [targets
193 (distinct
194 (map #(.getGeometry %) results))]
195 (if (>= (count targets) 2)
196 (sort-by
197 #(let [v
198 (jme-to-blender
199 (.mult
200 (.inverse (.getWorldRotation joint))
201 (.subtract (.getWorldTranslation %)
202 (.getWorldTranslation joint))))]
203 (println-repl (.getName %) ":" v)
204 (.dot (Vector3f. 1 1 1)
205 v))
206 (take 2 targets))
207 (recur (float (* radius 2))))))))
209 (defn world-to-local
210 "Convert the world coordinates into coordinates relative to the
211 object (i.e. local coordinates), taking into account the rotation
212 of object."
213 [#^Spatial object world-coordinate]
214 (let [out (Vector3f.)]
215 (.worldToLocal object world-coordinate out) out))
217 (defn local-to-world
218 "Convert the local coordinates into coordinates into world relative
219 coordinates"
220 [#^Spatial object local-coordinate]
221 (let [world-coordinate (Vector3f.)]
222 (.localToWorld object local-coordinate world-coordinate)
223 world-coordinate))
225 (defmulti joint-dispatch
226 "Translate blender pseudo-joints into real JME joints."
227 (fn [constraints & _]
228 (:type constraints)))
230 (defmethod joint-dispatch :point
231 [constraints control-a control-b pivot-a pivot-b rotation]
232 (println-repl "creating POINT2POINT joint")
233 (Point2PointJoint.
234 control-a
235 control-b
236 pivot-a
237 pivot-b))
239 (defmethod joint-dispatch :hinge
240 [constraints control-a control-b pivot-a pivot-b rotation]
241 (println-repl "creating HINGE joint")
242 (let [axis
243 (if-let
244 [axis (:axis constraints)]
245 axis
246 Vector3f/UNIT_X)
247 [limit-1 limit-2] (:limit constraints)
248 hinge-axis
249 (.mult
250 rotation
251 (blender-to-jme axis))]
252 (doto
253 (HingeJoint.
254 control-a
255 control-b
256 pivot-a
257 pivot-b
258 hinge-axis
259 hinge-axis)
260 (.setLimit limit-1 limit-2))))
262 (defmethod joint-dispatch :cone
263 [constraints control-a control-b pivot-a pivot-b rotation]
264 (let [limit-xz (:limit-xz constraints)
265 limit-xy (:limit-xy constraints)
266 twist (:twist constraints)]
268 (println-repl "creating CONE joint")
269 (println-repl rotation)
270 (println-repl
271 "UNIT_X --> " (.mult rotation (Vector3f. 1 0 0)))
272 (println-repl
273 "UNIT_Y --> " (.mult rotation (Vector3f. 0 1 0)))
274 (println-repl
275 "UNIT_Z --> " (.mult rotation (Vector3f. 0 0 1)))
276 (doto
277 (ConeJoint.
278 control-a
279 control-b
280 pivot-a
281 pivot-b
282 rotation
283 rotation)
284 (.setLimit (float limit-xz)
285 (float limit-xy)
286 (float twist)))))
288 (defn connect
289 "here are some examples:
290 {:type :point}
291 {:type :hinge :limit [0 (/ Math/PI 2)] :axis (Vector3f. 0 1 0)}
292 (:axis defaults to (Vector3f. 1 0 0) if not provided for hinge joints)
294 {:type :cone :limit-xz 0]
295 :limit-xy 0]
296 :twist 0]} (use XZY rotation mode in blender!)"
297 [#^Node obj-a #^Node obj-b #^Node joint]
298 (let [control-a (.getControl obj-a RigidBodyControl)
299 control-b (.getControl obj-b RigidBodyControl)
300 joint-center (.getWorldTranslation joint)
301 joint-rotation (.toRotationMatrix (.getWorldRotation joint))
302 pivot-a (world-to-local obj-a joint-center)
303 pivot-b (world-to-local obj-b joint-center)]
305 (if-let [constraints
306 (map-vals
307 eval
308 (read-string
309 (meta-data joint "joint")))]
310 ;; A side-effect of creating a joint registers
311 ;; it with both physics objects which in turn
312 ;; will register the joint with the physics system
313 ;; when the simulation is started.
314 (do
315 (println-repl "creating joint between"
316 (.getName obj-a) "and" (.getName obj-b))
317 (joint-dispatch constraints
318 control-a control-b
319 pivot-a pivot-b
320 joint-rotation))
321 (println-repl "could not find joint meta-data!"))))
323 (defn assemble-creature [#^Node pieces joints]
324 (dorun
325 (map
326 (fn [geom]
327 (let [physics-control
328 (RigidBodyControl.
329 (HullCollisionShape.
330 (.getMesh geom))
331 (if-let [mass (meta-data geom "mass")]
332 (do
333 (println-repl
334 "setting" (.getName geom) "mass to" (float mass))
335 (float mass))
336 (float 1)))]
338 (.addControl geom physics-control)))
339 (filter #(isa? (class %) Geometry )
340 (node-seq pieces))))
341 (dorun
342 (map
343 (fn [joint]
344 (let [[obj-a obj-b]
345 (joint-targets pieces joint)]
346 (connect obj-a obj-b joint)))
347 joints))
348 pieces)
350 (defn blender-creature [blender-path]
351 (let [model (load-blender-model blender-path)
352 joints
353 (if-let [joint-node (.getChild model "joints")]
354 (seq (.getChildren joint-node))
355 (do (println-repl "could not find joints node")
356 []))]
357 (assemble-creature model joints)))
359 (def hand "Models/creature1/one.blend")
361 (def worm "Models/creature1/try-again.blend")
363 (def touch "Models/creature1/touch.blend")
365 (defn worm-model [] (load-blender-model worm))
367 (defn x-ray [#^ColorRGBA color]
368 (doto (Material. (asset-manager)
369 "Common/MatDefs/Misc/Unshaded.j3md")
370 (.setColor "Color" color)
371 (-> (.getAdditionalRenderState)
372 (.setDepthTest false))))
374 (defn colorful []
375 (.getChild (worm-model) "worm-21"))
377 (import jme3tools.converters.ImageToAwt)
379 (import ij.ImagePlus)
381 ;; Every Mesh has many triangles, each with its own index.
382 ;; Every vertex has its own index as well.
384 (defn tactile-sensor-image
385 "Return the touch-sensor distribution image in BufferedImage format,
386 or nil if it does not exist."
387 [#^Geometry obj]
388 (if-let [image-path (meta-data obj "touch")]
389 (ImageToAwt/convert
390 (.getImage
391 (.loadTexture
392 (asset-manager)
393 image-path))
394 false false 0)))
396 (import ij.process.ImageProcessor)
397 (import java.awt.image.BufferedImage)
399 (def white -1)
401 (defn filter-pixels
402 "List the coordinates of all pixels matching pred, within the bounds
403 provided. Bounds -> [x0 y0 width height]"
404 {:author "Dylan Holmes"}
405 ([pred #^BufferedImage image]
406 (filter-pixels pred image [0 0 (.getWidth image) (.getHeight image)]))
407 ([pred #^BufferedImage image [x0 y0 width height]]
408 ((fn accumulate [x y matches]
409 (cond
410 (>= y (+ height y0)) matches
411 (>= x (+ width x0)) (recur 0 (inc y) matches)
412 (pred (.getRGB image x y))
413 (recur (inc x) y (conj matches [x y]))
414 :else (recur (inc x) y matches)))
415 x0 y0 [])))
417 (defn white-coordinates
418 "Coordinates of all the white pixels in a subset of the image."
419 ([#^BufferedImage image bounds]
420 (filter-pixels #(= % white) image bounds))
421 ([#^BufferedImage image]
422 (filter-pixels #(= % white) image)))
424 (defn triangle
425 "Get the triangle specified by triangle-index from the mesh within
426 bounds."
427 [#^Mesh mesh triangle-index]
428 (let [scratch (Triangle.)]
429 (.getTriangle mesh triangle-index scratch)
430 scratch))
432 (defn triangle-vertex-indices
433 "Get the triangle vertex indices of a given triangle from a given
434 mesh."
435 [#^Mesh mesh triangle-index]
436 (let [indices (int-array 3)]
437 (.getTriangle mesh triangle-index indices)
438 (vec indices)))
440 (defn vertex-UV-coord
441 "Get the uv-coordinates of the vertex named by vertex-index"
442 [#^Mesh mesh vertex-index]
443 (let [UV-buffer
444 (.getData
445 (.getBuffer
446 mesh
447 VertexBuffer$Type/TexCoord))]
448 [(.get UV-buffer (* vertex-index 2))
449 (.get UV-buffer (+ 1 (* vertex-index 2)))]))
451 (defn triangle-UV-coord
452 "Get the uv-cooridnates of the triangle's verticies."
453 [#^Mesh mesh width height triangle-index]
454 (map (fn [[u v]] (vector (* width u) (* height v)))
455 (map (partial vertex-UV-coord mesh)
456 (triangle-vertex-indices mesh triangle-index))))
458 (defn same-side?
459 "Given the points p1 and p2 and the reference point ref, is point p
460 on the same side of the line that goes through p1 and p2 as ref is?"
461 [p1 p2 ref p]
462 (<=
463 0
464 (.dot
465 (.cross (.subtract p2 p1) (.subtract p p1))
466 (.cross (.subtract p2 p1) (.subtract ref p1)))))
468 (defn triangle-seq [#^Triangle tri]
469 [(.get1 tri) (.get2 tri) (.get3 tri)])
471 (defn vector3f-seq [#^Vector3f v]
472 [(.getX v) (.getY v) (.getZ v)])
474 (defn inside-triangle?
475 "Is the point inside the triangle?"
476 {:author "Dylan Holmes"}
477 [#^Triangle tri #^Vector3f p]
478 (let [[vert-1 vert-2 vert-3] (triangle-seq tri)]
479 (and
480 (same-side? vert-1 vert-2 vert-3 p)
481 (same-side? vert-2 vert-3 vert-1 p)
482 (same-side? vert-3 vert-1 vert-2 p))))
484 (defn triangle->matrix4f
485 "Converts the triangle into a 4x4 matrix: The first three columns
486 contain the vertices of the triangle; the last contains the unit
487 normal of the triangle. The bottom row is filled with 1s."
488 [#^Triangle t]
489 (let [mat (Matrix4f.)
490 [vert-1 vert-2 vert-3]
491 ((comp vec map) #(.get t %) (range 3))
492 unit-normal (do (.calculateNormal t)(.getNormal t))
493 vertices [vert-1 vert-2 vert-3 unit-normal]]
494 (dorun
495 (for [row (range 4) col (range 3)]
496 (do
497 (.set mat col row (.get (vertices row)col))
498 (.set mat 3 row 1))))
499 mat))
501 (defn triangle-transformation
502 "Returns the affine transformation that converts each vertex in the
503 first triangle into the corresponding vertex in the second
504 triangle."
505 [#^Triangle tri-1 #^Triangle tri-2]
506 (.mult
507 (triangle->matrix4f tri-2)
508 (.invert (triangle->matrix4f tri-1))))
510 (defn point->vector2f [[u v]]
511 (Vector2f. u v))
513 (defn vector2f->vector3f [v]
514 (Vector3f. (.getX v) (.getY v) 0))
516 (defn map-triangle [f #^Triangle tri]
517 (Triangle.
518 (f 0 (.get1 tri))
519 (f 1 (.get2 tri))
520 (f 2 (.get3 tri))))
522 (defn points->triangle
523 "Convert a list of points into a triangle."
524 [points]
525 (apply #(Triangle. %1 %2 %3)
526 (map (fn [point]
527 (let [point (vec point)]
528 (Vector3f. (get point 0 0)
529 (get point 1 0)
530 (get point 2 0))))
531 (take 3 points))))
533 (defn convex-bounds
534 "Dimensions of the smallest integer bounding square of the list of
535 2D verticies in the form: [x y width height]."
536 [uv-verts]
537 (let [xs (map first uv-verts)
538 ys (map second uv-verts)
539 x0 (Math/floor (apply min xs))
540 y0 (Math/floor (apply min ys))
541 x1 (Math/ceil (apply max xs))
542 y1 (Math/ceil (apply max ys))]
543 [x0 y0 (- x1 x0) (- y1 y0)]))
545 (defn sensors-in-triangle
546 "Find the locations of the touch sensors within a triangle in both
547 UV and gemoetry relative coordinates."
548 [image mesh tri-index]
549 (let [width (.getWidth image)
550 height (.getHeight image)
551 UV-vertex-coords (triangle-UV-coord mesh width height tri-index)
552 bounds (convex-bounds UV-vertex-coords)
554 cutout-triangle (points->triangle UV-vertex-coords)
555 UV-sensor-coords
556 (filter (comp (partial inside-triangle? cutout-triangle)
557 (fn [[u v]] (Vector3f. u v 0)))
558 (white-coordinates image bounds))
559 UV->geometry (triangle-transformation
560 cutout-triangle
561 (triangle mesh tri-index))
562 geometry-sensor-coords
563 (map (fn [[u v]] (.mult UV->geometry (Vector3f. u v 0)))
564 UV-sensor-coords)]
565 {:UV UV-sensor-coords :geometry geometry-sensor-coords}))
567 (defn-memo locate-feelers
568 "Search the geometry's tactile UV image for touch sensors, returning
569 their positions in geometry-relative coordinates."
570 [#^Geometry geo]
571 (let [mesh (.getMesh geo)
572 num-triangles (.getTriangleCount mesh)]
573 (if-let [image (tactile-sensor-image geo)]
574 (map
575 (partial sensors-in-triangle image mesh)
576 (range num-triangles))
577 (repeat (.getTriangleCount mesh) {:UV nil :geometry nil}))))
579 (use 'clojure.contrib.def)
581 (defn-memo touch-topology [#^Gemoetry geo]
582 (vec (collapse (reduce concat (map :UV (locate-feelers geo))))))
584 (defn-memo feeler-coordinates [#^Geometry geo]
585 (vec (map :geometry (locate-feelers geo))))
587 (defn enable-touch [#^Geometry geo]
588 (let [feeler-coords (feeler-coordinates geo)
589 tris (triangles geo)
590 limit 0.1
591 ;;results (CollisionResults.)
592 ]
593 (if (empty? (touch-topology geo))
594 nil
595 (fn [node]
596 (let [sensor-origins
597 (map
598 #(map (partial local-to-world geo) %)
599 feeler-coords)
600 triangle-normals
601 (map (partial get-ray-direction geo)
602 tris)
603 rays
604 (flatten
605 (map (fn [origins norm]
606 (map #(doto (Ray. % norm)
607 (.setLimit limit)) origins))
608 sensor-origins triangle-normals))]
609 (vector
610 (touch-topology geo)
611 (vec
612 (for [ray rays]
613 (do
614 (let [results (CollisionResults.)]
615 (.collideWith node ray results)
616 (let [touch-objects
617 (set
618 (filter #(not (= geo %))
619 (map #(.getGeometry %) results)))]
620 (if (> (count touch-objects) 0)
621 1 0))))))))))))
623 (defn touch [#^Node pieces]
624 (filter (comp not nil?)
625 (map enable-touch
626 (filter #(isa? (class %) Geometry)
627 (node-seq pieces)))))
630 ;; human eye transmits 62kb/s to brain Bandwidth is 8.75 Mb/s
631 ;; http://en.wikipedia.org/wiki/Retina
633 (defn test-eye []
634 (.getChild (worm-model) "worm-11"))
637 (defn retina-sensor-image
638 "Return a map of pixel selection functions to BufferedImages
639 describing the distribution of light-sensitive components on this
640 geometry's surface. Each function creates an integer from the rgb
641 values found in the pixel. :red, :green, :blue, :gray are already
642 defined as extracting the red green blue and average components
643 respectively."
644 [#^Geometry eye]
645 (if-let [eye-map (meta-data eye "eye")]
646 (map-vals
647 #(ImageToAwt/convert
648 (.getImage (.loadTexture (asset-manager) %))
649 false false 0)
650 (read-string
651 eye-map))))
654 (defn enable-vision
656 ;; need to create a camera based on uv image,
657 ;; update this camera every frame based on the position of this
658 ;; geometry. (maybe can get cam to follow the object)
660 ;; use a stack for the continuation to grab the image.
663 [#^Geometry eye]
666 ;; Here's how vision will work.
668 ;; Make the continuation in scene-processor take FrameBuffer,
669 ;; byte-buffer, BufferedImage already sized to the correct
670 ;; dimensions. the continuation will decide wether to "mix" them
671 ;; into the BufferedImage, lazily ignore them, or mix them halfway
672 ;; and call c/graphics card routines.
674 ;; (vision creature) will take an optional :skip argument which will
675 ;; inform the continuations in scene processor to skip the given
676 ;; number of cycles; 0 means that no cycles will be skipped.
678 ;; (vision creature) will return [init-functions sensor-functions].
679 ;; The init-functions are each single-arg functions that take the
680 ;; world and register the cameras and must each be called before the
681 ;; corresponding sensor-functions. Each init-function returns the
682 ;; viewport for that eye which can be manipulated, saved, etc. Each
683 ;; sensor-function is a thunk and will return data in the same
684 ;; format as the tactile-sensor functions; the structure is
685 ;; [topology, sensor-data]. Internally, these sensor-functions
686 ;; maintain a reference to sensor-data which is periodically updated
687 ;; by the continuation function established by its init-function.
688 ;; They can be queried every cycle, but their information may not
689 ;; necessairly be different every cycle.
691 ;; Each eye in the creature in blender will work the same way as
692 ;; joints -- a one dimensional object with no geometry whose local
693 ;; coordinate system determines the orientation of the resulting
694 ;; eye. All eyes will have a parent named "eyes" just as all joints
695 ;; have a parent named "joints". The resulting camera will be a
696 ;; ChaseCamera or a CameraNode bound to the geo that is closest to
697 ;; the eye marker. The eye marker will contain the metadata for the
698 ;; eye, and will be moved by it's bound geometry. The dimensions of
699 ;; the eye's camera are equal to the dimensions of the eye's "UV"
700 ;; map.
703 )
705 (defn debug-window
706 "creates function that offers a debug view of sensor data"
707 []
708 (let [vi (view-image)]
709 (fn
710 [[coords sensor-data]]
711 (let [image (points->image coords)]
712 (dorun
713 (for [i (range (count coords))]
714 (.setRGB image ((coords i) 0) ((coords i) 1)
715 ({0 -16777216
716 1 -1} (sensor-data i)))))
717 (vi image)))))
720 ;;(defn test-touch [world creature]
723 (defn test-creature [thing]
724 (let [x-axis
725 (box 1 0.01 0.01 :physical? false :color ColorRGBA/Red)
726 y-axis
727 (box 0.01 1 0.01 :physical? false :color ColorRGBA/Green)
728 z-axis
729 (box 0.01 0.01 1 :physical? false :color ColorRGBA/Blue)
730 creature (blender-creature thing)
731 touch-nerves (touch creature)
732 touch-debug-windows (map (fn [_] (debug-window)) touch-nerves)
733 ]
734 (world
735 (nodify [creature
736 (box 10 2 10 :position (Vector3f. 0 -9 0)
737 :color ColorRGBA/Gray :mass 0)
738 x-axis y-axis z-axis
739 ])
740 standard-debug-controls
741 (fn [world]
742 (light-up-everything world)
743 (enable-debug world)
744 ;;(com.aurellem.capture.Capture/captureVideo
745 ;; world (file-str "/home/r/proj/ai-videos/hand"))
746 ;;(.setTimer world (RatchetTimer. 60))
747 ;;(speed-up world)
748 ;;(set-gravity world (Vector3f. 0 0 0))
749 )
750 (fn [world tpf]
751 ;;(dorun
752 ;; (map #(%1 %2) touch-nerves (repeat (.getRootNode world))))
754 (dorun
755 (map #(%1 (%2 (.getRootNode world)))
756 touch-debug-windows touch-nerves)
757 )
759 )
760 ;;(let [timer (atom 0)]
761 ;; (fn [_ _]
762 ;; (swap! timer inc)
763 ;; (if (= (rem @timer 60) 0)
764 ;; (println-repl (float (/ @timer 60))))))
765 )))
775 ;;; experiments in collisions
779 (defn collision-test []
780 (let [b-radius 1
781 b-position (Vector3f. 0 0 0)
782 obj-b (box 1 1 1 :color ColorRGBA/Blue
783 :position b-position
784 :mass 0)
785 node (nodify [obj-b])
786 bounds-b
787 (doto (Picture.)
788 (.setHeight 50)
789 (.setWidth 50)
790 (.setImage (asset-manager)
791 "Models/creature1/hand.png"
792 false
793 ))
795 ;;(Ray. (Vector3f. 0 -5 0) (.normalize (Vector3f. 0 1 0)))
797 collisions
798 (let [cr (CollisionResults.)]
799 (.collideWith node bounds-b cr)
800 (println (map #(.getContactPoint %) cr))
801 cr)
803 ;;collision-points
804 ;;(map #(sphere 0.1 :position (.getContactPoint %))
805 ;; collisions)
807 ;;node (nodify (conj collision-points obj-b))
809 sim
810 (world node
811 {"key-space"
812 (fn [_ value]
813 (if value
814 (let [cr (CollisionResults.)]
815 (.collideWith node bounds-b cr)
816 (println-repl (map #(.getContactPoint %) cr))
817 cr)))}
818 no-op
819 no-op)
821 ]
822 sim
824 ))
829 #+end_src
831 #+results: body-1
832 : #'cortex.silly/test-creature
835 * COMMENT purgatory
836 #+begin_src clojure
837 (defn bullet-trans []
838 (let [obj-a (sphere 0.5 :color ColorRGBA/Red
839 :position (Vector3f. -10 5 0))
840 obj-b (sphere 0.5 :color ColorRGBA/Blue
841 :position (Vector3f. -10 -5 0)
842 :mass 0)
843 control-a (.getControl obj-a RigidBodyControl)
844 control-b (.getControl obj-b RigidBodyControl)
845 swivel
846 (.toRotationMatrix
847 (doto (Quaternion.)
848 (.fromAngleAxis (/ Math/PI 2)
849 Vector3f/UNIT_X)))]
850 (doto
851 (ConeJoint.
852 control-a control-b
853 (Vector3f. 0 5 0)
854 (Vector3f. 0 -5 0)
855 swivel swivel)
856 (.setLimit (* 0.6 (/ Math/PI 4))
857 (/ Math/PI 4)
858 (* Math/PI 0.8)))
859 (world (nodify
860 [obj-a obj-b])
861 standard-debug-controls
862 enable-debug
863 no-op)))
866 (defn bullet-trans* []
867 (let [obj-a (box 1.5 0.5 0.5 :color ColorRGBA/Red
868 :position (Vector3f. 5 0 0)
869 :mass 90)
870 obj-b (sphere 0.5 :color ColorRGBA/Blue
871 :position (Vector3f. -5 0 0)
872 :mass 0)
873 control-a (.getControl obj-a RigidBodyControl)
874 control-b (.getControl obj-b RigidBodyControl)
875 move-up? (atom nil)
876 move-down? (atom nil)
877 move-left? (atom nil)
878 move-right? (atom nil)
879 roll-left? (atom nil)
880 roll-right? (atom nil)
881 force 100
882 swivel
883 (.toRotationMatrix
884 (doto (Quaternion.)
885 (.fromAngleAxis (/ Math/PI 2)
886 Vector3f/UNIT_X)))
887 x-move
888 (doto (Matrix3f.)
889 (.fromStartEndVectors Vector3f/UNIT_X
890 (.normalize (Vector3f. 1 1 0))))
892 timer (atom 0)]
893 (doto
894 (ConeJoint.
895 control-a control-b
896 (Vector3f. -8 0 0)
897 (Vector3f. 2 0 0)
898 ;;swivel swivel
899 ;;Matrix3f/IDENTITY Matrix3f/IDENTITY
900 x-move Matrix3f/IDENTITY
901 )
902 (.setCollisionBetweenLinkedBodys false)
903 (.setLimit (* 1 (/ Math/PI 4)) ;; twist
904 (* 1 (/ Math/PI 4)) ;; swing span in X-Y plane
905 (* 0 (/ Math/PI 4)))) ;; swing span in Y-Z plane
906 (world (nodify
907 [obj-a obj-b])
908 (merge standard-debug-controls
909 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
910 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
911 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
912 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
913 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
914 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
916 (fn [world]
917 (enable-debug world)
918 (set-gravity world Vector3f/ZERO)
919 )
921 (fn [world _]
923 (if @move-up?
924 (.applyForce control-a
925 (Vector3f. force 0 0)
926 (Vector3f. 0 0 0)))
927 (if @move-down?
928 (.applyForce control-a
929 (Vector3f. (- force) 0 0)
930 (Vector3f. 0 0 0)))
931 (if @move-left?
932 (.applyForce control-a
933 (Vector3f. 0 force 0)
934 (Vector3f. 0 0 0)))
935 (if @move-right?
936 (.applyForce control-a
937 (Vector3f. 0 (- force) 0)
938 (Vector3f. 0 0 0)))
940 (if @roll-left?
941 (.applyForce control-a
942 (Vector3f. 0 0 force)
943 (Vector3f. 0 0 0)))
944 (if @roll-right?
945 (.applyForce control-a
946 (Vector3f. 0 0 (- force))
947 (Vector3f. 0 0 0)))
949 (if (zero? (rem (swap! timer inc) 100))
950 (.attachChild
951 (.getRootNode world)
952 (sphere 0.05 :color ColorRGBA/Yellow
953 :physical? false :position
954 (.getWorldTranslation obj-a)))))
955 )
956 ))
958 (defn transform-trianglesdsd
959 "Transform that converts each vertex in the first triangle
960 into the corresponding vertex in the second triangle."
961 [#^Triangle tri-1 #^Triangle tri-2]
962 (let [in [(.get1 tri-1)
963 (.get2 tri-1)
964 (.get3 tri-1)]
965 out [(.get1 tri-2)
966 (.get2 tri-2)
967 (.get3 tri-2)]]
968 (let [translate (doto (Matrix4f.) (.setTranslation (.negate (in 0))))
969 in* [(.mult translate (in 0))
970 (.mult translate (in 1))
971 (.mult translate (in 2))]
972 final-translation
973 (doto (Matrix4f.)
974 (.setTranslation (out 1)))
976 rotate-1
977 (doto (Matrix3f.)
978 (.fromStartEndVectors
979 (.normalize
980 (.subtract
981 (in* 1) (in* 0)))
982 (.normalize
983 (.subtract
984 (out 1) (out 0)))))
985 in** [(.mult rotate-1 (in* 0))
986 (.mult rotate-1 (in* 1))
987 (.mult rotate-1 (in* 2))]
988 scale-factor-1
989 (.mult
990 (.normalize
991 (.subtract
992 (out 1)
993 (out 0)))
994 (/ (.length
995 (.subtract (out 1)
996 (out 0)))
997 (.length
998 (.subtract (in** 1)
999 (in** 0)))))
1000 scale-1 (doto (Matrix4f.) (.setScale scale-factor-1))
1001 in*** [(.mult scale-1 (in** 0))
1002 (.mult scale-1 (in** 1))
1003 (.mult scale-1 (in** 2))]
1011 (dorun (map println in))
1012 (println)
1013 (dorun (map println in*))
1014 (println)
1015 (dorun (map println in**))
1016 (println)
1017 (dorun (map println in***))
1018 (println)
1020 ))))
1023 (defn world-setup [joint]
1024 (let [joint-position (Vector3f. 0 0 0)
1025 joint-rotation
1026 (.toRotationMatrix
1027 (.mult
1028 (doto (Quaternion.)
1029 (.fromAngleAxis
1030 (* 1 (/ Math/PI 4))
1031 (Vector3f. -1 0 0)))
1032 (doto (Quaternion.)
1033 (.fromAngleAxis
1034 (* 1 (/ Math/PI 2))
1035 (Vector3f. 0 0 1)))))
1036 top-position (.mult joint-rotation (Vector3f. 8 0 0))
1038 origin (doto
1039 (sphere 0.1 :physical? false :color ColorRGBA/Cyan
1040 :position top-position))
1041 top (doto
1042 (sphere 0.1 :physical? false :color ColorRGBA/Yellow
1043 :position top-position)
1045 (.addControl
1046 (RigidBodyControl.
1047 (CapsuleCollisionShape. 0.5 1.5 1) (float 20))))
1048 bottom (doto
1049 (sphere 0.1 :physical? false :color ColorRGBA/DarkGray
1050 :position (Vector3f. 0 0 0))
1051 (.addControl
1052 (RigidBodyControl.
1053 (CapsuleCollisionShape. 0.5 1.5 1) (float 0))))
1054 table (box 10 2 10 :position (Vector3f. 0 -20 0)
1055 :color ColorRGBA/Gray :mass 0)
1056 a (.getControl top RigidBodyControl)
1057 b (.getControl bottom RigidBodyControl)]
1059 (cond
1060 (= joint :cone)
1062 (doto (ConeJoint.
1063 a b
1064 (world-to-local top joint-position)
1065 (world-to-local bottom joint-position)
1066 joint-rotation
1067 joint-rotation
1071 (.setLimit (* (/ 10) Math/PI)
1072 (* (/ 4) Math/PI)
1073 0)))
1074 [origin top bottom table]))
1076 (defn test-joint [joint]
1077 (let [[origin top bottom floor] (world-setup joint)
1078 control (.getControl top RigidBodyControl)
1079 move-up? (atom false)
1080 move-down? (atom false)
1081 move-left? (atom false)
1082 move-right? (atom false)
1083 roll-left? (atom false)
1084 roll-right? (atom false)
1085 timer (atom 0)]
1087 (world
1088 (nodify [top bottom floor origin])
1089 (merge standard-debug-controls
1090 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
1091 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
1092 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
1093 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
1094 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
1095 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
1097 (fn [world]
1098 (light-up-everything world)
1099 (enable-debug world)
1100 (set-gravity world (Vector3f. 0 0 0))
1103 (fn [world _]
1104 (if (zero? (rem (swap! timer inc) 100))
1105 (do
1106 ;; (println-repl @timer)
1107 (.attachChild (.getRootNode world)
1108 (sphere 0.05 :color ColorRGBA/Yellow
1109 :position (.getWorldTranslation top)
1110 :physical? false))
1111 (.attachChild (.getRootNode world)
1112 (sphere 0.05 :color ColorRGBA/LightGray
1113 :position (.getWorldTranslation bottom)
1114 :physical? false))))
1116 (if @move-up?
1117 (.applyTorque control
1118 (.mult (.getPhysicsRotation control)
1119 (Vector3f. 0 0 10))))
1120 (if @move-down?
1121 (.applyTorque control
1122 (.mult (.getPhysicsRotation control)
1123 (Vector3f. 0 0 -10))))
1124 (if @move-left?
1125 (.applyTorque control
1126 (.mult (.getPhysicsRotation control)
1127 (Vector3f. 0 10 0))))
1128 (if @move-right?
1129 (.applyTorque control
1130 (.mult (.getPhysicsRotation control)
1131 (Vector3f. 0 -10 0))))
1132 (if @roll-left?
1133 (.applyTorque control
1134 (.mult (.getPhysicsRotation control)
1135 (Vector3f. -1 0 0))))
1136 (if @roll-right?
1137 (.applyTorque control
1138 (.mult (.getPhysicsRotation control)
1139 (Vector3f. 1 0 0))))))))
1143 (defprotocol Frame
1144 (frame [this]))
1146 (extend-type BufferedImage
1147 Frame
1148 (frame [image]
1149 (merge
1150 (apply
1151 hash-map
1152 (interleave
1153 (doall (for [x (range (.getWidth image)) y (range (.getHeight image))]
1154 (vector x y)))
1155 (doall (for [x (range (.getWidth image)) y (range (.getHeight image))]
1156 (let [data (.getRGB image x y)]
1157 (hash-map :r (bit-shift-right (bit-and 0xff0000 data) 16)
1158 :g (bit-shift-right (bit-and 0x00ff00 data) 8)
1159 :b (bit-and 0x0000ff data)))))))
1160 {:width (.getWidth image) :height (.getHeight image)})))
1163 (extend-type ImagePlus
1164 Frame
1165 (frame [image+]
1166 (frame (.getBufferedImage image+))))
1169 #+end_src
1172 * COMMENT generate source
1173 #+begin_src clojure :tangle ../src/cortex/silly.clj
1174 <<body-1>>
1175 #+end_src