view org/test-creature.org @ 110:f89f0b9ed2fe

changed touch image retrieval code to use meta-data in preparation for multiple sensor maps per object
author Robert McIntyre <rlm@mit.edu>
date Thu, 19 Jan 2012 07:22:40 -0700
parents c05d8d222166
children 61d9c0e8d188
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 view-image
71 "Initailizes a JPanel on which you may draw a BufferedImage.
72 Returns a function that accepts a BufferedImage and draws it to the
73 JPanel."
74 []
75 (let [image
76 (atom
77 (BufferedImage. 1 1 BufferedImage/TYPE_4BYTE_ABGR))
78 panel
79 (proxy [JPanel] []
80 (paint
81 [graphics]
82 (proxy-super paintComponent graphics)
83 (.drawImage graphics @image 0 0 nil)))
84 frame (JFrame. "Display Image")]
85 (SwingUtilities/invokeLater
86 (fn []
87 (doto frame
88 (-> (.getContentPane) (.add panel))
89 (.pack)
90 (.setLocationRelativeTo nil)
91 (.setResizable true)
92 (.setVisible true))))
93 (fn [#^BufferedImage i]
94 (reset! image i)
95 (.setSize frame (+ 8 (.getWidth i)) (+ 28 (.getHeight i)))
96 (.repaint panel 0 0 (.getWidth i) (.getHeight i)))))
98 (defn points->image
99 "Take a sparse collection of points and visuliaze it as a
100 BufferedImage."
102 ;; TODO maybe parallelize this since it's easy
104 [points]
105 (if (empty? points)
106 (BufferedImage. 1 1 BufferedImage/TYPE_BYTE_BINARY)
107 (let [xs (vec (map first points))
108 ys (vec (map second points))
109 x0 (apply min xs)
110 y0 (apply min ys)
111 width (- (apply max xs) x0)
112 height (- (apply max ys) y0)
113 image (BufferedImage. (inc width) (inc height)
114 BufferedImage/TYPE_BYTE_BINARY)]
115 (dorun
116 (for [index (range (count points))]
117 (.setRGB image (- (xs index) x0) (- (ys index) y0) -1)))
119 image)))
121 (defn test-data
122 []
123 (vec
124 (for [a (range 0 1000 2)
125 b (range 0 1000 2)]
126 (vector a b))
127 ))
129 (defn average [coll]
130 (/ (reduce + coll) (count coll)))
132 (defn collapse-1d
133 "One dimensional analogue of collapse"
134 [center line]
135 (let [length (count line)
136 num-above (count (filter (partial < center) line))
137 num-below (- length num-above)]
138 (range (- center num-below)
139 (+ center num-above))
140 ))
142 (defn collapse
143 "Take a set of pairs of integers and collapse them into a
144 contigous bitmap."
145 [points]
146 (if (empty? points) []
147 (let
148 [num-points (count points)
149 center (vector
150 (int (average (map first points)))
151 (int (average (map first points))))
152 flattened
153 (reduce
154 concat
155 (map
156 (fn [column]
157 (map vector
158 (map first column)
159 (collapse-1d (second center)
160 (map second column))))
161 (partition-by first (sort-by first points))))
162 squeezed
163 (reduce
164 concat
165 (map
166 (fn [row]
167 (map vector
168 (collapse-1d (first center)
169 (map first row))
170 (map second row)))
171 (partition-by second (sort-by second flattened))))
172 relocate
173 (let [min-x (apply min (map first squeezed))
174 min-y (apply min (map second squeezed))]
175 (map (fn [[x y]]
176 [(- x min-x)
177 (- y min-y)])
178 squeezed))]
179 relocate
180 )))
182 (defn load-bullet []
183 (let [sim (world (Node.) {} no-op no-op)]
184 (doto sim
185 (.enqueue
186 (fn []
187 (.stop sim)))
188 (.start))))
190 (defn load-blender-model
191 "Load a .blend file using an asset folder relative path."
192 [^String model]
193 (.loadModel
194 (doto (asset-manager)
195 (.registerLoader BlenderModelLoader (into-array String ["blend"])))
196 model))
198 (defn meta-data [blender-node key]
199 (if-let [data (.getUserData blender-node "properties")]
200 (.findValue data key)
201 nil))
203 (defn blender-to-jme
204 "Convert from Blender coordinates to JME coordinates"
205 [#^Vector3f in]
206 (Vector3f. (.getX in)
207 (.getZ in)
208 (- (.getY in))))
210 (defn jme-to-blender
211 "Convert from JME coordinates to Blender coordinates"
212 [#^Vector3f in]
213 (Vector3f. (.getX in)
214 (- (.getZ in))
215 (.getY in)))
217 (defn joint-targets
218 "Return the two closest two objects to the joint object, ordered
219 from bottom to top according to the joint's rotation."
220 [#^Node parts #^Node joint]
221 ;;(println (meta-data joint "joint"))
222 (.getWorldRotation joint)
223 (loop [radius (float 0.01)]
224 (let [results (CollisionResults.)]
225 (.collideWith
226 parts
227 (BoundingBox. (.getWorldTranslation joint)
228 radius radius radius)
229 results)
230 (let [targets
231 (distinct
232 (map #(.getGeometry %) results))]
233 (if (>= (count targets) 2)
234 (sort-by
235 #(let [v
236 (jme-to-blender
237 (.mult
238 (.inverse (.getWorldRotation joint))
239 (.subtract (.getWorldTranslation %)
240 (.getWorldTranslation joint))))]
241 (println-repl (.getName %) ":" v)
242 (.dot (Vector3f. 1 1 1)
243 v))
244 (take 2 targets))
245 (recur (float (* radius 2))))))))
247 (defn world-to-local
248 "Convert the world coordinates into coordinates relative to the
249 object (i.e. local coordinates), taking into account the rotation
250 of object."
251 [#^Spatial object world-coordinate]
252 (let [out (Vector3f.)]
253 (.worldToLocal object world-coordinate out) out))
255 (defn local-to-world
256 "Convert the local coordinates into coordinates into world relative
257 coordinates"
258 [#^Spatial object local-coordinate]
259 (let [world-coordinate (Vector3f.)]
260 (.localToWorld object local-coordinate world-coordinate)
261 world-coordinate))
264 (defmulti joint-dispatch
265 "Translate blender pseudo-joints into real JME joints."
266 (fn [constraints & _]
267 (:type constraints)))
269 (defmethod joint-dispatch :point
270 [constraints control-a control-b pivot-a pivot-b rotation]
271 (println-repl "creating POINT2POINT joint")
272 (Point2PointJoint.
273 control-a
274 control-b
275 pivot-a
276 pivot-b))
278 (defmethod joint-dispatch :hinge
279 [constraints control-a control-b pivot-a pivot-b rotation]
280 (println-repl "creating HINGE joint")
281 (let [axis
282 (if-let
283 [axis (:axis constraints)]
284 axis
285 Vector3f/UNIT_X)
286 [limit-1 limit-2] (:limit constraints)
287 hinge-axis
288 (.mult
289 rotation
290 (blender-to-jme axis))]
291 (doto
292 (HingeJoint.
293 control-a
294 control-b
295 pivot-a
296 pivot-b
297 hinge-axis
298 hinge-axis)
299 (.setLimit limit-1 limit-2))))
301 (defmethod joint-dispatch :cone
302 [constraints control-a control-b pivot-a pivot-b rotation]
303 (let [limit-xz (:limit-xz constraints)
304 limit-xy (:limit-xy constraints)
305 twist (:twist constraints)]
307 (println-repl "creating CONE joint")
308 (println-repl rotation)
309 (println-repl
310 "UNIT_X --> " (.mult rotation (Vector3f. 1 0 0)))
311 (println-repl
312 "UNIT_Y --> " (.mult rotation (Vector3f. 0 1 0)))
313 (println-repl
314 "UNIT_Z --> " (.mult rotation (Vector3f. 0 0 1)))
315 (doto
316 (ConeJoint.
317 control-a
318 control-b
319 pivot-a
320 pivot-b
321 rotation
322 rotation)
323 (.setLimit (float limit-xz)
324 (float limit-xy)
325 (float twist)))))
327 (defn connect
328 "here are some examples:
329 {:type :point}
330 {:type :hinge :limit [0 (/ Math/PI 2)] :axis (Vector3f. 0 1 0)}
331 (:axis defaults to (Vector3f. 1 0 0) if not provided for hinge joints)
333 {:type :cone :limit-xz 0]
334 :limit-xy 0]
335 :twist 0]} (use XZY rotation mode in blender!)"
336 [#^Node obj-a #^Node obj-b #^Node joint]
337 (let [control-a (.getControl obj-a RigidBodyControl)
338 control-b (.getControl obj-b RigidBodyControl)
339 joint-center (.getWorldTranslation joint)
340 joint-rotation (.toRotationMatrix (.getWorldRotation joint))
341 pivot-a (world-to-local obj-a joint-center)
342 pivot-b (world-to-local obj-b joint-center)]
344 (if-let [constraints
345 (map-vals
346 eval
347 (read-string
348 (meta-data joint "joint")))]
349 ;; A side-effect of creating a joint registers
350 ;; it with both physics objects which in turn
351 ;; will register the joint with the physics system
352 ;; when the simulation is started.
353 (do
354 (println-repl "creating joint between"
355 (.getName obj-a) "and" (.getName obj-b))
356 (joint-dispatch constraints
357 control-a control-b
358 pivot-a pivot-b
359 joint-rotation))
360 (println-repl "could not find joint meta-data!"))))
362 (defn assemble-creature [#^Node pieces joints]
363 (dorun
364 (map
365 (fn [geom]
366 (let [physics-control
367 (RigidBodyControl.
368 (HullCollisionShape.
369 (.getMesh geom))
370 (if-let [mass (meta-data geom "mass")]
371 (do
372 (println-repl
373 "setting" (.getName geom) "mass to" (float mass))
374 (float mass))
375 (float 1)))]
377 (.addControl geom physics-control)))
378 (filter #(isa? (class %) Geometry )
379 (node-seq pieces))))
380 (dorun
381 (map
382 (fn [joint]
383 (let [[obj-a obj-b]
384 (joint-targets pieces joint)]
385 (connect obj-a obj-b joint)))
386 joints))
387 pieces)
389 (defn blender-creature [blender-path]
390 (let [model (load-blender-model blender-path)
391 joints
392 (if-let [joint-node (.getChild model "joints")]
393 (seq (.getChildren joint-node))
394 (do (println-repl "could not find joints node")
395 []))]
396 (assemble-creature model joints)))
398 (def hand "Models/creature1/one.blend")
400 (def worm "Models/creature1/try-again.blend")
402 (def touch "Models/creature1/touch.blend")
404 (defn worm-model [] (load-blender-model worm))
406 (defn x-ray [#^ColorRGBA color]
407 (doto (Material. (asset-manager)
408 "Common/MatDefs/Misc/Unshaded.j3md")
409 (.setColor "Color" color)
410 (-> (.getAdditionalRenderState)
411 (.setDepthTest false))))
415 (defn colorful []
416 (.getChild (worm-model) "worm-21"))
418 (import jme3tools.converters.ImageToAwt)
420 (import ij.ImagePlus)
422 ;; Every Mesh has many triangles, each with its own index.
423 ;; Every vertex has its own index as well.
425 (defn tactile-sensor-image
426 "Return the touch-sensor distribution image in BufferedImage format,
427 or nil if it does not exist."
428 [#^Geometry obj]
429 (if-let [image-path (meta-data obj "touch")]
430 (ImageToAwt/convert
431 (.getImage
432 (.loadTexture
433 (asset-manager)
434 image-path))
435 false false 0)))
437 (import ij.process.ImageProcessor)
438 (import java.awt.image.BufferedImage)
440 (def white -1)
442 (defn filter-pixels
443 "List the coordinates of all pixels matching pred, within the bounds
444 provided. Bounds -> [x0 y0 width height]"
445 {:author "Dylan Holmes"}
446 ([pred #^BufferedImage image]
447 (filter-pixels pred image [0 0 (.getWidth image) (.getHeight image)]))
448 ([pred #^BufferedImage image [x0 y0 width height]]
449 ((fn accumulate [x y matches]
450 (cond
451 (>= y (+ height y0)) matches
452 (>= x (+ width x0)) (recur 0 (inc y) matches)
453 (pred (.getRGB image x y))
454 (recur (inc x) y (conj matches [x y]))
455 :else (recur (inc x) y matches)))
456 x0 y0 [])))
458 (defn white-coordinates
459 "Coordinates of all the white pixels in a subset of the image."
460 [#^BufferedImage image bounds]
461 (filter-pixels #(= % white) image bounds))
463 (defn triangle
464 "Get the triangle specified by triangle-index from the mesh"
465 [#^Mesh mesh triangle-index]
466 (let [scratch (Triangle.)]
467 (.getTriangle mesh triangle-index scratch)
468 scratch))
470 (defn triangle-vertex-indices
471 "Get the triangle vertex indices of a given triangle from a given
472 mesh."
473 [#^Mesh mesh triangle-index]
474 (let [indices (int-array 3)]
475 (.getTriangle mesh triangle-index indices)
476 (vec indices)))
478 (defn vertex-UV-coord
479 "Get the uv-coordinates of the vertex named by vertex-index"
480 [#^Mesh mesh vertex-index]
481 (let [UV-buffer
482 (.getData
483 (.getBuffer
484 mesh
485 VertexBuffer$Type/TexCoord))]
486 [(.get UV-buffer (* vertex-index 2))
487 (.get UV-buffer (+ 1 (* vertex-index 2)))]))
489 (defn triangle-UV-coord
490 "Get the uv-cooridnates of the triangle's verticies."
491 [#^Mesh mesh width height triangle-index]
492 (map (fn [[u v]] (vector (* width u) (* height v)))
493 (map (partial vertex-UV-coord mesh)
494 (triangle-vertex-indices mesh triangle-index))))
496 (defn same-side?
497 "Given the points p1 and p2 and the reference point ref, is point p
498 on the same side of the line that goes through p1 and p2 as ref is?"
499 [p1 p2 ref p]
500 (<=
501 0
502 (.dot
503 (.cross (.subtract p2 p1) (.subtract p p1))
504 (.cross (.subtract p2 p1) (.subtract ref p1)))))
506 (defn triangle-seq [#^Triangle tri]
507 [(.get1 tri) (.get2 tri) (.get3 tri)])
509 (defn vector3f-seq [#^Vector3f v]
510 [(.getX v) (.getY v) (.getZ v)])
512 (defn inside-triangle?
513 "Is the point inside the triangle?"
514 {:author "Dylan Holmes"}
515 [#^Triangle tri #^Vector3f p]
516 (let [[vert-1 vert-2 vert-3] (triangle-seq tri)]
517 (and
518 (same-side? vert-1 vert-2 vert-3 p)
519 (same-side? vert-2 vert-3 vert-1 p)
520 (same-side? vert-3 vert-1 vert-2 p))))
522 (defn triangle->matrix4f
523 "Converts the triangle into a 4x4 matrix: The first three columns
524 contain the vertices of the triangle; the last contains the unit
525 normal of the triangle. The bottom row is filled with 1s."
526 [#^Triangle t]
527 (let [mat (Matrix4f.)
528 [vert-1 vert-2 vert-3]
529 ((comp vec map) #(.get t %) (range 3))
530 unit-normal (do (.calculateNormal t)(.getNormal t))
531 vertices [vert-1 vert-2 vert-3 unit-normal]]
532 (dorun
533 (for [row (range 4) col (range 3)]
534 (do
535 (.set mat col row (.get (vertices row)col))
536 (.set mat 3 row 1))))
537 mat))
539 (defn triangle-transformation
540 "Returns the affine transformation that converts each vertex in the
541 first triangle into the corresponding vertex in the second
542 triangle."
543 [#^Triangle tri-1 #^Triangle tri-2]
544 (.mult
545 (triangle->matrix4f tri-2)
546 (.invert (triangle->matrix4f tri-1))))
548 (defn point->vector2f [[u v]]
549 (Vector2f. u v))
551 (defn vector2f->vector3f [v]
552 (Vector3f. (.getX v) (.getY v) 0))
554 (defn map-triangle [f #^Triangle tri]
555 (Triangle.
556 (f 0 (.get1 tri))
557 (f 1 (.get2 tri))
558 (f 2 (.get3 tri))))
560 (defn points->triangle
561 "Convert a list of points into a triangle."
562 [points]
563 (apply #(Triangle. %1 %2 %3)
564 (map (fn [point]
565 (let [point (vec point)]
566 (Vector3f. (get point 0 0)
567 (get point 1 0)
568 (get point 2 0))))
569 (take 3 points))))
571 (defn convex-bounds
572 "Dimensions of the smallest integer bounding square of the list of
573 2D verticies in the form: [x y width height]."
574 [uv-verts]
575 (let [xs (map first uv-verts)
576 ys (map second uv-verts)
577 x0 (Math/floor (apply min xs))
578 y0 (Math/floor (apply min ys))
579 x1 (Math/ceil (apply max xs))
580 y1 (Math/ceil (apply max ys))]
581 [x0 y0 (- x1 x0) (- y1 y0)]))
583 (defn sensors-in-triangle
584 "Find the locations of the touch sensors within a triangle in both
585 UV and gemoetry relative coordinates."
586 [image mesh tri-index]
587 (let [width (.getWidth image)
588 height (.getHeight image)
589 UV-vertex-coords (triangle-UV-coord mesh width height tri-index)
590 bounds (convex-bounds UV-vertex-coords)
592 cutout-triangle (points->triangle UV-vertex-coords)
593 UV-sensor-coords
594 (filter (comp (partial inside-triangle? cutout-triangle)
595 (fn [[u v]] (Vector3f. u v 0)))
596 (white-coordinates image bounds))
597 UV->geometry (triangle-transformation
598 cutout-triangle
599 (triangle mesh tri-index))
600 geometry-sensor-coords
601 (map (fn [[u v]] (.mult UV->geometry (Vector3f. u v 0)))
602 UV-sensor-coords)]
603 {:UV UV-sensor-coords :geometry geometry-sensor-coords}))
605 (defn-memo locate-feelers
606 "Search the geometry's tactile UV image for touch sensors, returning
607 their positions in geometry-relative coordinates."
608 [#^Geometry geo]
609 (let [mesh (.getMesh geo)
610 num-triangles (.getTriangleCount mesh)]
611 (if-let [image (tactile-sensor-image geo)]
612 (map
613 (partial sensors-in-triangle image mesh)
614 (range num-triangles))
615 (repeat (.getTriangleCount mesh) {:UV nil :geometry nil}))))
617 (use 'clojure.contrib.def)
619 (defn-memo touch-topology [#^Gemoetry geo]
620 (vec (collapse (reduce concat (map :UV (locate-feelers geo))))))
622 (defn-memo feeler-coordinates [#^Geometry geo]
623 (vec (map :geometry (locate-feelers geo))))
625 (defn enable-touch [#^Geometry geo]
626 (let [feeler-coords (feeler-coordinates geo)
627 tris (triangles geo)
628 limit 0.1
629 ;;results (CollisionResults.)
630 ]
631 (fn [node]
632 (let [sensor-origins
633 (map
634 #(map (partial local-to-world geo) %)
635 feeler-coords)
636 triangle-normals
637 (map (partial get-ray-direction geo)
638 tris)
639 rays
640 (flatten
641 (map (fn [origins norm]
642 (map #(doto (Ray. % norm)
643 (.setLimit limit)) origins))
644 sensor-origins triangle-normals))]
645 (vector
646 (touch-topology geo)
647 (vec
648 (for [ray rays]
649 (do
650 (let [results (CollisionResults.)]
651 (.collideWith node ray results)
652 (let [touch-objects
653 (set
654 (filter #(not (= geo %))
655 (map #(.getGeometry %) results)))]
656 (if (> (count touch-objects) 0)
657 1 0)))))))))))
661 (defn touch [#^Node pieces]
662 (map enable-touch
663 (filter #(isa? (class %) Geometry)
664 (node-seq pieces))))
666 (defn debug-window
667 "creates function that offers a debug view of sensor data"
668 []
669 (let [vi (view-image)]
670 (fn
671 [[coords sensor-data]]
672 (let [image (points->image coords)]
673 (dorun
674 (for [i (range (count coords))]
675 (.setRGB image ((coords i) 0) ((coords i) 1)
676 ({0 -16777216
677 1 -1} (sensor-data i)))))
678 (vi image)))))
681 ;;(defn test-touch [world creature]
684 (defn test-creature [thing]
685 (let [x-axis
686 (box 1 0.01 0.01 :physical? false :color ColorRGBA/Red)
687 y-axis
688 (box 0.01 1 0.01 :physical? false :color ColorRGBA/Green)
689 z-axis
690 (box 0.01 0.01 1 :physical? false :color ColorRGBA/Blue)
691 creature (blender-creature thing)
692 touch-nerves (touch creature)
693 touch-debug-windows (map (fn [_] (debug-window)) touch-nerves)
694 ]
695 (world
696 (nodify [creature
697 (box 10 2 10 :position (Vector3f. 0 -9 0)
698 :color ColorRGBA/Gray :mass 0)
699 x-axis y-axis z-axis
700 ])
701 standard-debug-controls
702 (fn [world]
703 (light-up-everything world)
704 (enable-debug world)
705 ;;(com.aurellem.capture.Capture/captureVideo
706 ;; world (file-str "/home/r/proj/ai-videos/hand"))
707 ;;(.setTimer world (RatchetTimer. 60))
708 ;;(speed-up world)
709 ;;(set-gravity world (Vector3f. 0 0 0))
710 )
711 (fn [world tpf]
712 ;;(dorun
713 ;; (map #(%1 %2) touch-nerves (repeat (.getRootNode world))))
715 (dorun
716 (map #(%1 (%2 (.getRootNode world)))
717 touch-debug-windows touch-nerves)
718 )
720 )
721 ;;(let [timer (atom 0)]
722 ;; (fn [_ _]
723 ;; (swap! timer inc)
724 ;; (if (= (rem @timer 60) 0)
725 ;; (println-repl (float (/ @timer 60))))))
726 )))
736 ;;; experiments in collisions
740 (defn collision-test []
741 (let [b-radius 1
742 b-position (Vector3f. 0 0 0)
743 obj-b (box 1 1 1 :color ColorRGBA/Blue
744 :position b-position
745 :mass 0)
746 node (nodify [obj-b])
747 bounds-b
748 (doto (Picture.)
749 (.setHeight 50)
750 (.setWidth 50)
751 (.setImage (asset-manager)
752 "Models/creature1/hand.png"
753 false
754 ))
756 ;;(Ray. (Vector3f. 0 -5 0) (.normalize (Vector3f. 0 1 0)))
758 collisions
759 (let [cr (CollisionResults.)]
760 (.collideWith node bounds-b cr)
761 (println (map #(.getContactPoint %) cr))
762 cr)
764 ;;collision-points
765 ;;(map #(sphere 0.1 :position (.getContactPoint %))
766 ;; collisions)
768 ;;node (nodify (conj collision-points obj-b))
770 sim
771 (world node
772 {"key-space"
773 (fn [_ value]
774 (if value
775 (let [cr (CollisionResults.)]
776 (.collideWith node bounds-b cr)
777 (println-repl (map #(.getContactPoint %) cr))
778 cr)))}
779 no-op
780 no-op)
782 ]
783 sim
785 ))
790 #+end_src
792 #+results: body-1
793 : #'cortex.silly/test-creature
796 * COMMENT purgatory
797 #+begin_src clojure
798 (defn bullet-trans []
799 (let [obj-a (sphere 0.5 :color ColorRGBA/Red
800 :position (Vector3f. -10 5 0))
801 obj-b (sphere 0.5 :color ColorRGBA/Blue
802 :position (Vector3f. -10 -5 0)
803 :mass 0)
804 control-a (.getControl obj-a RigidBodyControl)
805 control-b (.getControl obj-b RigidBodyControl)
806 swivel
807 (.toRotationMatrix
808 (doto (Quaternion.)
809 (.fromAngleAxis (/ Math/PI 2)
810 Vector3f/UNIT_X)))]
811 (doto
812 (ConeJoint.
813 control-a control-b
814 (Vector3f. 0 5 0)
815 (Vector3f. 0 -5 0)
816 swivel swivel)
817 (.setLimit (* 0.6 (/ Math/PI 4))
818 (/ Math/PI 4)
819 (* Math/PI 0.8)))
820 (world (nodify
821 [obj-a obj-b])
822 standard-debug-controls
823 enable-debug
824 no-op)))
827 (defn bullet-trans* []
828 (let [obj-a (box 1.5 0.5 0.5 :color ColorRGBA/Red
829 :position (Vector3f. 5 0 0)
830 :mass 90)
831 obj-b (sphere 0.5 :color ColorRGBA/Blue
832 :position (Vector3f. -5 0 0)
833 :mass 0)
834 control-a (.getControl obj-a RigidBodyControl)
835 control-b (.getControl obj-b RigidBodyControl)
836 move-up? (atom nil)
837 move-down? (atom nil)
838 move-left? (atom nil)
839 move-right? (atom nil)
840 roll-left? (atom nil)
841 roll-right? (atom nil)
842 force 100
843 swivel
844 (.toRotationMatrix
845 (doto (Quaternion.)
846 (.fromAngleAxis (/ Math/PI 2)
847 Vector3f/UNIT_X)))
848 x-move
849 (doto (Matrix3f.)
850 (.fromStartEndVectors Vector3f/UNIT_X
851 (.normalize (Vector3f. 1 1 0))))
853 timer (atom 0)]
854 (doto
855 (ConeJoint.
856 control-a control-b
857 (Vector3f. -8 0 0)
858 (Vector3f. 2 0 0)
859 ;;swivel swivel
860 ;;Matrix3f/IDENTITY Matrix3f/IDENTITY
861 x-move Matrix3f/IDENTITY
862 )
863 (.setCollisionBetweenLinkedBodys false)
864 (.setLimit (* 1 (/ Math/PI 4)) ;; twist
865 (* 1 (/ Math/PI 4)) ;; swing span in X-Y plane
866 (* 0 (/ Math/PI 4)))) ;; swing span in Y-Z plane
867 (world (nodify
868 [obj-a obj-b])
869 (merge standard-debug-controls
870 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
871 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
872 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
873 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
874 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
875 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
877 (fn [world]
878 (enable-debug world)
879 (set-gravity world Vector3f/ZERO)
880 )
882 (fn [world _]
884 (if @move-up?
885 (.applyForce control-a
886 (Vector3f. force 0 0)
887 (Vector3f. 0 0 0)))
888 (if @move-down?
889 (.applyForce control-a
890 (Vector3f. (- force) 0 0)
891 (Vector3f. 0 0 0)))
892 (if @move-left?
893 (.applyForce control-a
894 (Vector3f. 0 force 0)
895 (Vector3f. 0 0 0)))
896 (if @move-right?
897 (.applyForce control-a
898 (Vector3f. 0 (- force) 0)
899 (Vector3f. 0 0 0)))
901 (if @roll-left?
902 (.applyForce control-a
903 (Vector3f. 0 0 force)
904 (Vector3f. 0 0 0)))
905 (if @roll-right?
906 (.applyForce control-a
907 (Vector3f. 0 0 (- force))
908 (Vector3f. 0 0 0)))
910 (if (zero? (rem (swap! timer inc) 100))
911 (.attachChild
912 (.getRootNode world)
913 (sphere 0.05 :color ColorRGBA/Yellow
914 :physical? false :position
915 (.getWorldTranslation obj-a)))))
916 )
917 ))
919 (defn transform-trianglesdsd
920 "Transform that converts each vertex in the first triangle
921 into the corresponding vertex in the second triangle."
922 [#^Triangle tri-1 #^Triangle tri-2]
923 (let [in [(.get1 tri-1)
924 (.get2 tri-1)
925 (.get3 tri-1)]
926 out [(.get1 tri-2)
927 (.get2 tri-2)
928 (.get3 tri-2)]]
929 (let [translate (doto (Matrix4f.) (.setTranslation (.negate (in 0))))
930 in* [(.mult translate (in 0))
931 (.mult translate (in 1))
932 (.mult translate (in 2))]
933 final-translation
934 (doto (Matrix4f.)
935 (.setTranslation (out 1)))
937 rotate-1
938 (doto (Matrix3f.)
939 (.fromStartEndVectors
940 (.normalize
941 (.subtract
942 (in* 1) (in* 0)))
943 (.normalize
944 (.subtract
945 (out 1) (out 0)))))
946 in** [(.mult rotate-1 (in* 0))
947 (.mult rotate-1 (in* 1))
948 (.mult rotate-1 (in* 2))]
949 scale-factor-1
950 (.mult
951 (.normalize
952 (.subtract
953 (out 1)
954 (out 0)))
955 (/ (.length
956 (.subtract (out 1)
957 (out 0)))
958 (.length
959 (.subtract (in** 1)
960 (in** 0)))))
961 scale-1 (doto (Matrix4f.) (.setScale scale-factor-1))
962 in*** [(.mult scale-1 (in** 0))
963 (.mult scale-1 (in** 1))
964 (.mult scale-1 (in** 2))]
970 ]
972 (dorun (map println in))
973 (println)
974 (dorun (map println in*))
975 (println)
976 (dorun (map println in**))
977 (println)
978 (dorun (map println in***))
979 (println)
981 ))))
984 (defn world-setup [joint]
985 (let [joint-position (Vector3f. 0 0 0)
986 joint-rotation
987 (.toRotationMatrix
988 (.mult
989 (doto (Quaternion.)
990 (.fromAngleAxis
991 (* 1 (/ Math/PI 4))
992 (Vector3f. -1 0 0)))
993 (doto (Quaternion.)
994 (.fromAngleAxis
995 (* 1 (/ Math/PI 2))
996 (Vector3f. 0 0 1)))))
997 top-position (.mult joint-rotation (Vector3f. 8 0 0))
999 origin (doto
1000 (sphere 0.1 :physical? false :color ColorRGBA/Cyan
1001 :position top-position))
1002 top (doto
1003 (sphere 0.1 :physical? false :color ColorRGBA/Yellow
1004 :position top-position)
1006 (.addControl
1007 (RigidBodyControl.
1008 (CapsuleCollisionShape. 0.5 1.5 1) (float 20))))
1009 bottom (doto
1010 (sphere 0.1 :physical? false :color ColorRGBA/DarkGray
1011 :position (Vector3f. 0 0 0))
1012 (.addControl
1013 (RigidBodyControl.
1014 (CapsuleCollisionShape. 0.5 1.5 1) (float 0))))
1015 table (box 10 2 10 :position (Vector3f. 0 -20 0)
1016 :color ColorRGBA/Gray :mass 0)
1017 a (.getControl top RigidBodyControl)
1018 b (.getControl bottom RigidBodyControl)]
1020 (cond
1021 (= joint :cone)
1023 (doto (ConeJoint.
1024 a b
1025 (world-to-local top joint-position)
1026 (world-to-local bottom joint-position)
1027 joint-rotation
1028 joint-rotation
1032 (.setLimit (* (/ 10) Math/PI)
1033 (* (/ 4) Math/PI)
1034 0)))
1035 [origin top bottom table]))
1037 (defn test-joint [joint]
1038 (let [[origin top bottom floor] (world-setup joint)
1039 control (.getControl top RigidBodyControl)
1040 move-up? (atom false)
1041 move-down? (atom false)
1042 move-left? (atom false)
1043 move-right? (atom false)
1044 roll-left? (atom false)
1045 roll-right? (atom false)
1046 timer (atom 0)]
1048 (world
1049 (nodify [top bottom floor origin])
1050 (merge standard-debug-controls
1051 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
1052 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
1053 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
1054 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
1055 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
1056 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
1058 (fn [world]
1059 (light-up-everything world)
1060 (enable-debug world)
1061 (set-gravity world (Vector3f. 0 0 0))
1064 (fn [world _]
1065 (if (zero? (rem (swap! timer inc) 100))
1066 (do
1067 ;; (println-repl @timer)
1068 (.attachChild (.getRootNode world)
1069 (sphere 0.05 :color ColorRGBA/Yellow
1070 :position (.getWorldTranslation top)
1071 :physical? false))
1072 (.attachChild (.getRootNode world)
1073 (sphere 0.05 :color ColorRGBA/LightGray
1074 :position (.getWorldTranslation bottom)
1075 :physical? false))))
1077 (if @move-up?
1078 (.applyTorque control
1079 (.mult (.getPhysicsRotation control)
1080 (Vector3f. 0 0 10))))
1081 (if @move-down?
1082 (.applyTorque control
1083 (.mult (.getPhysicsRotation control)
1084 (Vector3f. 0 0 -10))))
1085 (if @move-left?
1086 (.applyTorque control
1087 (.mult (.getPhysicsRotation control)
1088 (Vector3f. 0 10 0))))
1089 (if @move-right?
1090 (.applyTorque control
1091 (.mult (.getPhysicsRotation control)
1092 (Vector3f. 0 -10 0))))
1093 (if @roll-left?
1094 (.applyTorque control
1095 (.mult (.getPhysicsRotation control)
1096 (Vector3f. -1 0 0))))
1097 (if @roll-right?
1098 (.applyTorque control
1099 (.mult (.getPhysicsRotation control)
1100 (Vector3f. 1 0 0))))))))
1104 (defprotocol Frame
1105 (frame [this]))
1107 (extend-type BufferedImage
1108 Frame
1109 (frame [image]
1110 (merge
1111 (apply
1112 hash-map
1113 (interleave
1114 (doall (for [x (range (.getWidth image)) y (range (.getHeight image))]
1115 (vector x y)))
1116 (doall (for [x (range (.getWidth image)) y (range (.getHeight image))]
1117 (let [data (.getRGB image x y)]
1118 (hash-map :r (bit-shift-right (bit-and 0xff0000 data) 16)
1119 :g (bit-shift-right (bit-and 0x00ff00 data) 8)
1120 :b (bit-and 0x0000ff data)))))))
1121 {:width (.getWidth image) :height (.getHeight image)})))
1124 (extend-type ImagePlus
1125 Frame
1126 (frame [image+]
1127 (frame (.getBufferedImage image+))))
1130 #+end_src
1133 * COMMENT generate source
1134 #+begin_src clojure :tangle ../src/cortex/silly.clj
1135 <<body-1>>
1136 #+end_src