view org/test-creature.org @ 101:65332841b7d9

topological sensor bundling appears to work
author Robert McIntyre <rlm@mit.edu>
date Sat, 14 Jan 2012 04:28:37 -0700
parents 940074adc1d5
children 7eeb940bcbc8
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 (vec (map first points))
102 ys (vec (map second points))
103 x0 (apply min xs)
104 y0 (apply min ys)
105 width (- (apply max xs) x0)
106 height (- (apply max ys) y0)
107 image (BufferedImage. (inc width) (inc height)
108 BufferedImage/TYPE_BYTE_BINARY)]
109 (dorun
110 (for [index (range (count points))]
111 (.setRGB image (- (xs index) x0) (- (ys index) y0) -1)))
113 image))
118 ;;(defn visualize [points]
120 (defn test-data
121 []
122 (vec
123 (for [a (range 0 100 2)
124 b (range 0 100 2)]
125 (vector a b))
126 ))
128 (defn average [coll]
129 (/ (reduce + coll) (count coll)))
131 (defn collapse-1d
132 "One dimensional analogue of collapse"
133 [center line]
134 (let [length (count line)
135 num-above (count (filter (partial < center) line))
136 num-below (- length num-above)]
137 (range (- center num-below)
138 (+ center num-above))
139 ))
141 (defn collapse
142 "Take a set of pairs of integers and collapse them into a
143 contigous bitmap."
144 [points]
145 (let
146 [num-points (count points)
147 center (vector
148 (average (map first points))
149 (average (map first points)))
150 flattened
151 (reduce
152 concat
153 (map
154 (fn [column]
155 (map vector
156 (map first column)
157 (collapse-1d (second center)
158 (map second column))))
159 (partition-by first (sort-by first points))))
160 squeezed
161 (reduce
162 concat
163 (map
164 (fn [row]
165 (map vector
166 (collapse-1d (first center)
167 (map first row))
168 (map second row)))
169 (partition-by second (sort-by second flattened))))]
170 squeezed
171 ))
175 (defn load-bullet []
176 (let [sim (world (Node.) {} no-op no-op)]
177 (.enqueue
178 sim
179 (fn []
180 (.stop sim)))
181 (.start sim)))
183 (defn load-blender-model
184 "Load a .blend file using an asset folder relative path."
185 [^String model]
186 (.loadModel
187 (doto (asset-manager)
188 (.registerLoader BlenderModelLoader (into-array String ["blend"])))
189 model))
191 (defn meta-data [blender-node key]
192 (if-let [data (.getUserData blender-node "properties")]
193 (.findValue data key)
194 nil))
196 (defn blender-to-jme
197 "Convert from Blender coordinates to JME coordinates"
198 [#^Vector3f in]
199 (Vector3f. (.getX in)
200 (.getZ in)
201 (- (.getY in))))
203 (defn jme-to-blender
204 "Convert from JME coordinates to Blender coordinates"
205 [#^Vector3f in]
206 (Vector3f. (.getX in)
207 (- (.getZ in))
208 (.getY in)))
210 (defn joint-targets
211 "Return the two closest two objects to the joint object, ordered
212 from bottom to top according to the joint's rotation."
213 [#^Node parts #^Node joint]
214 ;;(println (meta-data joint "joint"))
215 (.getWorldRotation joint)
216 (loop [radius (float 0.01)]
217 (let [results (CollisionResults.)]
218 (.collideWith
219 parts
220 (BoundingBox. (.getWorldTranslation joint)
221 radius radius radius)
222 results)
223 (let [targets
224 (distinct
225 (map #(.getGeometry %) results))]
226 (if (>= (count targets) 2)
227 (sort-by
228 #(let [v
229 (jme-to-blender
230 (.mult
231 (.inverse (.getWorldRotation joint))
232 (.subtract (.getWorldTranslation %)
233 (.getWorldTranslation joint))))]
234 (println-repl (.getName %) ":" v)
235 (.dot (Vector3f. 1 1 1)
236 v))
237 (take 2 targets))
238 (recur (float (* radius 2))))))))
240 (defn world-to-local
241 "Convert the world coordinates into coordinates relative to the
242 object (i.e. local coordinates), taking into account the rotation
243 of object."
244 [#^Spatial object world-coordinate]
245 (let [out (Vector3f.)]
246 (.worldToLocal object world-coordinate out) out))
248 (defn local-to-world
249 "Convert the local coordinates into coordinates into world relative
250 coordinates"
251 [#^Spatial object local-coordinate]
252 (let [world-coordinate (Vector3f.)]
253 (.localToWorld object local-coordinate world-coordinate)
254 world-coordinate))
257 (defmulti joint-dispatch
258 "Translate blender pseudo-joints into real JME joints."
259 (fn [constraints & _]
260 (:type constraints)))
262 (defmethod joint-dispatch :point
263 [constraints control-a control-b pivot-a pivot-b rotation]
264 (println-repl "creating POINT2POINT joint")
265 (Point2PointJoint.
266 control-a
267 control-b
268 pivot-a
269 pivot-b))
271 (defmethod joint-dispatch :hinge
272 [constraints control-a control-b pivot-a pivot-b rotation]
273 (println-repl "creating HINGE joint")
274 (let [axis
275 (if-let
276 [axis (:axis constraints)]
277 axis
278 Vector3f/UNIT_X)
279 [limit-1 limit-2] (:limit constraints)
280 hinge-axis
281 (.mult
282 rotation
283 (blender-to-jme axis))]
284 (doto
285 (HingeJoint.
286 control-a
287 control-b
288 pivot-a
289 pivot-b
290 hinge-axis
291 hinge-axis)
292 (.setLimit limit-1 limit-2))))
294 (defmethod joint-dispatch :cone
295 [constraints control-a control-b pivot-a pivot-b rotation]
296 (let [limit-xz (:limit-xz constraints)
297 limit-xy (:limit-xy constraints)
298 twist (:twist constraints)]
300 (println-repl "creating CONE joint")
301 (println-repl rotation)
302 (println-repl
303 "UNIT_X --> " (.mult rotation (Vector3f. 1 0 0)))
304 (println-repl
305 "UNIT_Y --> " (.mult rotation (Vector3f. 0 1 0)))
306 (println-repl
307 "UNIT_Z --> " (.mult rotation (Vector3f. 0 0 1)))
308 (doto
309 (ConeJoint.
310 control-a
311 control-b
312 pivot-a
313 pivot-b
314 rotation
315 rotation)
316 (.setLimit (float limit-xz)
317 (float limit-xy)
318 (float twist)))))
320 (defn connect
321 "here are some examples:
322 {:type :point}
323 {:type :hinge :limit [0 (/ Math/PI 2)] :axis (Vector3f. 0 1 0)}
324 (:axis defaults to (Vector3f. 1 0 0) if not provided for hinge joints)
326 {:type :cone :limit-xz 0]
327 :limit-xy 0]
328 :twist 0]} (use XZY rotation mode in blender!)"
329 [#^Node obj-a #^Node obj-b #^Node joint]
330 (let [control-a (.getControl obj-a RigidBodyControl)
331 control-b (.getControl obj-b RigidBodyControl)
332 joint-center (.getWorldTranslation joint)
333 joint-rotation (.toRotationMatrix (.getWorldRotation joint))
334 pivot-a (world-to-local obj-a joint-center)
335 pivot-b (world-to-local obj-b joint-center)]
337 (if-let [constraints
338 (map-vals
339 eval
340 (read-string
341 (meta-data joint "joint")))]
342 ;; A side-effect of creating a joint registers
343 ;; it with both physics objects which in turn
344 ;; will register the joint with the physics system
345 ;; when the simulation is started.
346 (do
347 (println-repl "creating joint between"
348 (.getName obj-a) "and" (.getName obj-b))
349 (joint-dispatch constraints
350 control-a control-b
351 pivot-a pivot-b
352 joint-rotation))
353 (println-repl "could not find joint meta-data!"))))
355 (defn assemble-creature [#^Node pieces joints]
356 (dorun
357 (map
358 (fn [geom]
359 (let [physics-control
360 (RigidBodyControl.
361 (HullCollisionShape.
362 (.getMesh geom))
363 (if-let [mass (meta-data geom "mass")]
364 (do
365 (println-repl
366 "setting" (.getName geom) "mass to" (float mass))
367 (float mass))
368 (float 1)))]
370 (.addControl geom physics-control)))
371 (filter #(isa? (class %) Geometry )
372 (node-seq pieces))))
373 (dorun
374 (map
375 (fn [joint]
376 (let [[obj-a obj-b]
377 (joint-targets pieces joint)]
378 (connect obj-a obj-b joint)))
379 joints))
380 pieces)
382 (defn blender-creature [blender-path]
383 (let [model (load-blender-model blender-path)
384 joints
385 (if-let [joint-node (.getChild model "joints")]
386 (seq (.getChildren joint-node))
387 (do (println-repl "could not find joints node")
388 []))]
389 (assemble-creature model joints)))
391 (def hand "Models/creature1/one.blend")
393 (def worm "Models/creature1/try-again.blend")
395 (def touch "Models/creature1/touch.blend")
397 (defn worm-model [] (load-blender-model worm))
399 (defn x-ray [#^ColorRGBA color]
400 (doto (Material. (asset-manager)
401 "Common/MatDefs/Misc/Unshaded.j3md")
402 (.setColor "Color" color)
403 (-> (.getAdditionalRenderState)
404 (.setDepthTest false))))
406 (defn test-creature [thing]
407 (let [x-axis
408 (box 1 0.01 0.01 :physical? false :color ColorRGBA/Red)
409 y-axis
410 (box 0.01 1 0.01 :physical? false :color ColorRGBA/Green)
411 z-axis
412 (box 0.01 0.01 1 :physical? false :color ColorRGBA/Blue)]
413 (world
414 (nodify [(blender-creature thing)
415 (box 10 2 10 :position (Vector3f. 0 -9 0)
416 :color ColorRGBA/Gray :mass 0)
417 x-axis y-axis z-axis
418 ])
419 standard-debug-controls
420 (fn [world]
421 (light-up-everything world)
422 (enable-debug world)
423 ;;(com.aurellem.capture.Capture/captureVideo
424 ;; world (file-str "/home/r/proj/ai-videos/hand"))
425 (.setTimer world (NanoTimer.))
426 (set-gravity world (Vector3f. 0 0 0))
427 (speed-up world)
428 )
429 no-op
430 ;;(let [timer (atom 0)]
431 ;; (fn [_ _]
432 ;; (swap! timer inc)
433 ;; (if (= (rem @timer 60) 0)
434 ;; (println-repl (float (/ @timer 60))))))
435 )))
437 (defn colorful []
438 (.getChild (worm-model) "worm-21"))
440 (import jme3tools.converters.ImageToAwt)
442 (import ij.ImagePlus)
444 (defn triangle-indices
445 "Get the triangle vertex indices of a given triangle from a given
446 mesh."
447 [#^Mesh mesh triangle-index]
448 (let [indices (int-array 3)]
449 (.getTriangle mesh triangle-index indices)
450 (vec indices)))
452 (defn uv-coord
453 "Get the uv-coordinates of the vertex named by vertex-index"
454 [#^Mesh mesh vertex-index]
455 (let [UV-buffer
456 (.getData
457 (.getBuffer
458 mesh
459 VertexBuffer$Type/TexCoord))]
460 (Vector2f.
461 (.get UV-buffer (* vertex-index 2))
462 (.get UV-buffer (+ 1 (* vertex-index 2))))))
464 (defn tri-uv-coord
465 "Get the uv-cooridnates of the triangle's verticies."
466 [#^Mesh mesh #^Triangle triangle]
467 (map (partial uv-coord mesh)
468 (triangle-indices mesh (.getIndex triangle))))
470 (defn touch-receptor-image
471 "Return the touch-sensor distribution image in ImagePlus format, or
472 nil if it does not exist."
473 [#^Geometry obj]
474 (let [mat (.getMaterial obj)]
475 (if-let [texture-param
476 (.getTextureParam
477 mat
478 MaterialHelper/TEXTURE_TYPE_DIFFUSE)]
479 (let
480 [texture
481 (.getTextureValue texture-param)
482 im (.getImage texture)]
483 (ImagePlus.
484 "UV-map"
485 (ImageToAwt/convert im false false 0))))))
487 (import ij.process.ImageProcessor)
488 (import java.awt.image.BufferedImage)
490 (defprotocol Frame
491 (frame [this]))
493 (extend-type BufferedImage
494 Frame
495 (frame [image]
496 (merge
497 (apply
498 hash-map
499 (interleave
500 (doall (for [x (range (.getWidth image)) y (range (.getHeight image))]
501 (vector x y)))
502 (doall (for [x (range (.getWidth image)) y (range (.getHeight image))]
503 (let [data (.getRGB image x y)]
504 (hash-map :r (bit-shift-right (bit-and 0xff0000 data) 16)
505 :g (bit-shift-right (bit-and 0x00ff00 data) 8)
506 :b (bit-and 0x0000ff data)))))))
507 {:width (.getWidth image) :height (.getHeight image)})))
510 (extend-type ImagePlus
511 Frame
512 (frame [image+]
513 (frame (.getBufferedImage image+))))
516 (def white -1)
518 (defn filter-pixels
519 "List the coordinates of all pixels matching pred."
520 {:author "Dylan Holmes"}
521 [pred #^ImageProcessor ip]
522 (let
523 [width (.getWidth ip)
524 height (.getHeight ip)]
525 ((fn accumulate [x y matches]
526 (cond
527 (>= y height) matches
528 (>= x width) (recur 0 (inc y) matches)
529 (pred (.getPixel ip x y))
530 (recur (inc x) y (conj matches (Vector2f. x y)))
531 :else (recur (inc x) y matches)))
532 0 0 [])))
534 (defn white-coordinates
535 "List the coordinates of all the white pixels in an image."
536 [#^ImageProcessor ip]
537 (filter-pixels #(= % white) ip))
539 (defn same-side? [p1 p2 ref p]
540 (<=
541 0
542 (.dot
543 (.cross (.subtract p2 p1) (.subtract p p1))
544 (.cross (.subtract p2 p1) (.subtract ref p1)))))
547 (defn triangle->matrix4f
548 "Converts the triangle into a 4x4 matrix of vertices: The first
549 three columns contain the vertices of the triangle; the last
550 contains the unit normal of the triangle. The bottom row is filled
551 with 1s."
552 [#^Triangle t]
553 (let [mat (Matrix4f.)
554 [vert-1 vert-2 vert-3]
555 ((comp vec map) #(.get t %) (range 3))
556 unit-normal (do (.calculateNormal t)(.getNormal t))
557 vertices [vert-1 vert-2 vert-3 unit-normal]]
559 (dorun
560 (for [row (range 4) col (range 3)]
561 (do
562 (.set mat col row (.get (vertices row)col))
563 (.set mat 3 row 1))))
564 mat))
566 (defn triangle-transformation
567 "Returns the affine transformation that converts each vertex in the
568 first triangle into the corresponding vertex in the second
569 triangle."
570 [#^Triangle tri-1 #^Triangle tri-2]
571 (.mult
572 (triangle->matrix4f tri-2)
573 (.invert (triangle->matrix4f tri-1))))
575 (def death (Triangle.
576 (Vector3f. 1 1 1)
577 (Vector3f. 1 2 3)
578 (Vector3f. 5 6 7)))
580 (def death-2 (Triangle.
581 (Vector3f. 2 2 2)
582 (Vector3f. 1 1 1)
583 (Vector3f. 0 1 0)))
585 (defn vector2f->vector3f [v]
586 (Vector3f. (.getX v) (.getY v) 0))
589 (extend-type Triangle
590 Textual
591 (text [t]
592 (println "Triangle: " \newline (.get1 t) \newline
593 (.get2 t) \newline (.get3 t))))
596 (defn map-triangle [f #^Triangle tri]
597 (Triangle.
598 (f 0 (.get1 tri))
599 (f 1 (.get2 tri))
600 (f 2 (.get3 tri))))
602 (defn triangle-seq [#^Triangle tri]
603 [(.get1 tri) (.get2 tri) (.get3 tri)])
605 (defn vector3f-seq [#^Vector3f v]
606 [(.getX v) (.getY v) (.getZ v)])
608 (defn inside-triangle?
609 "Is the point inside the triangle? Now what do we do?
610 You might want to hold on there"
611 {:author "Dylan Holmes"}
612 [tri p]
613 (let [[vert-1 vert-2 vert-3] (triangle-seq tri)]
614 (and
615 (same-side? vert-1 vert-2 vert-3 p)
616 (same-side? vert-2 vert-3 vert-1 p)
617 (same-side? vert-3 vert-1 vert-2 p))))
619 (defn uv-triangle
620 "Convert the mesh triangle into the cooresponding triangle in
621 UV-space. Z-component of these triangles is always zero."
622 [#^Mesh mesh #^Triangle tri]
623 (apply #(Triangle. %1 %2 %3)
624 (map vector2f->vector3f
625 (tri-uv-coord mesh tri))))
627 (defn pixel-triangle
628 "Convert the mesh triange into the corresponding triangle in
629 UV-pixel-space. Z compenent will be zero."
630 [#^Mesh mesh #^Triangle tri width height]
631 (map-triangle (fn [_ v]
632 (Vector3f. (* width (.getX v))
633 (* height (.getY v))
634 0))
635 (uv-triangle mesh tri)))
637 (def rasterize pixel-triangle)
640 (defn triangle-bounds
641 "Dimensions of the bounding square of the triangle in the form
642 [x y width height].
643 Assumes that the triangle lies in the XY plane."
644 [#^Triangle tri]
645 (let [verts (map vector3f-seq (triangle-seq tri))
646 x (apply min (map first verts))
647 y (apply min (map second verts))]
649 [x y
650 (- (apply max (map first verts)) x)
651 (- (apply max (map second verts)) y)
652 ]))
655 (defn locate-feelers
656 "Search the geometry's tactile UV image for touch sensors, returning
657 their positions in geometry-relative coordinates."
658 [#^Geometry geo]
659 (if-let [image (touch-receptor-image geo)]
660 (let [mesh (.getMesh geo)
661 tris (triangles geo)
664 width (.getWidth image)
665 height (.getHeight image)
667 ;; for each triangle
668 sensor-coords
669 (fn [tri]
670 ;; translate triangle to uv-pixel-space
671 (let [uv-tri
672 (pixel-triangle mesh tri width height)
673 bounds (vec (triangle-bounds uv-tri))]
675 ;; get that part of the picture
677 (apply #(.setRoi image %1 %2 %3 %4) bounds)
678 (let [cutout (.crop (.getProcessor image))
679 ;; extract white pixels inside triangle
680 cutout-tri
681 (map-triangle
682 (fn [_ v]
683 (.subtract
684 v
685 (Vector3f. (bounds 0) (bounds 1) (float 0))))
686 uv-tri)
687 whites (filter (partial inside-triangle? cutout-tri)
688 (map vector2f->vector3f
689 (white-coordinates cutout)))
690 ;; translate pixel coordinates to world-space
691 transform (triangle-transformation cutout-tri tri)]
692 (map #(.mult transform %) whites))))]
693 (vec (map sensor-coords tris)))
694 (repeat (count (triangles geo)) [])))
696 (defn enable-touch [#^Geometry geo]
697 (let [feeler-coords (locate-feelers geo)
698 tris (triangles geo)
699 limit 0.1]
700 (fn [node]
701 (let [sensor-origins
702 (map
703 #(map (partial local-to-world geo) %)
704 feeler-coords)
705 triangle-normals
706 (map (partial get-ray-direction geo)
707 tris)
708 rays
709 (flatten
710 (map (fn [origins norm]
711 (map #(doto (Ray. % norm)
712 (.setLimit limit)) origins))
713 sensor-origins triangle-normals))]
714 (for [ray rays]
715 (do
716 (let [results (CollisionResults.)]
717 (.collideWith node ray results)
718 (let [touch-objects
719 (set
720 (filter #(not (= geo %))
721 (map #(.getGeometry %) results)))]
722 (if (> (count touch-objects) 0)
723 1 0)))))))))
725 (defn touch [#^Node pieces]
726 (let [touch-components
727 (map enable-touch
728 (filter #(isa? (class %) Geometry)
729 (node-seq pieces)))]
730 (fn [node]
731 (reduce into [] (map #(% node) touch-components)))))
733 (defn all-names []
734 (concat
735 (re-split #"\n" (slurp (file-str
736 "/home/r/proj/names/dist.female.first")))
737 (re-split #"\n" (slurp (file-str
738 "/home/r/proj/names/dist.male.first")))
739 (re-split #"\n" (slurp (file-str
740 "/home/r/proj/names/dist.all.last")))))
750 (defrecord LulzLoader [])
751 (defprotocol Lulzable (load-lulz [this]))
752 (extend-type LulzLoader
753 Lulzable
754 (load-lulz [this] (println "the lulz have arrived!")))
757 (defn world-setup [joint]
758 (let [joint-position (Vector3f. 0 0 0)
759 joint-rotation
760 (.toRotationMatrix
761 (.mult
762 (doto (Quaternion.)
763 (.fromAngleAxis
764 (* 1 (/ Math/PI 4))
765 (Vector3f. -1 0 0)))
766 (doto (Quaternion.)
767 (.fromAngleAxis
768 (* 1 (/ Math/PI 2))
769 (Vector3f. 0 0 1)))))
770 top-position (.mult joint-rotation (Vector3f. 8 0 0))
772 origin (doto
773 (sphere 0.1 :physical? false :color ColorRGBA/Cyan
774 :position top-position))
775 top (doto
776 (sphere 0.1 :physical? false :color ColorRGBA/Yellow
777 :position top-position)
779 (.addControl
780 (RigidBodyControl.
781 (CapsuleCollisionShape. 0.5 1.5 1) (float 20))))
782 bottom (doto
783 (sphere 0.1 :physical? false :color ColorRGBA/DarkGray
784 :position (Vector3f. 0 0 0))
785 (.addControl
786 (RigidBodyControl.
787 (CapsuleCollisionShape. 0.5 1.5 1) (float 0))))
788 table (box 10 2 10 :position (Vector3f. 0 -20 0)
789 :color ColorRGBA/Gray :mass 0)
790 a (.getControl top RigidBodyControl)
791 b (.getControl bottom RigidBodyControl)]
793 (cond
794 (= joint :cone)
796 (doto (ConeJoint.
797 a b
798 (world-to-local top joint-position)
799 (world-to-local bottom joint-position)
800 joint-rotation
801 joint-rotation
802 )
805 (.setLimit (* (/ 10) Math/PI)
806 (* (/ 4) Math/PI)
807 0)))
808 [origin top bottom table]))
810 (defn test-joint [joint]
811 (let [[origin top bottom floor] (world-setup joint)
812 control (.getControl top RigidBodyControl)
813 move-up? (atom false)
814 move-down? (atom false)
815 move-left? (atom false)
816 move-right? (atom false)
817 roll-left? (atom false)
818 roll-right? (atom false)
819 timer (atom 0)]
821 (world
822 (nodify [top bottom floor origin])
823 (merge standard-debug-controls
824 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
825 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
826 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
827 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
828 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
829 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
831 (fn [world]
832 (light-up-everything world)
833 (enable-debug world)
834 (set-gravity world (Vector3f. 0 0 0))
835 )
837 (fn [world _]
838 (if (zero? (rem (swap! timer inc) 100))
839 (do
840 ;; (println-repl @timer)
841 (.attachChild (.getRootNode world)
842 (sphere 0.05 :color ColorRGBA/Yellow
843 :position (.getWorldTranslation top)
844 :physical? false))
845 (.attachChild (.getRootNode world)
846 (sphere 0.05 :color ColorRGBA/LightGray
847 :position (.getWorldTranslation bottom)
848 :physical? false))))
850 (if @move-up?
851 (.applyTorque control
852 (.mult (.getPhysicsRotation control)
853 (Vector3f. 0 0 10))))
854 (if @move-down?
855 (.applyTorque control
856 (.mult (.getPhysicsRotation control)
857 (Vector3f. 0 0 -10))))
858 (if @move-left?
859 (.applyTorque control
860 (.mult (.getPhysicsRotation control)
861 (Vector3f. 0 10 0))))
862 (if @move-right?
863 (.applyTorque control
864 (.mult (.getPhysicsRotation control)
865 (Vector3f. 0 -10 0))))
866 (if @roll-left?
867 (.applyTorque control
868 (.mult (.getPhysicsRotation control)
869 (Vector3f. -1 0 0))))
870 (if @roll-right?
871 (.applyTorque control
872 (.mult (.getPhysicsRotation control)
873 (Vector3f. 1 0 0))))))))
876 (defn locate-feelers*
877 "Search the geometry's tactile UV image for touch sensors, returning
878 their positions in geometry-relative coordinates."
879 [#^Geometry geo]
880 (let [uv-image (touch-receptor-image geo)
881 width (.getWidth uv-image)
882 height (.getHeight uv-image)
884 mesh (.getMesh geo)
885 mesh-tris (triangles geo)
887 ;; for each triangle
888 sensor-coords
889 (fn [tri]
890 ;; translate triangle to uv-pixel-space
891 (let [uv-tri
892 (rasterize mesh tri width height)
893 bounds (vec (triangle-bounds uv-tri))]
895 ;; get that part of the picture
897 (apply (partial (memfn setRoi) uv-image) bounds)
898 (let [cutout (.crop (.getProcessor uv-image))
899 ;; extract white pixels inside triangle
900 cutout-tri
901 (map-triangle
902 (fn [_ v]
903 (.subtract
904 v
905 (Vector3f. (bounds 0) (bounds 1) (float 0))))
906 uv-tri)
907 whites (filter (partial inside-triangle? cutout-tri)
908 (map vector2f->vector3f
909 (white-coordinates cutout)))
910 ;; translate pixel coordinates to world-space
911 transform (triangle-transformation cutout-tri tri)]
912 (map #(.mult transform %) whites))))]
916 (for [mesh-tri mesh-tris]
918 (let [uv-tri (rasterize mesh mesh-tri width height)
919 bounding-box (vec (triangle-bounds uv-tri))]
920 (apply (partial (memfn setRoi) uv-image) bounding-box)
921 ))
922 (vec (map sensor-coords mesh-tris))))
925 (defn tactile-coords [#^Geometry obj]
926 (let [mesh (.getMesh obj)
927 num-triangles (.getTriangleCount mesh)
928 num-verticies (.getVertexCount mesh)
929 uv-coord (partial uv-coord mesh)
930 triangle-indices (partial triangle-indices mesh)
931 receptors (touch-receptor-image obj)
932 tris (triangles obj)
933 ]
934 (map
935 (fn [[tri-1 tri-2 tri-3]]
936 (let [width (.getWidth receptors)
937 height (.getHeight receptors)
938 uv-1 (uv-coord tri-1)
939 uv-2 (uv-coord tri-2)
940 uv-3 (uv-coord tri-3)
941 x-coords (map #(.getX %) [uv-1 uv-2 uv-3])
942 y-coords (map #(.getY %) [uv-1 uv-2 uv-3])
943 max-x (Math/ceil (* width (apply max x-coords)))
944 min-x (Math/floor (* width (apply min x-coords)))
945 max-y (Math/ceil (* height (apply max y-coords)))
946 min-y (Math/floor (* height (apply min y-coords)))
948 image-1 (Vector2f. (* width (.getX uv-1))
949 (* height (.getY uv-1)))
950 image-2 (Vector2f. (* width (.getX uv-2))
951 (* height (.getY uv-2)))
952 image-3 (Vector2f. (* width (.getX uv-3))
953 (* height (.getY uv-3)))
954 left-corner
955 (Vector2f. min-x min-y)
956 ]
958 (.setRoi receptors min-x min-y (- max-x min-x) (- max-y min-y))
959 (let [processor (.crop (.getProcessor receptors))]
960 (map
961 #(.add left-corner %)
963 (filter
964 (partial
965 inside-triangle?
966 (.subtract image-1 left-corner)
967 (.subtract image-2 left-corner)
968 (.subtract image-3 left-corner))
969 (white-coordinates processor))))
970 )) (map triangle-indices (range num-triangles)))))
972 #+end_src
974 #+results: body-1
975 : #'cortex.silly/test-joint
978 * COMMENT purgatory
979 #+begin_src clojure
980 (defn bullet-trans []
981 (let [obj-a (sphere 0.5 :color ColorRGBA/Red
982 :position (Vector3f. -10 5 0))
983 obj-b (sphere 0.5 :color ColorRGBA/Blue
984 :position (Vector3f. -10 -5 0)
985 :mass 0)
986 control-a (.getControl obj-a RigidBodyControl)
987 control-b (.getControl obj-b RigidBodyControl)
988 swivel
989 (.toRotationMatrix
990 (doto (Quaternion.)
991 (.fromAngleAxis (/ Math/PI 2)
992 Vector3f/UNIT_X)))]
993 (doto
994 (ConeJoint.
995 control-a control-b
996 (Vector3f. 0 5 0)
997 (Vector3f. 0 -5 0)
998 swivel swivel)
999 (.setLimit (* 0.6 (/ Math/PI 4))
1000 (/ Math/PI 4)
1001 (* Math/PI 0.8)))
1002 (world (nodify
1003 [obj-a obj-b])
1004 standard-debug-controls
1005 enable-debug
1006 no-op)))
1009 (defn bullet-trans* []
1010 (let [obj-a (box 1.5 0.5 0.5 :color ColorRGBA/Red
1011 :position (Vector3f. 5 0 0)
1012 :mass 90)
1013 obj-b (sphere 0.5 :color ColorRGBA/Blue
1014 :position (Vector3f. -5 0 0)
1015 :mass 0)
1016 control-a (.getControl obj-a RigidBodyControl)
1017 control-b (.getControl obj-b RigidBodyControl)
1018 move-up? (atom nil)
1019 move-down? (atom nil)
1020 move-left? (atom nil)
1021 move-right? (atom nil)
1022 roll-left? (atom nil)
1023 roll-right? (atom nil)
1024 force 100
1025 swivel
1026 (.toRotationMatrix
1027 (doto (Quaternion.)
1028 (.fromAngleAxis (/ Math/PI 2)
1029 Vector3f/UNIT_X)))
1030 x-move
1031 (doto (Matrix3f.)
1032 (.fromStartEndVectors Vector3f/UNIT_X
1033 (.normalize (Vector3f. 1 1 0))))
1035 timer (atom 0)]
1036 (doto
1037 (ConeJoint.
1038 control-a control-b
1039 (Vector3f. -8 0 0)
1040 (Vector3f. 2 0 0)
1041 ;;swivel swivel
1042 ;;Matrix3f/IDENTITY Matrix3f/IDENTITY
1043 x-move Matrix3f/IDENTITY
1045 (.setCollisionBetweenLinkedBodys false)
1046 (.setLimit (* 1 (/ Math/PI 4)) ;; twist
1047 (* 1 (/ Math/PI 4)) ;; swing span in X-Y plane
1048 (* 0 (/ Math/PI 4)))) ;; swing span in Y-Z plane
1049 (world (nodify
1050 [obj-a obj-b])
1051 (merge standard-debug-controls
1052 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
1053 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
1054 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
1055 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
1056 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
1057 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
1059 (fn [world]
1060 (enable-debug world)
1061 (set-gravity world Vector3f/ZERO)
1064 (fn [world _]
1066 (if @move-up?
1067 (.applyForce control-a
1068 (Vector3f. force 0 0)
1069 (Vector3f. 0 0 0)))
1070 (if @move-down?
1071 (.applyForce control-a
1072 (Vector3f. (- force) 0 0)
1073 (Vector3f. 0 0 0)))
1074 (if @move-left?
1075 (.applyForce control-a
1076 (Vector3f. 0 force 0)
1077 (Vector3f. 0 0 0)))
1078 (if @move-right?
1079 (.applyForce control-a
1080 (Vector3f. 0 (- force) 0)
1081 (Vector3f. 0 0 0)))
1083 (if @roll-left?
1084 (.applyForce control-a
1085 (Vector3f. 0 0 force)
1086 (Vector3f. 0 0 0)))
1087 (if @roll-right?
1088 (.applyForce control-a
1089 (Vector3f. 0 0 (- force))
1090 (Vector3f. 0 0 0)))
1092 (if (zero? (rem (swap! timer inc) 100))
1093 (.attachChild
1094 (.getRootNode world)
1095 (sphere 0.05 :color ColorRGBA/Yellow
1096 :physical? false :position
1097 (.getWorldTranslation obj-a)))))
1099 ))
1101 (defn transform-trianglesdsd
1102 "Transform that converts each vertex in the first triangle
1103 into the corresponding vertex in the second triangle."
1104 [#^Triangle tri-1 #^Triangle tri-2]
1105 (let [in [(.get1 tri-1)
1106 (.get2 tri-1)
1107 (.get3 tri-1)]
1108 out [(.get1 tri-2)
1109 (.get2 tri-2)
1110 (.get3 tri-2)]]
1111 (let [translate (doto (Matrix4f.) (.setTranslation (.negate (in 0))))
1112 in* [(.mult translate (in 0))
1113 (.mult translate (in 1))
1114 (.mult translate (in 2))]
1115 final-translation
1116 (doto (Matrix4f.)
1117 (.setTranslation (out 1)))
1119 rotate-1
1120 (doto (Matrix3f.)
1121 (.fromStartEndVectors
1122 (.normalize
1123 (.subtract
1124 (in* 1) (in* 0)))
1125 (.normalize
1126 (.subtract
1127 (out 1) (out 0)))))
1128 in** [(.mult rotate-1 (in* 0))
1129 (.mult rotate-1 (in* 1))
1130 (.mult rotate-1 (in* 2))]
1131 scale-factor-1
1132 (.mult
1133 (.normalize
1134 (.subtract
1135 (out 1)
1136 (out 0)))
1137 (/ (.length
1138 (.subtract (out 1)
1139 (out 0)))
1140 (.length
1141 (.subtract (in** 1)
1142 (in** 0)))))
1143 scale-1 (doto (Matrix4f.) (.setScale scale-factor-1))
1144 in*** [(.mult scale-1 (in** 0))
1145 (.mult scale-1 (in** 1))
1146 (.mult scale-1 (in** 2))]
1154 (dorun (map println in))
1155 (println)
1156 (dorun (map println in*))
1157 (println)
1158 (dorun (map println in**))
1159 (println)
1160 (dorun (map println in***))
1161 (println)
1163 ))))
1168 #+end_src
1171 * COMMENT generate source
1172 #+begin_src clojure :tangle ../src/cortex/silly.clj
1173 <<body-1>>
1174 #+end_src