view org/test-creature.org @ 98:5b23961433e3

going to create bitmaps for touch sensing
author Robert McIntyre <rlm@mit.edu>
date Wed, 11 Jan 2012 21:30:26 -0700
parents 2ff8c7c4e64d
children b7a3ba5e879b
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 * Intro
10 So far, I've made the following senses --
11 - Vision
12 - Hearing
13 - Touch
14 - Proprioception
16 And one effector:
17 - Movement
19 However, the code so far has only enabled these senses, but has not
20 actually implemented them. For example, there is still a lot of work
21 to be done for vision. I need to be able to create an /eyeball/ in
22 simulation that can be moved around and see the world from different
23 angles. I also need to determine weather to use log-polar or cartesian
24 for the visual input, and I need to determine how/wether to
25 disceritise the visual input.
27 I also want to be able to visualize both the sensors and the
28 effectors in pretty pictures. This semi-retarted creature will by my
29 first attempt at bringing everything together.
31 * The creature's body
33 Still going to do an eve-like body in blender, but due to problems
34 importing the joints, etc into jMonkeyEngine3, I',m going to do all
35 the connecting here in clojure code, using the names of the individual
36 components and trial and error. Later, I'll maybe make some sort of
37 creature-building modifications to blender that support whatever
38 discreitized senses I'm going to make.
40 #+name: body-1
41 #+begin_src clojure
42 (ns cortex.silly
43 "let's play!"
44 {:author "Robert McIntyre"})
46 ;; TODO remove this!
47 (require 'cortex.import)
48 (cortex.import/mega-import-jme3)
49 (use '(cortex world util body hearing touch vision))
51 (rlm.rlm-commands/help)
53 (declare joint-create)
55 (defn load-bullet []
56 (let [sim (world (Node.) {} no-op no-op)]
57 (.enqueue
58 sim
59 (fn []
60 (.stop sim)))
61 (.start sim)))
63 (defn load-blender-model
64 "Load a .blend file using an asset folder relative path."
65 [^String model]
66 (.loadModel
67 (doto (asset-manager)
68 (.registerLoader BlenderModelLoader (into-array String ["blend"])))
69 model))
71 (defn meta-data [blender-node key]
72 (if-let [data (.getUserData blender-node "properties")]
73 (.findValue data key)
74 nil))
76 (defn blender-to-jme
77 "Convert from Blender coordinates to JME coordinates"
78 [#^Vector3f in]
79 (Vector3f. (.getX in)
80 (.getZ in)
81 (- (.getY in))))
83 (defn jme-to-blender
84 "Convert from JME coordinates to Blender coordinates"
85 [#^Vector3f in]
86 (Vector3f. (.getX in)
87 (- (.getZ in))
88 (.getY in)))
90 (defn joint-targets
91 "Return the two closest two objects to the joint object, ordered
92 from bottom to top according to the joint's rotation."
93 [#^Node parts #^Node joint]
94 ;;(println (meta-data joint "joint"))
95 (.getWorldRotation joint)
96 (loop [radius (float 0.01)]
97 (let [results (CollisionResults.)]
98 (.collideWith
99 parts
100 (BoundingBox. (.getWorldTranslation joint)
101 radius radius radius)
102 results)
103 (let [targets
104 (distinct
105 (map #(.getGeometry %) results))]
106 (if (>= (count targets) 2)
107 (sort-by
108 #(let [v
109 (jme-to-blender
110 (.mult
111 (.inverse (.getWorldRotation joint))
112 (.subtract (.getWorldTranslation %)
113 (.getWorldTranslation joint))))]
114 (println-repl (.getName %) ":" v)
115 (.dot (Vector3f. 1 1 1)
116 v))
117 (take 2 targets))
118 (recur (float (* radius 2))))))))
120 (defn world-to-local
121 "Convert the world coordinates into coordinates relative to the
122 object (i.e. local coordinates), taking into account the rotation
123 of object."
124 [#^Spatial object world-coordinate]
125 (let [out (Vector3f.)]
126 (.worldToLocal object world-coordinate out) out))
128 (defn local-to-world
129 "Convert the local coordinates into coordinates into world relative
130 coordinates"
131 [#^Spatial object local-coordinate]
132 (let [world-coordinate (Vector3f.)]
133 (.localToWorld object local-coordinate world-coordinate)
134 world-coordinate))
137 (defmulti joint-dispatch
138 "Translate blender pseudo-joints into real JME joints."
139 (fn [constraints & _]
140 (:type constraints)))
142 (defmethod joint-dispatch :point
143 [constraints control-a control-b pivot-a pivot-b rotation]
144 (println-repl "creating POINT2POINT joint")
145 (Point2PointJoint.
146 control-a
147 control-b
148 pivot-a
149 pivot-b))
151 (defmethod joint-dispatch :hinge
152 [constraints control-a control-b pivot-a pivot-b rotation]
153 (println-repl "creating HINGE joint")
154 (let [axis
155 (if-let
156 [axis (:axis constraints)]
157 axis
158 Vector3f/UNIT_X)
159 [limit-1 limit-2] (:limit constraints)
160 hinge-axis
161 (.mult
162 rotation
163 (blender-to-jme axis))]
164 (doto
165 (HingeJoint.
166 control-a
167 control-b
168 pivot-a
169 pivot-b
170 hinge-axis
171 hinge-axis)
172 (.setLimit limit-1 limit-2))))
174 (defmethod joint-dispatch :cone
175 [constraints control-a control-b pivot-a pivot-b rotation]
176 (let [limit-xz (:limit-xz constraints)
177 limit-xy (:limit-xy constraints)
178 twist (:twist constraints)]
180 (println-repl "creating CONE joint")
181 (println-repl rotation)
182 (println-repl
183 "UNIT_X --> " (.mult rotation (Vector3f. 1 0 0)))
184 (println-repl
185 "UNIT_Y --> " (.mult rotation (Vector3f. 0 1 0)))
186 (println-repl
187 "UNIT_Z --> " (.mult rotation (Vector3f. 0 0 1)))
188 (doto
189 (ConeJoint.
190 control-a
191 control-b
192 pivot-a
193 pivot-b
194 rotation
195 rotation)
196 (.setLimit (float limit-xz)
197 (float limit-xy)
198 (float twist)))))
200 (defn connect
201 "here are some examples:
202 {:type :point}
203 {:type :hinge :limit [0 (/ Math/PI 2)] :axis (Vector3f. 0 1 0)}
204 (:axis defaults to (Vector3f. 1 0 0) if not provided for hinge joints)
206 {:type :cone :limit-xz 0]
207 :limit-xy 0]
208 :twist 0]} (use XZY rotation mode in blender!)"
209 [#^Node obj-a #^Node obj-b #^Node joint]
210 (let [control-a (.getControl obj-a RigidBodyControl)
211 control-b (.getControl obj-b RigidBodyControl)
212 joint-center (.getWorldTranslation joint)
213 joint-rotation (.toRotationMatrix (.getWorldRotation joint))
214 pivot-a (world-to-local obj-a joint-center)
215 pivot-b (world-to-local obj-b joint-center)]
217 (if-let [constraints
218 (map-vals
219 eval
220 (read-string
221 (meta-data joint "joint")))]
222 ;; A side-effect of creating a joint registers
223 ;; it with both physics objects which in turn
224 ;; will register the joint with the physics system
225 ;; when the simulation is started.
226 (do
227 (println-repl "creating joint between"
228 (.getName obj-a) "and" (.getName obj-b))
229 (joint-dispatch constraints
230 control-a control-b
231 pivot-a pivot-b
232 joint-rotation))
233 (println-repl "could not find joint meta-data!"))))
235 (defn assemble-creature [#^Node pieces joints]
236 (dorun
237 (map
238 (fn [geom]
239 (let [physics-control
240 (RigidBodyControl.
241 (HullCollisionShape.
242 (.getMesh geom))
243 (if-let [mass (meta-data geom "mass")]
244 (do
245 (println-repl
246 "setting" (.getName geom) "mass to" (float mass))
247 (float mass))
248 (float 1)))]
250 (.addControl geom physics-control)))
251 (filter #(isa? (class %) Geometry )
252 (node-seq pieces))))
253 (dorun
254 (map
255 (fn [joint]
256 (let [[obj-a obj-b]
257 (joint-targets pieces joint)]
258 (connect obj-a obj-b joint)))
259 joints))
260 pieces)
262 (defn blender-creature [blender-path]
263 (let [model (load-blender-model blender-path)
264 joints
265 (if-let [joint-node (.getChild model "joints")]
266 (seq (.getChildren joint-node))
267 (do (println-repl "could not find joints node")
268 []))]
269 (assemble-creature model joints)))
271 (def hand "Models/creature1/one.blend")
273 (def worm "Models/creature1/try-again.blend")
275 (def touch "Models/creature1/touch.blend")
277 (defn worm-model [] (load-blender-model worm))
279 (defn x-ray [#^ColorRGBA color]
280 (doto (Material. (asset-manager)
281 "Common/MatDefs/Misc/Unshaded.j3md")
282 (.setColor "Color" color)
283 (-> (.getAdditionalRenderState)
284 (.setDepthTest false))))
286 (defn test-creature [thing]
287 (let [x-axis
288 (box 1 0.01 0.01 :physical? false :color ColorRGBA/Red)
289 y-axis
290 (box 0.01 1 0.01 :physical? false :color ColorRGBA/Green)
291 z-axis
292 (box 0.01 0.01 1 :physical? false :color ColorRGBA/Blue)]
293 (world
294 (nodify [(blender-creature thing)
295 (box 10 2 10 :position (Vector3f. 0 -9 0)
296 :color ColorRGBA/Gray :mass 0)
297 x-axis y-axis z-axis
298 ])
299 standard-debug-controls
300 (fn [world]
301 (light-up-everything world)
302 (enable-debug world)
303 ;;(com.aurellem.capture.Capture/captureVideo
304 ;; world (file-str "/home/r/proj/ai-videos/hand"))
305 (.setTimer world (NanoTimer.))
306 (set-gravity world (Vector3f. 0 0 0))
307 (speed-up world)
308 )
309 no-op
310 ;;(let [timer (atom 0)]
311 ;; (fn [_ _]
312 ;; (swap! timer inc)
313 ;; (if (= (rem @timer 60) 0)
314 ;; (println-repl (float (/ @timer 60))))))
315 )))
318 (defn colorful []
319 (.getChild (worm-model) "worm-21"))
321 (import jme3tools.converters.ImageToAwt)
323 (import ij.ImagePlus)
325 (defn triangle-indices
326 "Get the triangle vertex indices of a given triangle from a given
327 mesh."
328 [#^Mesh mesh triangle-index]
329 (let [indices (int-array 3)]
330 (.getTriangle mesh triangle-index indices)
331 (vec indices)))
333 (defn uv-coord
334 "Get the uv-coordinates of the vertex named by vertex-index"
335 [#^Mesh mesh vertex-index]
336 (let [UV-buffer
337 (.getData
338 (.getBuffer
339 mesh
340 VertexBuffer$Type/TexCoord))]
341 (Vector2f.
342 (.get UV-buffer (* vertex-index 2))
343 (.get UV-buffer (+ 1 (* vertex-index 2))))))
345 (defn tri-uv-coord
346 "Get the uv-cooridnates of the triangle's verticies."
347 [#^Mesh mesh #^Triangle triangle]
348 (map (partial uv-coord mesh)
349 (triangle-indices mesh (.getIndex triangle))))
351 (defn touch-receptor-image
352 "Return the touch-sensor distribution image in ImagePlus format, or
353 nil if it does not exist."
354 [#^Geometry obj]
355 (let [mat (.getMaterial obj)]
356 (if-let [texture-param
357 (.getTextureParam
358 mat
359 MaterialHelper/TEXTURE_TYPE_DIFFUSE)]
360 (let
361 [texture
362 (.getTextureValue texture-param)
363 im (.getImage texture)]
364 (ImagePlus.
365 "UV-map"
366 (ImageToAwt/convert im false false 0))))))
370 (import ij.process.ImageProcessor)
371 (import java.awt.image.BufferedImage)
373 (defprotocol Frame
374 (frame [this]))
376 (extend-type BufferedImage
377 Frame
378 (frame [image]
379 (merge
380 (apply
381 hash-map
382 (interleave
383 (doall (for [x (range (.getWidth image)) y (range (.getHeight image))]
384 (vector x y)))
385 (doall (for [x (range (.getWidth image)) y (range (.getHeight image))]
386 (let [data (.getRGB image x y)]
387 (hash-map :r (bit-shift-right (bit-and 0xff0000 data) 16)
388 :g (bit-shift-right (bit-and 0x00ff00 data) 8)
389 :b (bit-and 0x0000ff data)))))))
390 {:width (.getWidth image) :height (.getHeight image)})))
393 (extend-type ImagePlus
394 Frame
395 (frame [image+]
396 (frame (.getBufferedImage image+))))
399 (def white -1)
401 (defn filter-pixels
402 "List the coordinates of all pixels matching pred."
403 {:author "Dylan Holmes"}
404 [pred #^ImageProcessor ip]
405 (let
406 [width (.getWidth ip)
407 height (.getHeight ip)]
408 ((fn accumulate [x y matches]
409 (cond
410 (>= y height) matches
411 (>= x width) (recur 0 (inc y) matches)
412 (pred (.getPixel ip x y))
413 (recur (inc x) y (conj matches (Vector2f. x y)))
414 :else (recur (inc x) y matches)))
415 0 0 [])))
417 (defn white-coordinates
418 "List the coordinates of all the white pixels in an image."
419 [#^ImageProcessor ip]
420 (filter-pixels #(= % white) ip))
422 (defn same-side? [p1 p2 ref p]
423 (<=
424 0
425 (.dot
426 (.cross (.subtract p2 p1) (.subtract p p1))
427 (.cross (.subtract p2 p1) (.subtract ref p1)))))
430 (defn triangle->matrix4f
431 "Converts the triangle into a 4x4 matrix of vertices: The first
432 three columns contain the vertices of the triangle; the last
433 contains the unit normal of the triangle. The bottom row is filled
434 with 1s."
435 [#^Triangle t]
436 (let [mat (Matrix4f.)
437 [vert-1 vert-2 vert-3]
438 ((comp vec map) #(.get t %) (range 3))
439 unit-normal (do (.calculateNormal t)(.getNormal t))
440 vertices [vert-1 vert-2 vert-3 unit-normal]]
442 (dorun
443 (for [row (range 4) col (range 3)]
444 (do
445 (.set mat col row (.get (vertices row)col))
446 (.set mat 3 row 1))))
447 mat))
449 (defn triangle-transformation
450 "Returns the affine transformation that converts each vertex in the
451 first triangle into the corresponding vertex in the second
452 triangle."
453 [#^Triangle tri-1 #^Triangle tri-2]
454 (.mult
455 (triangle->matrix4f tri-2)
456 (.invert (triangle->matrix4f tri-1))))
458 (def death (Triangle.
459 (Vector3f. 1 1 1)
460 (Vector3f. 1 2 3)
461 (Vector3f. 5 6 7)))
463 (def death-2 (Triangle.
464 (Vector3f. 2 2 2)
465 (Vector3f. 1 1 1)
466 (Vector3f. 0 1 0)))
468 (defn vector2f->vector3f [v]
469 (Vector3f. (.getX v) (.getY v) 0))
472 (extend-type Triangle
473 Textual
474 (text [t]
475 (println "Triangle: " \newline (.get1 t) \newline
476 (.get2 t) \newline (.get3 t))))
479 (defn map-triangle [f #^Triangle tri]
480 (Triangle.
481 (f 0 (.get1 tri))
482 (f 1 (.get2 tri))
483 (f 2 (.get3 tri))))
485 (defn triangle-seq [#^Triangle tri]
486 [(.get1 tri) (.get2 tri) (.get3 tri)])
488 (defn vector3f-seq [#^Vector3f v]
489 [(.getX v) (.getY v) (.getZ v)])
491 (defn inside-triangle?
492 "Is the point inside the triangle? Now what do we do?
493 You might want to hold on there"
494 {:author "Dylan Holmes"}
495 [tri p]
496 (let [[vert-1 vert-2 vert-3] (triangle-seq tri)]
497 (and
498 (same-side? vert-1 vert-2 vert-3 p)
499 (same-side? vert-2 vert-3 vert-1 p)
500 (same-side? vert-3 vert-1 vert-2 p))))
502 (defn uv-triangle
503 "Convert the mesh triangle into the cooresponding triangle in
504 UV-space. Z-component of these triangles is always zero."
505 [#^Mesh mesh #^Triangle tri]
506 (apply #(Triangle. %1 %2 %3)
507 (map vector2f->vector3f
508 (tri-uv-coord mesh tri))))
510 (defn pixel-triangle
511 "Convert the mesh triange into the corresponding triangle in
512 UV-pixel-space. Z compenent will be zero."
513 [#^Mesh mesh #^Triangle tri width height]
514 (map-triangle (fn [_ v]
515 (Vector3f. (* width (.getX v))
516 (* height (.getY v))
517 0))
518 (uv-triangle mesh tri)))
520 (def rasterize pixel-triangle)
523 (defn triangle-bounds
524 "Dimensions of the bounding square of the triangle in the form
525 [x y width height].
526 Assumes that the triangle lies in the XY plane."
527 [#^Triangle tri]
528 (let [verts (map vector3f-seq (triangle-seq tri))
529 x (apply min (map first verts))
530 y (apply min (map second verts))]
532 [x y
533 (- (apply max (map first verts)) x)
534 (- (apply max (map second verts)) y)
535 ]))
538 (defn locate-feelers
539 "Search the geometry's tactile UV image for touch sensors, returning
540 their positions in geometry-relative coordinates."
541 [#^Geometry geo]
542 (if-let [image (touch-receptor-image geo)]
543 (let [mesh (.getMesh geo)
544 tris (triangles geo)
547 width (.getWidth image)
548 height (.getHeight image)
550 ;; for each triangle
551 sensor-coords
552 (fn [tri]
553 ;; translate triangle to uv-pixel-space
554 (let [uv-tri
555 (pixel-triangle mesh tri width height)
556 bounds (vec (triangle-bounds uv-tri))]
558 ;; get that part of the picture
560 (apply #(.setRoi image %1 %2 %3 %4) bounds)
561 (let [cutout (.crop (.getProcessor image))
562 ;; extract white pixels inside triangle
563 cutout-tri
564 (map-triangle
565 (fn [_ v]
566 (.subtract
567 v
568 (Vector3f. (bounds 0) (bounds 1) (float 0))))
569 uv-tri)
570 whites (filter (partial inside-triangle? cutout-tri)
571 (map vector2f->vector3f
572 (white-coordinates cutout)))
573 ;; translate pixel coordinates to world-space
574 transform (triangle-transformation cutout-tri tri)]
575 (map #(.mult transform %) whites))))]
576 (vec (map sensor-coords tris)))
577 (repeat (count (triangles geo)) [])))
579 (defn enable-touch [#^Geometry geo]
580 (let [feeler-coords (locate-feelers geo)
581 tris (triangles geo)
582 limit 0.1]
583 (fn [node]
584 (let [sensor-origins
585 (map
586 #(map (partial local-to-world geo) %)
587 feeler-coords)
588 triangle-normals
589 (map (partial get-ray-direction geo)
590 tris)
591 rays
592 (flatten
593 (map (fn [origins norm]
594 (map #(doto (Ray. % norm)
595 (.setLimit limit)) origins))
596 sensor-origins triangle-normals))]
597 (for [ray rays]
598 (do
599 (let [results (CollisionResults.)]
600 (.collideWith node ray results)
601 (let [touch-objects
602 (set
603 (filter #(not (= geo %))
604 (map #(.getGeometry %) results)))]
605 (count touch-objects)))))))))
607 (defn touch [#^Node pieces]
608 (let [touch-components
609 (map enable-touch
610 (filter #(isa? (class %) Geometry)
611 (node-seq pieces)))]
612 (fn [node]
613 (reduce into [] (map #(% node) touch-components)))))
620 (defn all-names []
621 (concat
622 (re-split #"\n" (slurp (file-str
623 "/home/r/proj/names/dist.female.first")))
624 (re-split #"\n" (slurp (file-str
625 "/home/r/proj/names/dist.male.first")))
626 (re-split #"\n" (slurp (file-str
627 "/home/r/proj/names/dist.all.last")))))
637 (defrecord LulzLoader [])
638 (defprotocol Lulzable (load-lulz [this]))
639 (extend-type LulzLoader
640 Lulzable
641 (load-lulz [this] (println "the lulz have arrived!")))
644 (defn world-setup [joint]
645 (let [joint-position (Vector3f. 0 0 0)
646 joint-rotation
647 (.toRotationMatrix
648 (.mult
649 (doto (Quaternion.)
650 (.fromAngleAxis
651 (* 1 (/ Math/PI 4))
652 (Vector3f. -1 0 0)))
653 (doto (Quaternion.)
654 (.fromAngleAxis
655 (* 1 (/ Math/PI 2))
656 (Vector3f. 0 0 1)))))
657 top-position (.mult joint-rotation (Vector3f. 8 0 0))
659 origin (doto
660 (sphere 0.1 :physical? false :color ColorRGBA/Cyan
661 :position top-position))
662 top (doto
663 (sphere 0.1 :physical? false :color ColorRGBA/Yellow
664 :position top-position)
666 (.addControl
667 (RigidBodyControl.
668 (CapsuleCollisionShape. 0.5 1.5 1) (float 20))))
669 bottom (doto
670 (sphere 0.1 :physical? false :color ColorRGBA/DarkGray
671 :position (Vector3f. 0 0 0))
672 (.addControl
673 (RigidBodyControl.
674 (CapsuleCollisionShape. 0.5 1.5 1) (float 0))))
675 table (box 10 2 10 :position (Vector3f. 0 -20 0)
676 :color ColorRGBA/Gray :mass 0)
677 a (.getControl top RigidBodyControl)
678 b (.getControl bottom RigidBodyControl)]
680 (cond
681 (= joint :cone)
683 (doto (ConeJoint.
684 a b
685 (world-to-local top joint-position)
686 (world-to-local bottom joint-position)
687 joint-rotation
688 joint-rotation
689 )
692 (.setLimit (* (/ 10) Math/PI)
693 (* (/ 4) Math/PI)
694 0)))
695 [origin top bottom table]))
697 (defn test-joint [joint]
698 (let [[origin top bottom floor] (world-setup joint)
699 control (.getControl top RigidBodyControl)
700 move-up? (atom false)
701 move-down? (atom false)
702 move-left? (atom false)
703 move-right? (atom false)
704 roll-left? (atom false)
705 roll-right? (atom false)
706 timer (atom 0)]
708 (world
709 (nodify [top bottom floor origin])
710 (merge standard-debug-controls
711 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
712 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
713 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
714 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
715 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
716 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
718 (fn [world]
719 (light-up-everything world)
720 (enable-debug world)
721 (set-gravity world (Vector3f. 0 0 0))
722 )
724 (fn [world _]
725 (if (zero? (rem (swap! timer inc) 100))
726 (do
727 ;; (println-repl @timer)
728 (.attachChild (.getRootNode world)
729 (sphere 0.05 :color ColorRGBA/Yellow
730 :position (.getWorldTranslation top)
731 :physical? false))
732 (.attachChild (.getRootNode world)
733 (sphere 0.05 :color ColorRGBA/LightGray
734 :position (.getWorldTranslation bottom)
735 :physical? false))))
737 (if @move-up?
738 (.applyTorque control
739 (.mult (.getPhysicsRotation control)
740 (Vector3f. 0 0 10))))
741 (if @move-down?
742 (.applyTorque control
743 (.mult (.getPhysicsRotation control)
744 (Vector3f. 0 0 -10))))
745 (if @move-left?
746 (.applyTorque control
747 (.mult (.getPhysicsRotation control)
748 (Vector3f. 0 10 0))))
749 (if @move-right?
750 (.applyTorque control
751 (.mult (.getPhysicsRotation control)
752 (Vector3f. 0 -10 0))))
753 (if @roll-left?
754 (.applyTorque control
755 (.mult (.getPhysicsRotation control)
756 (Vector3f. -1 0 0))))
757 (if @roll-right?
758 (.applyTorque control
759 (.mult (.getPhysicsRotation control)
760 (Vector3f. 1 0 0))))))))
763 (defn locate-feelers*
764 "Search the geometry's tactile UV image for touch sensors, returning
765 their positions in geometry-relative coordinates."
766 [#^Geometry geo]
767 (let [uv-image (touch-receptor-image geo)
768 width (.getWidth uv-image)
769 height (.getHeight uv-image)
771 mesh (.getMesh geo)
772 mesh-tris (triangles geo)
774 ;; for each triangle
775 sensor-coords
776 (fn [tri]
777 ;; translate triangle to uv-pixel-space
778 (let [uv-tri
779 (rasterize mesh tri width height)
780 bounds (vec (triangle-bounds uv-tri))]
782 ;; get that part of the picture
784 (apply (partial (memfn setRoi) uv-image) bounds)
785 (let [cutout (.crop (.getProcessor uv-image))
786 ;; extract white pixels inside triangle
787 cutout-tri
788 (map-triangle
789 (fn [_ v]
790 (.subtract
791 v
792 (Vector3f. (bounds 0) (bounds 1) (float 0))))
793 uv-tri)
794 whites (filter (partial inside-triangle? cutout-tri)
795 (map vector2f->vector3f
796 (white-coordinates cutout)))
797 ;; translate pixel coordinates to world-space
798 transform (triangle-transformation cutout-tri tri)]
799 (map #(.mult transform %) whites))))]
803 (for [mesh-tri mesh-tris]
805 (let [uv-tri (rasterize mesh mesh-tri width height)
806 bounding-box (vec (triangle-bounds uv-tri))]
807 (apply (partial (memfn setRoi) uv-image) bounding-box)
808 ))
809 (vec (map sensor-coords mesh-tris))))
812 (defn tactile-coords [#^Geometry obj]
813 (let [mesh (.getMesh obj)
814 num-triangles (.getTriangleCount mesh)
815 num-verticies (.getVertexCount mesh)
816 uv-coord (partial uv-coord mesh)
817 triangle-indices (partial triangle-indices mesh)
818 receptors (touch-receptor-image obj)
819 tris (triangles obj)
820 ]
821 (map
822 (fn [[tri-1 tri-2 tri-3]]
823 (let [width (.getWidth receptors)
824 height (.getHeight receptors)
825 uv-1 (uv-coord tri-1)
826 uv-2 (uv-coord tri-2)
827 uv-3 (uv-coord tri-3)
828 x-coords (map #(.getX %) [uv-1 uv-2 uv-3])
829 y-coords (map #(.getY %) [uv-1 uv-2 uv-3])
830 max-x (Math/ceil (* width (apply max x-coords)))
831 min-x (Math/floor (* width (apply min x-coords)))
832 max-y (Math/ceil (* height (apply max y-coords)))
833 min-y (Math/floor (* height (apply min y-coords)))
835 image-1 (Vector2f. (* width (.getX uv-1))
836 (* height (.getY uv-1)))
837 image-2 (Vector2f. (* width (.getX uv-2))
838 (* height (.getY uv-2)))
839 image-3 (Vector2f. (* width (.getX uv-3))
840 (* height (.getY uv-3)))
841 left-corner
842 (Vector2f. min-x min-y)
843 ]
845 (.setRoi receptors min-x min-y (- max-x min-x) (- max-y min-y))
846 (let [processor (.crop (.getProcessor receptors))]
847 (map
848 #(.add left-corner %)
850 (filter
851 (partial
852 inside-triangle?
853 (.subtract image-1 left-corner)
854 (.subtract image-2 left-corner)
855 (.subtract image-3 left-corner))
856 (white-coordinates processor))))
857 )) (map triangle-indices (range num-triangles)))))
859 #+end_src
861 #+results: body-1
862 : #'cortex.silly/test-joint
865 * COMMENT purgatory
866 #+begin_src clojure
867 (defn bullet-trans []
868 (let [obj-a (sphere 0.5 :color ColorRGBA/Red
869 :position (Vector3f. -10 5 0))
870 obj-b (sphere 0.5 :color ColorRGBA/Blue
871 :position (Vector3f. -10 -5 0)
872 :mass 0)
873 control-a (.getControl obj-a RigidBodyControl)
874 control-b (.getControl obj-b RigidBodyControl)
875 swivel
876 (.toRotationMatrix
877 (doto (Quaternion.)
878 (.fromAngleAxis (/ Math/PI 2)
879 Vector3f/UNIT_X)))]
880 (doto
881 (ConeJoint.
882 control-a control-b
883 (Vector3f. 0 5 0)
884 (Vector3f. 0 -5 0)
885 swivel swivel)
886 (.setLimit (* 0.6 (/ Math/PI 4))
887 (/ Math/PI 4)
888 (* Math/PI 0.8)))
889 (world (nodify
890 [obj-a obj-b])
891 standard-debug-controls
892 enable-debug
893 no-op)))
896 (defn bullet-trans* []
897 (let [obj-a (box 1.5 0.5 0.5 :color ColorRGBA/Red
898 :position (Vector3f. 5 0 0)
899 :mass 90)
900 obj-b (sphere 0.5 :color ColorRGBA/Blue
901 :position (Vector3f. -5 0 0)
902 :mass 0)
903 control-a (.getControl obj-a RigidBodyControl)
904 control-b (.getControl obj-b RigidBodyControl)
905 move-up? (atom nil)
906 move-down? (atom nil)
907 move-left? (atom nil)
908 move-right? (atom nil)
909 roll-left? (atom nil)
910 roll-right? (atom nil)
911 force 100
912 swivel
913 (.toRotationMatrix
914 (doto (Quaternion.)
915 (.fromAngleAxis (/ Math/PI 2)
916 Vector3f/UNIT_X)))
917 x-move
918 (doto (Matrix3f.)
919 (.fromStartEndVectors Vector3f/UNIT_X
920 (.normalize (Vector3f. 1 1 0))))
922 timer (atom 0)]
923 (doto
924 (ConeJoint.
925 control-a control-b
926 (Vector3f. -8 0 0)
927 (Vector3f. 2 0 0)
928 ;;swivel swivel
929 ;;Matrix3f/IDENTITY Matrix3f/IDENTITY
930 x-move Matrix3f/IDENTITY
931 )
932 (.setCollisionBetweenLinkedBodys false)
933 (.setLimit (* 1 (/ Math/PI 4)) ;; twist
934 (* 1 (/ Math/PI 4)) ;; swing span in X-Y plane
935 (* 0 (/ Math/PI 4)))) ;; swing span in Y-Z plane
936 (world (nodify
937 [obj-a obj-b])
938 (merge standard-debug-controls
939 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
940 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
941 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
942 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
943 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
944 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
946 (fn [world]
947 (enable-debug world)
948 (set-gravity world Vector3f/ZERO)
949 )
951 (fn [world _]
953 (if @move-up?
954 (.applyForce control-a
955 (Vector3f. force 0 0)
956 (Vector3f. 0 0 0)))
957 (if @move-down?
958 (.applyForce control-a
959 (Vector3f. (- force) 0 0)
960 (Vector3f. 0 0 0)))
961 (if @move-left?
962 (.applyForce control-a
963 (Vector3f. 0 force 0)
964 (Vector3f. 0 0 0)))
965 (if @move-right?
966 (.applyForce control-a
967 (Vector3f. 0 (- force) 0)
968 (Vector3f. 0 0 0)))
970 (if @roll-left?
971 (.applyForce control-a
972 (Vector3f. 0 0 force)
973 (Vector3f. 0 0 0)))
974 (if @roll-right?
975 (.applyForce control-a
976 (Vector3f. 0 0 (- force))
977 (Vector3f. 0 0 0)))
979 (if (zero? (rem (swap! timer inc) 100))
980 (.attachChild
981 (.getRootNode world)
982 (sphere 0.05 :color ColorRGBA/Yellow
983 :physical? false :position
984 (.getWorldTranslation obj-a)))))
985 )
986 ))
990 #+end_src
993 * COMMENT generate source
994 #+begin_src clojure :tangle ../src/cortex/silly.clj
995 <<body-1>>
996 #+end_src
1002 (defn transform-trianglesdsd
1003 "Transform that converts each vertex in the first triangle
1004 into the corresponding vertex in the second triangle."
1005 [#^Triangle tri-1 #^Triangle tri-2]
1006 (let [in [(.get1 tri-1)
1007 (.get2 tri-1)
1008 (.get3 tri-1)]
1009 out [(.get1 tri-2)
1010 (.get2 tri-2)
1011 (.get3 tri-2)]]
1012 (let [translate (doto (Matrix4f.) (.setTranslation (.negate (in 0))))
1013 in* [(.mult translate (in 0))
1014 (.mult translate (in 1))
1015 (.mult translate (in 2))]
1016 final-translation
1017 (doto (Matrix4f.)
1018 (.setTranslation (out 1)))
1020 rotate-1
1021 (doto (Matrix3f.)
1022 (.fromStartEndVectors
1023 (.normalize
1024 (.subtract
1025 (in* 1) (in* 0)))
1026 (.normalize
1027 (.subtract
1028 (out 1) (out 0)))))
1029 in** [(.mult rotate-1 (in* 0))
1030 (.mult rotate-1 (in* 1))
1031 (.mult rotate-1 (in* 2))]
1032 scale-factor-1
1033 (.mult
1034 (.normalize
1035 (.subtract
1036 (out 1)
1037 (out 0)))
1038 (/ (.length
1039 (.subtract (out 1)
1040 (out 0)))
1041 (.length
1042 (.subtract (in** 1)
1043 (in** 0)))))
1044 scale-1 (doto (Matrix4f.) (.setScale scale-factor-1))
1045 in*** [(.mult scale-1 (in** 0))
1046 (.mult scale-1 (in** 1))
1047 (.mult scale-1 (in** 2))]
1055 (dorun (map println in))
1056 (println)
1057 (dorun (map println in*))
1058 (println)
1059 (dorun (map println in**))
1060 (println)
1061 (dorun (map println in***))
1062 (println)
1064 )))