view org/test-creature.org @ 103:85ee8bb80edf

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