view org/test-creature.org @ 100:940074adc1d5

can visualize a collection of points now.
author Robert McIntyre <rlm@mit.edu>
date Sat, 14 Jan 2012 01:19:18 -0700
parents b7a3ba5e879b
children 65332841b7d9
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
10 * objectives
11 - [ ] get an overall bitmap-like image for touch
12 - [ ] write code to visuliaze this bitmap
13 - [ ] directly change the UV-pixels to show touch sensor activation
14 - [ ] write an explination for why b&w bitmaps for senses is appropiate
15 - [ ] clean up touch code and write visulazation test
16 - [ ] do the same for eyes
18 * Intro
19 So far, I've made the following senses --
20 - Vision
21 - Hearing
22 - Touch
23 - Proprioception
25 And one effector:
26 - Movement
28 However, the code so far has only enabled these senses, but has not
29 actually implemented them. For example, there is still a lot of work
30 to be done for vision. I need to be able to create an /eyeball/ in
31 simulation that can be moved around and see the world from different
32 angles. I also need to determine weather to use log-polar or cartesian
33 for the visual input, and I need to determine how/wether to
34 disceritise the visual input.
36 I also want to be able to visualize both the sensors and the
37 effectors in pretty pictures. This semi-retarted creature will by my
38 first attempt at bringing everything together.
40 * The creature's body
42 Still going to do an eve-like body in blender, but due to problems
43 importing the joints, etc into jMonkeyEngine3, I',m going to do all
44 the connecting here in clojure code, using the names of the individual
45 components and trial and error. Later, I'll maybe make some sort of
46 creature-building modifications to blender that support whatever
47 discreitized senses I'm going to make.
49 #+name: body-1
50 #+begin_src clojure
51 (ns cortex.silly
52 "let's play!"
53 {:author "Robert McIntyre"})
55 ;; TODO remove this!
56 (require 'cortex.import)
57 (cortex.import/mega-import-jme3)
58 (use '(cortex world util body hearing touch vision))
60 (rlm.rlm-commands/help)
61 (import java.awt.image.BufferedImage)
62 (import javax.swing.JPanel)
63 (import javax.swing.SwingUtilities)
64 (import java.awt.Dimension)
65 (import javax.swing.JFrame)
66 (import java.awt.Dimension)
67 (declare joint-create)
69 (defn view-image
70 "Initailizes a JPanel on which you may draw a BufferedImage.
71 Returns a function that accepts a BufferedImage and draws it to the
72 JPanel."
73 []
74 (let [image
75 (atom
76 (BufferedImage. 1 1 BufferedImage/TYPE_4BYTE_ABGR))
77 panel
78 (proxy [JPanel] []
79 (paint
80 [graphics]
81 (proxy-super paintComponent graphics)
82 (.drawImage graphics @image 0 0 nil)))
83 frame (JFrame. "Display Image")]
84 (SwingUtilities/invokeLater
85 (fn []
86 (doto frame
87 (-> (.getContentPane) (.add panel))
88 (.pack)
89 (.setLocationRelativeTo nil)
90 (.setResizable true)
91 (.setVisible true))))
92 (fn [#^BufferedImage i]
93 (reset! image i)
94 (.setSize frame (+ 8 (.getWidth i)) (+ 28 (.getHeight i)))
95 (.repaint panel 0 0 (.getWidth i) (.getHeight i)))))
97 (defn points->image
98 "Take a sparse collection of points and visuliaze it as a
99 BufferedImage."
100 [points]
101 (let [xs (map first points)
102 ys (map second points)
103 width (- (apply max xs) (apply min xs))
104 height (- (apply max ys) (apply min ys))
105 image (BufferedImage. width height
106 BufferedImage/TYPE_BYTE_BINARY)
110 ))
115 ;;(defn visualize [points]
119 (defn collapse
120 "Take a set of pairs of integers and collapse them into a
121 contigous bitmap."
122 [points]
123 (let [center [0 0]]
125 )
136 (defn load-bullet []
137 (let [sim (world (Node.) {} no-op no-op)]
138 (.enqueue
139 sim
140 (fn []
141 (.stop sim)))
142 (.start sim)))
144 (defn load-blender-model
145 "Load a .blend file using an asset folder relative path."
146 [^String model]
147 (.loadModel
148 (doto (asset-manager)
149 (.registerLoader BlenderModelLoader (into-array String ["blend"])))
150 model))
152 (defn meta-data [blender-node key]
153 (if-let [data (.getUserData blender-node "properties")]
154 (.findValue data key)
155 nil))
157 (defn blender-to-jme
158 "Convert from Blender coordinates to JME coordinates"
159 [#^Vector3f in]
160 (Vector3f. (.getX in)
161 (.getZ in)
162 (- (.getY in))))
164 (defn jme-to-blender
165 "Convert from JME coordinates to Blender coordinates"
166 [#^Vector3f in]
167 (Vector3f. (.getX in)
168 (- (.getZ in))
169 (.getY in)))
171 (defn joint-targets
172 "Return the two closest two objects to the joint object, ordered
173 from bottom to top according to the joint's rotation."
174 [#^Node parts #^Node joint]
175 ;;(println (meta-data joint "joint"))
176 (.getWorldRotation joint)
177 (loop [radius (float 0.01)]
178 (let [results (CollisionResults.)]
179 (.collideWith
180 parts
181 (BoundingBox. (.getWorldTranslation joint)
182 radius radius radius)
183 results)
184 (let [targets
185 (distinct
186 (map #(.getGeometry %) results))]
187 (if (>= (count targets) 2)
188 (sort-by
189 #(let [v
190 (jme-to-blender
191 (.mult
192 (.inverse (.getWorldRotation joint))
193 (.subtract (.getWorldTranslation %)
194 (.getWorldTranslation joint))))]
195 (println-repl (.getName %) ":" v)
196 (.dot (Vector3f. 1 1 1)
197 v))
198 (take 2 targets))
199 (recur (float (* radius 2))))))))
201 (defn world-to-local
202 "Convert the world coordinates into coordinates relative to the
203 object (i.e. local coordinates), taking into account the rotation
204 of object."
205 [#^Spatial object world-coordinate]
206 (let [out (Vector3f.)]
207 (.worldToLocal object world-coordinate out) out))
209 (defn local-to-world
210 "Convert the local coordinates into coordinates into world relative
211 coordinates"
212 [#^Spatial object local-coordinate]
213 (let [world-coordinate (Vector3f.)]
214 (.localToWorld object local-coordinate world-coordinate)
215 world-coordinate))
218 (defmulti joint-dispatch
219 "Translate blender pseudo-joints into real JME joints."
220 (fn [constraints & _]
221 (:type constraints)))
223 (defmethod joint-dispatch :point
224 [constraints control-a control-b pivot-a pivot-b rotation]
225 (println-repl "creating POINT2POINT joint")
226 (Point2PointJoint.
227 control-a
228 control-b
229 pivot-a
230 pivot-b))
232 (defmethod joint-dispatch :hinge
233 [constraints control-a control-b pivot-a pivot-b rotation]
234 (println-repl "creating HINGE joint")
235 (let [axis
236 (if-let
237 [axis (:axis constraints)]
238 axis
239 Vector3f/UNIT_X)
240 [limit-1 limit-2] (:limit constraints)
241 hinge-axis
242 (.mult
243 rotation
244 (blender-to-jme axis))]
245 (doto
246 (HingeJoint.
247 control-a
248 control-b
249 pivot-a
250 pivot-b
251 hinge-axis
252 hinge-axis)
253 (.setLimit limit-1 limit-2))))
255 (defmethod joint-dispatch :cone
256 [constraints control-a control-b pivot-a pivot-b rotation]
257 (let [limit-xz (:limit-xz constraints)
258 limit-xy (:limit-xy constraints)
259 twist (:twist constraints)]
261 (println-repl "creating CONE joint")
262 (println-repl rotation)
263 (println-repl
264 "UNIT_X --> " (.mult rotation (Vector3f. 1 0 0)))
265 (println-repl
266 "UNIT_Y --> " (.mult rotation (Vector3f. 0 1 0)))
267 (println-repl
268 "UNIT_Z --> " (.mult rotation (Vector3f. 0 0 1)))
269 (doto
270 (ConeJoint.
271 control-a
272 control-b
273 pivot-a
274 pivot-b
275 rotation
276 rotation)
277 (.setLimit (float limit-xz)
278 (float limit-xy)
279 (float twist)))))
281 (defn connect
282 "here are some examples:
283 {:type :point}
284 {:type :hinge :limit [0 (/ Math/PI 2)] :axis (Vector3f. 0 1 0)}
285 (:axis defaults to (Vector3f. 1 0 0) if not provided for hinge joints)
287 {:type :cone :limit-xz 0]
288 :limit-xy 0]
289 :twist 0]} (use XZY rotation mode in blender!)"
290 [#^Node obj-a #^Node obj-b #^Node joint]
291 (let [control-a (.getControl obj-a RigidBodyControl)
292 control-b (.getControl obj-b RigidBodyControl)
293 joint-center (.getWorldTranslation joint)
294 joint-rotation (.toRotationMatrix (.getWorldRotation joint))
295 pivot-a (world-to-local obj-a joint-center)
296 pivot-b (world-to-local obj-b joint-center)]
298 (if-let [constraints
299 (map-vals
300 eval
301 (read-string
302 (meta-data joint "joint")))]
303 ;; A side-effect of creating a joint registers
304 ;; it with both physics objects which in turn
305 ;; will register the joint with the physics system
306 ;; when the simulation is started.
307 (do
308 (println-repl "creating joint between"
309 (.getName obj-a) "and" (.getName obj-b))
310 (joint-dispatch constraints
311 control-a control-b
312 pivot-a pivot-b
313 joint-rotation))
314 (println-repl "could not find joint meta-data!"))))
316 (defn assemble-creature [#^Node pieces joints]
317 (dorun
318 (map
319 (fn [geom]
320 (let [physics-control
321 (RigidBodyControl.
322 (HullCollisionShape.
323 (.getMesh geom))
324 (if-let [mass (meta-data geom "mass")]
325 (do
326 (println-repl
327 "setting" (.getName geom) "mass to" (float mass))
328 (float mass))
329 (float 1)))]
331 (.addControl geom physics-control)))
332 (filter #(isa? (class %) Geometry )
333 (node-seq pieces))))
334 (dorun
335 (map
336 (fn [joint]
337 (let [[obj-a obj-b]
338 (joint-targets pieces joint)]
339 (connect obj-a obj-b joint)))
340 joints))
341 pieces)
343 (defn blender-creature [blender-path]
344 (let [model (load-blender-model blender-path)
345 joints
346 (if-let [joint-node (.getChild model "joints")]
347 (seq (.getChildren joint-node))
348 (do (println-repl "could not find joints node")
349 []))]
350 (assemble-creature model joints)))
352 (def hand "Models/creature1/one.blend")
354 (def worm "Models/creature1/try-again.blend")
356 (def touch "Models/creature1/touch.blend")
358 (defn worm-model [] (load-blender-model worm))
360 (defn x-ray [#^ColorRGBA color]
361 (doto (Material. (asset-manager)
362 "Common/MatDefs/Misc/Unshaded.j3md")
363 (.setColor "Color" color)
364 (-> (.getAdditionalRenderState)
365 (.setDepthTest false))))
367 (defn test-creature [thing]
368 (let [x-axis
369 (box 1 0.01 0.01 :physical? false :color ColorRGBA/Red)
370 y-axis
371 (box 0.01 1 0.01 :physical? false :color ColorRGBA/Green)
372 z-axis
373 (box 0.01 0.01 1 :physical? false :color ColorRGBA/Blue)]
374 (world
375 (nodify [(blender-creature thing)
376 (box 10 2 10 :position (Vector3f. 0 -9 0)
377 :color ColorRGBA/Gray :mass 0)
378 x-axis y-axis z-axis
379 ])
380 standard-debug-controls
381 (fn [world]
382 (light-up-everything world)
383 (enable-debug world)
384 ;;(com.aurellem.capture.Capture/captureVideo
385 ;; world (file-str "/home/r/proj/ai-videos/hand"))
386 (.setTimer world (NanoTimer.))
387 (set-gravity world (Vector3f. 0 0 0))
388 (speed-up world)
389 )
390 no-op
391 ;;(let [timer (atom 0)]
392 ;; (fn [_ _]
393 ;; (swap! timer inc)
394 ;; (if (= (rem @timer 60) 0)
395 ;; (println-repl (float (/ @timer 60))))))
396 )))
398 (defn colorful []
399 (.getChild (worm-model) "worm-21"))
401 (import jme3tools.converters.ImageToAwt)
403 (import ij.ImagePlus)
405 (defn triangle-indices
406 "Get the triangle vertex indices of a given triangle from a given
407 mesh."
408 [#^Mesh mesh triangle-index]
409 (let [indices (int-array 3)]
410 (.getTriangle mesh triangle-index indices)
411 (vec indices)))
413 (defn uv-coord
414 "Get the uv-coordinates of the vertex named by vertex-index"
415 [#^Mesh mesh vertex-index]
416 (let [UV-buffer
417 (.getData
418 (.getBuffer
419 mesh
420 VertexBuffer$Type/TexCoord))]
421 (Vector2f.
422 (.get UV-buffer (* vertex-index 2))
423 (.get UV-buffer (+ 1 (* vertex-index 2))))))
425 (defn tri-uv-coord
426 "Get the uv-cooridnates of the triangle's verticies."
427 [#^Mesh mesh #^Triangle triangle]
428 (map (partial uv-coord mesh)
429 (triangle-indices mesh (.getIndex triangle))))
431 (defn touch-receptor-image
432 "Return the touch-sensor distribution image in ImagePlus format, or
433 nil if it does not exist."
434 [#^Geometry obj]
435 (let [mat (.getMaterial obj)]
436 (if-let [texture-param
437 (.getTextureParam
438 mat
439 MaterialHelper/TEXTURE_TYPE_DIFFUSE)]
440 (let
441 [texture
442 (.getTextureValue texture-param)
443 im (.getImage texture)]
444 (ImagePlus.
445 "UV-map"
446 (ImageToAwt/convert im false false 0))))))
448 (import ij.process.ImageProcessor)
449 (import java.awt.image.BufferedImage)
451 (defprotocol Frame
452 (frame [this]))
454 (extend-type BufferedImage
455 Frame
456 (frame [image]
457 (merge
458 (apply
459 hash-map
460 (interleave
461 (doall (for [x (range (.getWidth image)) y (range (.getHeight image))]
462 (vector x y)))
463 (doall (for [x (range (.getWidth image)) y (range (.getHeight image))]
464 (let [data (.getRGB image x y)]
465 (hash-map :r (bit-shift-right (bit-and 0xff0000 data) 16)
466 :g (bit-shift-right (bit-and 0x00ff00 data) 8)
467 :b (bit-and 0x0000ff data)))))))
468 {:width (.getWidth image) :height (.getHeight image)})))
471 (extend-type ImagePlus
472 Frame
473 (frame [image+]
474 (frame (.getBufferedImage image+))))
477 (def white -1)
479 (defn filter-pixels
480 "List the coordinates of all pixels matching pred."
481 {:author "Dylan Holmes"}
482 [pred #^ImageProcessor ip]
483 (let
484 [width (.getWidth ip)
485 height (.getHeight ip)]
486 ((fn accumulate [x y matches]
487 (cond
488 (>= y height) matches
489 (>= x width) (recur 0 (inc y) matches)
490 (pred (.getPixel ip x y))
491 (recur (inc x) y (conj matches (Vector2f. x y)))
492 :else (recur (inc x) y matches)))
493 0 0 [])))
495 (defn white-coordinates
496 "List the coordinates of all the white pixels in an image."
497 [#^ImageProcessor ip]
498 (filter-pixels #(= % white) ip))
500 (defn same-side? [p1 p2 ref p]
501 (<=
502 0
503 (.dot
504 (.cross (.subtract p2 p1) (.subtract p p1))
505 (.cross (.subtract p2 p1) (.subtract ref p1)))))
508 (defn triangle->matrix4f
509 "Converts the triangle into a 4x4 matrix of vertices: The first
510 three columns contain the vertices of the triangle; the last
511 contains the unit normal of the triangle. The bottom row is filled
512 with 1s."
513 [#^Triangle t]
514 (let [mat (Matrix4f.)
515 [vert-1 vert-2 vert-3]
516 ((comp vec map) #(.get t %) (range 3))
517 unit-normal (do (.calculateNormal t)(.getNormal t))
518 vertices [vert-1 vert-2 vert-3 unit-normal]]
520 (dorun
521 (for [row (range 4) col (range 3)]
522 (do
523 (.set mat col row (.get (vertices row)col))
524 (.set mat 3 row 1))))
525 mat))
527 (defn triangle-transformation
528 "Returns the affine transformation that converts each vertex in the
529 first triangle into the corresponding vertex in the second
530 triangle."
531 [#^Triangle tri-1 #^Triangle tri-2]
532 (.mult
533 (triangle->matrix4f tri-2)
534 (.invert (triangle->matrix4f tri-1))))
536 (def death (Triangle.
537 (Vector3f. 1 1 1)
538 (Vector3f. 1 2 3)
539 (Vector3f. 5 6 7)))
541 (def death-2 (Triangle.
542 (Vector3f. 2 2 2)
543 (Vector3f. 1 1 1)
544 (Vector3f. 0 1 0)))
546 (defn vector2f->vector3f [v]
547 (Vector3f. (.getX v) (.getY v) 0))
550 (extend-type Triangle
551 Textual
552 (text [t]
553 (println "Triangle: " \newline (.get1 t) \newline
554 (.get2 t) \newline (.get3 t))))
557 (defn map-triangle [f #^Triangle tri]
558 (Triangle.
559 (f 0 (.get1 tri))
560 (f 1 (.get2 tri))
561 (f 2 (.get3 tri))))
563 (defn triangle-seq [#^Triangle tri]
564 [(.get1 tri) (.get2 tri) (.get3 tri)])
566 (defn vector3f-seq [#^Vector3f v]
567 [(.getX v) (.getY v) (.getZ v)])
569 (defn inside-triangle?
570 "Is the point inside the triangle? Now what do we do?
571 You might want to hold on there"
572 {:author "Dylan Holmes"}
573 [tri p]
574 (let [[vert-1 vert-2 vert-3] (triangle-seq tri)]
575 (and
576 (same-side? vert-1 vert-2 vert-3 p)
577 (same-side? vert-2 vert-3 vert-1 p)
578 (same-side? vert-3 vert-1 vert-2 p))))
580 (defn uv-triangle
581 "Convert the mesh triangle into the cooresponding triangle in
582 UV-space. Z-component of these triangles is always zero."
583 [#^Mesh mesh #^Triangle tri]
584 (apply #(Triangle. %1 %2 %3)
585 (map vector2f->vector3f
586 (tri-uv-coord mesh tri))))
588 (defn pixel-triangle
589 "Convert the mesh triange into the corresponding triangle in
590 UV-pixel-space. Z compenent will be zero."
591 [#^Mesh mesh #^Triangle tri width height]
592 (map-triangle (fn [_ v]
593 (Vector3f. (* width (.getX v))
594 (* height (.getY v))
595 0))
596 (uv-triangle mesh tri)))
598 (def rasterize pixel-triangle)
601 (defn triangle-bounds
602 "Dimensions of the bounding square of the triangle in the form
603 [x y width height].
604 Assumes that the triangle lies in the XY plane."
605 [#^Triangle tri]
606 (let [verts (map vector3f-seq (triangle-seq tri))
607 x (apply min (map first verts))
608 y (apply min (map second verts))]
610 [x y
611 (- (apply max (map first verts)) x)
612 (- (apply max (map second verts)) y)
613 ]))
616 (defn locate-feelers
617 "Search the geometry's tactile UV image for touch sensors, returning
618 their positions in geometry-relative coordinates."
619 [#^Geometry geo]
620 (if-let [image (touch-receptor-image geo)]
621 (let [mesh (.getMesh geo)
622 tris (triangles geo)
625 width (.getWidth image)
626 height (.getHeight image)
628 ;; for each triangle
629 sensor-coords
630 (fn [tri]
631 ;; translate triangle to uv-pixel-space
632 (let [uv-tri
633 (pixel-triangle mesh tri width height)
634 bounds (vec (triangle-bounds uv-tri))]
636 ;; get that part of the picture
638 (apply #(.setRoi image %1 %2 %3 %4) bounds)
639 (let [cutout (.crop (.getProcessor image))
640 ;; extract white pixels inside triangle
641 cutout-tri
642 (map-triangle
643 (fn [_ v]
644 (.subtract
645 v
646 (Vector3f. (bounds 0) (bounds 1) (float 0))))
647 uv-tri)
648 whites (filter (partial inside-triangle? cutout-tri)
649 (map vector2f->vector3f
650 (white-coordinates cutout)))
651 ;; translate pixel coordinates to world-space
652 transform (triangle-transformation cutout-tri tri)]
653 (map #(.mult transform %) whites))))]
654 (vec (map sensor-coords tris)))
655 (repeat (count (triangles geo)) [])))
657 (defn enable-touch [#^Geometry geo]
658 (let [feeler-coords (locate-feelers geo)
659 tris (triangles geo)
660 limit 0.1]
661 (fn [node]
662 (let [sensor-origins
663 (map
664 #(map (partial local-to-world geo) %)
665 feeler-coords)
666 triangle-normals
667 (map (partial get-ray-direction geo)
668 tris)
669 rays
670 (flatten
671 (map (fn [origins norm]
672 (map #(doto (Ray. % norm)
673 (.setLimit limit)) origins))
674 sensor-origins triangle-normals))]
675 (for [ray rays]
676 (do
677 (let [results (CollisionResults.)]
678 (.collideWith node ray results)
679 (let [touch-objects
680 (set
681 (filter #(not (= geo %))
682 (map #(.getGeometry %) results)))]
683 (if (> (count touch-objects) 0)
684 1 0)))))))))
686 (defn touch [#^Node pieces]
687 (let [touch-components
688 (map enable-touch
689 (filter #(isa? (class %) Geometry)
690 (node-seq pieces)))]
691 (fn [node]
692 (reduce into [] (map #(% node) touch-components)))))
694 (defn all-names []
695 (concat
696 (re-split #"\n" (slurp (file-str
697 "/home/r/proj/names/dist.female.first")))
698 (re-split #"\n" (slurp (file-str
699 "/home/r/proj/names/dist.male.first")))
700 (re-split #"\n" (slurp (file-str
701 "/home/r/proj/names/dist.all.last")))))
711 (defrecord LulzLoader [])
712 (defprotocol Lulzable (load-lulz [this]))
713 (extend-type LulzLoader
714 Lulzable
715 (load-lulz [this] (println "the lulz have arrived!")))
718 (defn world-setup [joint]
719 (let [joint-position (Vector3f. 0 0 0)
720 joint-rotation
721 (.toRotationMatrix
722 (.mult
723 (doto (Quaternion.)
724 (.fromAngleAxis
725 (* 1 (/ Math/PI 4))
726 (Vector3f. -1 0 0)))
727 (doto (Quaternion.)
728 (.fromAngleAxis
729 (* 1 (/ Math/PI 2))
730 (Vector3f. 0 0 1)))))
731 top-position (.mult joint-rotation (Vector3f. 8 0 0))
733 origin (doto
734 (sphere 0.1 :physical? false :color ColorRGBA/Cyan
735 :position top-position))
736 top (doto
737 (sphere 0.1 :physical? false :color ColorRGBA/Yellow
738 :position top-position)
740 (.addControl
741 (RigidBodyControl.
742 (CapsuleCollisionShape. 0.5 1.5 1) (float 20))))
743 bottom (doto
744 (sphere 0.1 :physical? false :color ColorRGBA/DarkGray
745 :position (Vector3f. 0 0 0))
746 (.addControl
747 (RigidBodyControl.
748 (CapsuleCollisionShape. 0.5 1.5 1) (float 0))))
749 table (box 10 2 10 :position (Vector3f. 0 -20 0)
750 :color ColorRGBA/Gray :mass 0)
751 a (.getControl top RigidBodyControl)
752 b (.getControl bottom RigidBodyControl)]
754 (cond
755 (= joint :cone)
757 (doto (ConeJoint.
758 a b
759 (world-to-local top joint-position)
760 (world-to-local bottom joint-position)
761 joint-rotation
762 joint-rotation
763 )
766 (.setLimit (* (/ 10) Math/PI)
767 (* (/ 4) Math/PI)
768 0)))
769 [origin top bottom table]))
771 (defn test-joint [joint]
772 (let [[origin top bottom floor] (world-setup joint)
773 control (.getControl top RigidBodyControl)
774 move-up? (atom false)
775 move-down? (atom false)
776 move-left? (atom false)
777 move-right? (atom false)
778 roll-left? (atom false)
779 roll-right? (atom false)
780 timer (atom 0)]
782 (world
783 (nodify [top bottom floor origin])
784 (merge standard-debug-controls
785 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
786 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
787 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
788 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
789 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
790 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
792 (fn [world]
793 (light-up-everything world)
794 (enable-debug world)
795 (set-gravity world (Vector3f. 0 0 0))
796 )
798 (fn [world _]
799 (if (zero? (rem (swap! timer inc) 100))
800 (do
801 ;; (println-repl @timer)
802 (.attachChild (.getRootNode world)
803 (sphere 0.05 :color ColorRGBA/Yellow
804 :position (.getWorldTranslation top)
805 :physical? false))
806 (.attachChild (.getRootNode world)
807 (sphere 0.05 :color ColorRGBA/LightGray
808 :position (.getWorldTranslation bottom)
809 :physical? false))))
811 (if @move-up?
812 (.applyTorque control
813 (.mult (.getPhysicsRotation control)
814 (Vector3f. 0 0 10))))
815 (if @move-down?
816 (.applyTorque control
817 (.mult (.getPhysicsRotation control)
818 (Vector3f. 0 0 -10))))
819 (if @move-left?
820 (.applyTorque control
821 (.mult (.getPhysicsRotation control)
822 (Vector3f. 0 10 0))))
823 (if @move-right?
824 (.applyTorque control
825 (.mult (.getPhysicsRotation control)
826 (Vector3f. 0 -10 0))))
827 (if @roll-left?
828 (.applyTorque control
829 (.mult (.getPhysicsRotation control)
830 (Vector3f. -1 0 0))))
831 (if @roll-right?
832 (.applyTorque control
833 (.mult (.getPhysicsRotation control)
834 (Vector3f. 1 0 0))))))))
837 (defn locate-feelers*
838 "Search the geometry's tactile UV image for touch sensors, returning
839 their positions in geometry-relative coordinates."
840 [#^Geometry geo]
841 (let [uv-image (touch-receptor-image geo)
842 width (.getWidth uv-image)
843 height (.getHeight uv-image)
845 mesh (.getMesh geo)
846 mesh-tris (triangles geo)
848 ;; for each triangle
849 sensor-coords
850 (fn [tri]
851 ;; translate triangle to uv-pixel-space
852 (let [uv-tri
853 (rasterize mesh tri width height)
854 bounds (vec (triangle-bounds uv-tri))]
856 ;; get that part of the picture
858 (apply (partial (memfn setRoi) uv-image) bounds)
859 (let [cutout (.crop (.getProcessor uv-image))
860 ;; extract white pixels inside triangle
861 cutout-tri
862 (map-triangle
863 (fn [_ v]
864 (.subtract
865 v
866 (Vector3f. (bounds 0) (bounds 1) (float 0))))
867 uv-tri)
868 whites (filter (partial inside-triangle? cutout-tri)
869 (map vector2f->vector3f
870 (white-coordinates cutout)))
871 ;; translate pixel coordinates to world-space
872 transform (triangle-transformation cutout-tri tri)]
873 (map #(.mult transform %) whites))))]
877 (for [mesh-tri mesh-tris]
879 (let [uv-tri (rasterize mesh mesh-tri width height)
880 bounding-box (vec (triangle-bounds uv-tri))]
881 (apply (partial (memfn setRoi) uv-image) bounding-box)
882 ))
883 (vec (map sensor-coords mesh-tris))))
886 (defn tactile-coords [#^Geometry obj]
887 (let [mesh (.getMesh obj)
888 num-triangles (.getTriangleCount mesh)
889 num-verticies (.getVertexCount mesh)
890 uv-coord (partial uv-coord mesh)
891 triangle-indices (partial triangle-indices mesh)
892 receptors (touch-receptor-image obj)
893 tris (triangles obj)
894 ]
895 (map
896 (fn [[tri-1 tri-2 tri-3]]
897 (let [width (.getWidth receptors)
898 height (.getHeight receptors)
899 uv-1 (uv-coord tri-1)
900 uv-2 (uv-coord tri-2)
901 uv-3 (uv-coord tri-3)
902 x-coords (map #(.getX %) [uv-1 uv-2 uv-3])
903 y-coords (map #(.getY %) [uv-1 uv-2 uv-3])
904 max-x (Math/ceil (* width (apply max x-coords)))
905 min-x (Math/floor (* width (apply min x-coords)))
906 max-y (Math/ceil (* height (apply max y-coords)))
907 min-y (Math/floor (* height (apply min y-coords)))
909 image-1 (Vector2f. (* width (.getX uv-1))
910 (* height (.getY uv-1)))
911 image-2 (Vector2f. (* width (.getX uv-2))
912 (* height (.getY uv-2)))
913 image-3 (Vector2f. (* width (.getX uv-3))
914 (* height (.getY uv-3)))
915 left-corner
916 (Vector2f. min-x min-y)
917 ]
919 (.setRoi receptors min-x min-y (- max-x min-x) (- max-y min-y))
920 (let [processor (.crop (.getProcessor receptors))]
921 (map
922 #(.add left-corner %)
924 (filter
925 (partial
926 inside-triangle?
927 (.subtract image-1 left-corner)
928 (.subtract image-2 left-corner)
929 (.subtract image-3 left-corner))
930 (white-coordinates processor))))
931 )) (map triangle-indices (range num-triangles)))))
933 #+end_src
935 #+results: body-1
936 : #'cortex.silly/test-joint
939 * COMMENT purgatory
940 #+begin_src clojure
941 (defn bullet-trans []
942 (let [obj-a (sphere 0.5 :color ColorRGBA/Red
943 :position (Vector3f. -10 5 0))
944 obj-b (sphere 0.5 :color ColorRGBA/Blue
945 :position (Vector3f. -10 -5 0)
946 :mass 0)
947 control-a (.getControl obj-a RigidBodyControl)
948 control-b (.getControl obj-b RigidBodyControl)
949 swivel
950 (.toRotationMatrix
951 (doto (Quaternion.)
952 (.fromAngleAxis (/ Math/PI 2)
953 Vector3f/UNIT_X)))]
954 (doto
955 (ConeJoint.
956 control-a control-b
957 (Vector3f. 0 5 0)
958 (Vector3f. 0 -5 0)
959 swivel swivel)
960 (.setLimit (* 0.6 (/ Math/PI 4))
961 (/ Math/PI 4)
962 (* Math/PI 0.8)))
963 (world (nodify
964 [obj-a obj-b])
965 standard-debug-controls
966 enable-debug
967 no-op)))
970 (defn bullet-trans* []
971 (let [obj-a (box 1.5 0.5 0.5 :color ColorRGBA/Red
972 :position (Vector3f. 5 0 0)
973 :mass 90)
974 obj-b (sphere 0.5 :color ColorRGBA/Blue
975 :position (Vector3f. -5 0 0)
976 :mass 0)
977 control-a (.getControl obj-a RigidBodyControl)
978 control-b (.getControl obj-b RigidBodyControl)
979 move-up? (atom nil)
980 move-down? (atom nil)
981 move-left? (atom nil)
982 move-right? (atom nil)
983 roll-left? (atom nil)
984 roll-right? (atom nil)
985 force 100
986 swivel
987 (.toRotationMatrix
988 (doto (Quaternion.)
989 (.fromAngleAxis (/ Math/PI 2)
990 Vector3f/UNIT_X)))
991 x-move
992 (doto (Matrix3f.)
993 (.fromStartEndVectors Vector3f/UNIT_X
994 (.normalize (Vector3f. 1 1 0))))
996 timer (atom 0)]
997 (doto
998 (ConeJoint.
999 control-a control-b
1000 (Vector3f. -8 0 0)
1001 (Vector3f. 2 0 0)
1002 ;;swivel swivel
1003 ;;Matrix3f/IDENTITY Matrix3f/IDENTITY
1004 x-move Matrix3f/IDENTITY
1006 (.setCollisionBetweenLinkedBodys false)
1007 (.setLimit (* 1 (/ Math/PI 4)) ;; twist
1008 (* 1 (/ Math/PI 4)) ;; swing span in X-Y plane
1009 (* 0 (/ Math/PI 4)))) ;; swing span in Y-Z plane
1010 (world (nodify
1011 [obj-a obj-b])
1012 (merge standard-debug-controls
1013 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
1014 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
1015 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
1016 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
1017 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
1018 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
1020 (fn [world]
1021 (enable-debug world)
1022 (set-gravity world Vector3f/ZERO)
1025 (fn [world _]
1027 (if @move-up?
1028 (.applyForce control-a
1029 (Vector3f. force 0 0)
1030 (Vector3f. 0 0 0)))
1031 (if @move-down?
1032 (.applyForce control-a
1033 (Vector3f. (- force) 0 0)
1034 (Vector3f. 0 0 0)))
1035 (if @move-left?
1036 (.applyForce control-a
1037 (Vector3f. 0 force 0)
1038 (Vector3f. 0 0 0)))
1039 (if @move-right?
1040 (.applyForce control-a
1041 (Vector3f. 0 (- force) 0)
1042 (Vector3f. 0 0 0)))
1044 (if @roll-left?
1045 (.applyForce control-a
1046 (Vector3f. 0 0 force)
1047 (Vector3f. 0 0 0)))
1048 (if @roll-right?
1049 (.applyForce control-a
1050 (Vector3f. 0 0 (- force))
1051 (Vector3f. 0 0 0)))
1053 (if (zero? (rem (swap! timer inc) 100))
1054 (.attachChild
1055 (.getRootNode world)
1056 (sphere 0.05 :color ColorRGBA/Yellow
1057 :physical? false :position
1058 (.getWorldTranslation obj-a)))))
1060 ))
1062 (defn transform-trianglesdsd
1063 "Transform that converts each vertex in the first triangle
1064 into the corresponding vertex in the second triangle."
1065 [#^Triangle tri-1 #^Triangle tri-2]
1066 (let [in [(.get1 tri-1)
1067 (.get2 tri-1)
1068 (.get3 tri-1)]
1069 out [(.get1 tri-2)
1070 (.get2 tri-2)
1071 (.get3 tri-2)]]
1072 (let [translate (doto (Matrix4f.) (.setTranslation (.negate (in 0))))
1073 in* [(.mult translate (in 0))
1074 (.mult translate (in 1))
1075 (.mult translate (in 2))]
1076 final-translation
1077 (doto (Matrix4f.)
1078 (.setTranslation (out 1)))
1080 rotate-1
1081 (doto (Matrix3f.)
1082 (.fromStartEndVectors
1083 (.normalize
1084 (.subtract
1085 (in* 1) (in* 0)))
1086 (.normalize
1087 (.subtract
1088 (out 1) (out 0)))))
1089 in** [(.mult rotate-1 (in* 0))
1090 (.mult rotate-1 (in* 1))
1091 (.mult rotate-1 (in* 2))]
1092 scale-factor-1
1093 (.mult
1094 (.normalize
1095 (.subtract
1096 (out 1)
1097 (out 0)))
1098 (/ (.length
1099 (.subtract (out 1)
1100 (out 0)))
1101 (.length
1102 (.subtract (in** 1)
1103 (in** 0)))))
1104 scale-1 (doto (Matrix4f.) (.setScale scale-factor-1))
1105 in*** [(.mult scale-1 (in** 0))
1106 (.mult scale-1 (in** 1))
1107 (.mult scale-1 (in** 2))]
1115 (dorun (map println in))
1116 (println)
1117 (dorun (map println in*))
1118 (println)
1119 (dorun (map println in**))
1120 (println)
1121 (dorun (map println in***))
1122 (println)
1124 ))))
1129 #+end_src
1132 * COMMENT generate source
1133 #+begin_src clojure :tangle ../src/cortex/silly.clj
1134 <<body-1>>
1135 #+end_src