view org/test-creature.org @ 102:7eeb940bcbc8

data format for touch implemented
author Robert McIntyre <rlm@mit.edu>
date Sat, 14 Jan 2012 20:44:13 -0700
parents 65332841b7d9
children 85ee8bb80edf
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."
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))))
751 (defn all-names []
752 (concat
753 (re-split #"\n" (slurp (file-str
754 "/home/r/proj/names/dist.female.first")))
755 (re-split #"\n" (slurp (file-str
756 "/home/r/proj/names/dist.male.first")))
757 (re-split #"\n" (slurp (file-str
758 "/home/r/proj/names/dist.all.last")))))
768 (defrecord LulzLoader [])
769 (defprotocol Lulzable (load-lulz [this]))
770 (extend-type LulzLoader
771 Lulzable
772 (load-lulz [this] (println "the lulz have arrived!")))
775 (defn world-setup [joint]
776 (let [joint-position (Vector3f. 0 0 0)
777 joint-rotation
778 (.toRotationMatrix
779 (.mult
780 (doto (Quaternion.)
781 (.fromAngleAxis
782 (* 1 (/ Math/PI 4))
783 (Vector3f. -1 0 0)))
784 (doto (Quaternion.)
785 (.fromAngleAxis
786 (* 1 (/ Math/PI 2))
787 (Vector3f. 0 0 1)))))
788 top-position (.mult joint-rotation (Vector3f. 8 0 0))
790 origin (doto
791 (sphere 0.1 :physical? false :color ColorRGBA/Cyan
792 :position top-position))
793 top (doto
794 (sphere 0.1 :physical? false :color ColorRGBA/Yellow
795 :position top-position)
797 (.addControl
798 (RigidBodyControl.
799 (CapsuleCollisionShape. 0.5 1.5 1) (float 20))))
800 bottom (doto
801 (sphere 0.1 :physical? false :color ColorRGBA/DarkGray
802 :position (Vector3f. 0 0 0))
803 (.addControl
804 (RigidBodyControl.
805 (CapsuleCollisionShape. 0.5 1.5 1) (float 0))))
806 table (box 10 2 10 :position (Vector3f. 0 -20 0)
807 :color ColorRGBA/Gray :mass 0)
808 a (.getControl top RigidBodyControl)
809 b (.getControl bottom RigidBodyControl)]
811 (cond
812 (= joint :cone)
814 (doto (ConeJoint.
815 a b
816 (world-to-local top joint-position)
817 (world-to-local bottom joint-position)
818 joint-rotation
819 joint-rotation
820 )
823 (.setLimit (* (/ 10) Math/PI)
824 (* (/ 4) Math/PI)
825 0)))
826 [origin top bottom table]))
828 (defn test-joint [joint]
829 (let [[origin top bottom floor] (world-setup joint)
830 control (.getControl top RigidBodyControl)
831 move-up? (atom false)
832 move-down? (atom false)
833 move-left? (atom false)
834 move-right? (atom false)
835 roll-left? (atom false)
836 roll-right? (atom false)
837 timer (atom 0)]
839 (world
840 (nodify [top bottom floor origin])
841 (merge standard-debug-controls
842 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
843 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
844 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
845 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
846 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
847 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
849 (fn [world]
850 (light-up-everything world)
851 (enable-debug world)
852 (set-gravity world (Vector3f. 0 0 0))
853 )
855 (fn [world _]
856 (if (zero? (rem (swap! timer inc) 100))
857 (do
858 ;; (println-repl @timer)
859 (.attachChild (.getRootNode world)
860 (sphere 0.05 :color ColorRGBA/Yellow
861 :position (.getWorldTranslation top)
862 :physical? false))
863 (.attachChild (.getRootNode world)
864 (sphere 0.05 :color ColorRGBA/LightGray
865 :position (.getWorldTranslation bottom)
866 :physical? false))))
868 (if @move-up?
869 (.applyTorque control
870 (.mult (.getPhysicsRotation control)
871 (Vector3f. 0 0 10))))
872 (if @move-down?
873 (.applyTorque control
874 (.mult (.getPhysicsRotation control)
875 (Vector3f. 0 0 -10))))
876 (if @move-left?
877 (.applyTorque control
878 (.mult (.getPhysicsRotation control)
879 (Vector3f. 0 10 0))))
880 (if @move-right?
881 (.applyTorque control
882 (.mult (.getPhysicsRotation control)
883 (Vector3f. 0 -10 0))))
884 (if @roll-left?
885 (.applyTorque control
886 (.mult (.getPhysicsRotation control)
887 (Vector3f. -1 0 0))))
888 (if @roll-right?
889 (.applyTorque control
890 (.mult (.getPhysicsRotation control)
891 (Vector3f. 1 0 0))))))))
894 (defn locate-feelers*
895 "Search the geometry's tactile UV image for touch sensors, returning
896 their positions in geometry-relative coordinates."
897 [#^Geometry geo]
898 (let [uv-image (touch-receptor-image geo)
899 width (.getWidth uv-image)
900 height (.getHeight uv-image)
902 mesh (.getMesh geo)
903 mesh-tris (triangles geo)
905 ;; for each triangle
906 sensor-coords
907 (fn [tri]
908 ;; translate triangle to uv-pixel-space
909 (let [uv-tri
910 (rasterize mesh tri width height)
911 bounds (vec (triangle-bounds uv-tri))]
913 ;; get that part of the picture
915 (apply (partial (memfn setRoi) uv-image) bounds)
916 (let [cutout (.crop (.getProcessor uv-image))
917 ;; extract white pixels inside triangle
918 cutout-tri
919 (map-triangle
920 (fn [_ v]
921 (.subtract
922 v
923 (Vector3f. (bounds 0) (bounds 1) (float 0))))
924 uv-tri)
925 whites (filter (partial inside-triangle? cutout-tri)
926 (map vector2f->vector3f
927 (white-coordinates cutout)))
928 ;; translate pixel coordinates to world-space
929 transform (triangle-transformation cutout-tri tri)]
930 (map #(.mult transform %) whites))))]
932 (for [mesh-tri mesh-tris]
934 (let [uv-tri (rasterize mesh mesh-tri width height)
935 bounding-box (vec (triangle-bounds uv-tri))]
936 (apply (partial (memfn setRoi) uv-image) bounding-box)
937 ))
938 (vec (map sensor-coords mesh-tris))))
941 (defn tactile-coords [#^Geometry obj]
942 (let [mesh (.getMesh obj)
943 num-triangles (.getTriangleCount mesh)
944 num-verticies (.getVertexCount mesh)
945 uv-coord (partial uv-coord mesh)
946 triangle-indices (partial triangle-indices mesh)
947 receptors (touch-receptor-image obj)
948 tris (triangles obj)
949 ]
950 (map
951 (fn [[tri-1 tri-2 tri-3]]
952 (let [width (.getWidth receptors)
953 height (.getHeight receptors)
954 uv-1 (uv-coord tri-1)
955 uv-2 (uv-coord tri-2)
956 uv-3 (uv-coord tri-3)
957 x-coords (map #(.getX %) [uv-1 uv-2 uv-3])
958 y-coords (map #(.getY %) [uv-1 uv-2 uv-3])
959 max-x (Math/ceil (* width (apply max x-coords)))
960 min-x (Math/floor (* width (apply min x-coords)))
961 max-y (Math/ceil (* height (apply max y-coords)))
962 min-y (Math/floor (* height (apply min y-coords)))
964 image-1 (Vector2f. (* width (.getX uv-1))
965 (* height (.getY uv-1)))
966 image-2 (Vector2f. (* width (.getX uv-2))
967 (* height (.getY uv-2)))
968 image-3 (Vector2f. (* width (.getX uv-3))
969 (* height (.getY uv-3)))
970 left-corner
971 (Vector2f. min-x min-y)
972 ]
974 (.setRoi receptors min-x min-y (- max-x min-x) (- max-y min-y))
975 (let [processor (.crop (.getProcessor receptors))]
976 (map
977 #(.add left-corner %)
979 (filter
980 (partial
981 inside-triangle?
982 (.subtract image-1 left-corner)
983 (.subtract image-2 left-corner)
984 (.subtract image-3 left-corner))
985 (white-coordinates processor))))
986 )) (map triangle-indices (range num-triangles)))))
988 #+end_src
990 #+results: body-1
991 : #'cortex.silly/test-joint
994 * COMMENT purgatory
995 #+begin_src clojure
996 (defn bullet-trans []
997 (let [obj-a (sphere 0.5 :color ColorRGBA/Red
998 :position (Vector3f. -10 5 0))
999 obj-b (sphere 0.5 :color ColorRGBA/Blue
1000 :position (Vector3f. -10 -5 0)
1001 :mass 0)
1002 control-a (.getControl obj-a RigidBodyControl)
1003 control-b (.getControl obj-b RigidBodyControl)
1004 swivel
1005 (.toRotationMatrix
1006 (doto (Quaternion.)
1007 (.fromAngleAxis (/ Math/PI 2)
1008 Vector3f/UNIT_X)))]
1009 (doto
1010 (ConeJoint.
1011 control-a control-b
1012 (Vector3f. 0 5 0)
1013 (Vector3f. 0 -5 0)
1014 swivel swivel)
1015 (.setLimit (* 0.6 (/ Math/PI 4))
1016 (/ Math/PI 4)
1017 (* Math/PI 0.8)))
1018 (world (nodify
1019 [obj-a obj-b])
1020 standard-debug-controls
1021 enable-debug
1022 no-op)))
1025 (defn bullet-trans* []
1026 (let [obj-a (box 1.5 0.5 0.5 :color ColorRGBA/Red
1027 :position (Vector3f. 5 0 0)
1028 :mass 90)
1029 obj-b (sphere 0.5 :color ColorRGBA/Blue
1030 :position (Vector3f. -5 0 0)
1031 :mass 0)
1032 control-a (.getControl obj-a RigidBodyControl)
1033 control-b (.getControl obj-b RigidBodyControl)
1034 move-up? (atom nil)
1035 move-down? (atom nil)
1036 move-left? (atom nil)
1037 move-right? (atom nil)
1038 roll-left? (atom nil)
1039 roll-right? (atom nil)
1040 force 100
1041 swivel
1042 (.toRotationMatrix
1043 (doto (Quaternion.)
1044 (.fromAngleAxis (/ Math/PI 2)
1045 Vector3f/UNIT_X)))
1046 x-move
1047 (doto (Matrix3f.)
1048 (.fromStartEndVectors Vector3f/UNIT_X
1049 (.normalize (Vector3f. 1 1 0))))
1051 timer (atom 0)]
1052 (doto
1053 (ConeJoint.
1054 control-a control-b
1055 (Vector3f. -8 0 0)
1056 (Vector3f. 2 0 0)
1057 ;;swivel swivel
1058 ;;Matrix3f/IDENTITY Matrix3f/IDENTITY
1059 x-move Matrix3f/IDENTITY
1061 (.setCollisionBetweenLinkedBodys false)
1062 (.setLimit (* 1 (/ Math/PI 4)) ;; twist
1063 (* 1 (/ Math/PI 4)) ;; swing span in X-Y plane
1064 (* 0 (/ Math/PI 4)))) ;; swing span in Y-Z plane
1065 (world (nodify
1066 [obj-a obj-b])
1067 (merge standard-debug-controls
1068 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
1069 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
1070 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
1071 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
1072 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
1073 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
1075 (fn [world]
1076 (enable-debug world)
1077 (set-gravity world Vector3f/ZERO)
1080 (fn [world _]
1082 (if @move-up?
1083 (.applyForce control-a
1084 (Vector3f. force 0 0)
1085 (Vector3f. 0 0 0)))
1086 (if @move-down?
1087 (.applyForce control-a
1088 (Vector3f. (- force) 0 0)
1089 (Vector3f. 0 0 0)))
1090 (if @move-left?
1091 (.applyForce control-a
1092 (Vector3f. 0 force 0)
1093 (Vector3f. 0 0 0)))
1094 (if @move-right?
1095 (.applyForce control-a
1096 (Vector3f. 0 (- force) 0)
1097 (Vector3f. 0 0 0)))
1099 (if @roll-left?
1100 (.applyForce control-a
1101 (Vector3f. 0 0 force)
1102 (Vector3f. 0 0 0)))
1103 (if @roll-right?
1104 (.applyForce control-a
1105 (Vector3f. 0 0 (- force))
1106 (Vector3f. 0 0 0)))
1108 (if (zero? (rem (swap! timer inc) 100))
1109 (.attachChild
1110 (.getRootNode world)
1111 (sphere 0.05 :color ColorRGBA/Yellow
1112 :physical? false :position
1113 (.getWorldTranslation obj-a)))))
1115 ))
1117 (defn transform-trianglesdsd
1118 "Transform that converts each vertex in the first triangle
1119 into the corresponding vertex in the second triangle."
1120 [#^Triangle tri-1 #^Triangle tri-2]
1121 (let [in [(.get1 tri-1)
1122 (.get2 tri-1)
1123 (.get3 tri-1)]
1124 out [(.get1 tri-2)
1125 (.get2 tri-2)
1126 (.get3 tri-2)]]
1127 (let [translate (doto (Matrix4f.) (.setTranslation (.negate (in 0))))
1128 in* [(.mult translate (in 0))
1129 (.mult translate (in 1))
1130 (.mult translate (in 2))]
1131 final-translation
1132 (doto (Matrix4f.)
1133 (.setTranslation (out 1)))
1135 rotate-1
1136 (doto (Matrix3f.)
1137 (.fromStartEndVectors
1138 (.normalize
1139 (.subtract
1140 (in* 1) (in* 0)))
1141 (.normalize
1142 (.subtract
1143 (out 1) (out 0)))))
1144 in** [(.mult rotate-1 (in* 0))
1145 (.mult rotate-1 (in* 1))
1146 (.mult rotate-1 (in* 2))]
1147 scale-factor-1
1148 (.mult
1149 (.normalize
1150 (.subtract
1151 (out 1)
1152 (out 0)))
1153 (/ (.length
1154 (.subtract (out 1)
1155 (out 0)))
1156 (.length
1157 (.subtract (in** 1)
1158 (in** 0)))))
1159 scale-1 (doto (Matrix4f.) (.setScale scale-factor-1))
1160 in*** [(.mult scale-1 (in** 0))
1161 (.mult scale-1 (in** 1))
1162 (.mult scale-1 (in** 2))]
1170 (dorun (map println in))
1171 (println)
1172 (dorun (map println in*))
1173 (println)
1174 (dorun (map println in**))
1175 (println)
1176 (dorun (map println in***))
1177 (println)
1179 ))))
1184 #+end_src
1187 * COMMENT generate source
1188 #+begin_src clojure :tangle ../src/cortex/silly.clj
1189 <<body-1>>
1190 #+end_src