view org/body.org @ 61:7b44348af538

cleaning up body code
author Robert McIntyre <rlm@mit.edu>
date Mon, 28 Nov 2011 21:22:35 -0700
parents e5e627f50a3a
children 2b9d81017cb7
line wrap: on
line source
1 #+title: The BODY!!!
2 #+author: Robert McIntyre
3 #+email: rlm@mit.edu
4 #+description: Simulating a body (movement, touch, propioception) in jMonkeyEngine3.
5 #+SETUPFILE: ../../aurellem/org/setup.org
6 #+INCLUDE: ../../aurellem/org/level-0.org
8 * Body
10 #+srcname: body-main
11 #+begin_src clojure
12 (ns cortex.body
13 (use (cortex world util import)))
15 (use 'clojure.contrib.def)
16 (cortex.import/mega-import-jme3)
17 (rlm.rlm-commands/help)
19 (defn load-blender-model
20 [^String model]
21 (.loadModel
22 (doto (asset-manager)
23 (.registerLoader BlenderModelLoader (into-array String ["blend"])))
24 model))
26 (defn skel [node]
27 (doto
28 (.getSkeleton
29 (.getControl node SkeletonControl))
30 ;; this is necessary to force the skeleton to have accurate world
31 ;; transforms before it is rendered to the screen.
32 (.resetAndUpdate)))
34 (defprotocol Textual
35 (text [something]
36 "Display a detailed textual analysis of the given object."))
38 (extend-type com.jme3.scene.Node
39 Textual
40 (text [node]
41 (println "Total Vertexes: " (.getVertexCount node))
42 (println "Total Triangles: " (.getTriangleCount node))
43 (println "Controls :")
44 (dorun (map #(text (.getControl node %)) (range (.getNumControls node))))
45 (println "Has " (.getQuantity node) " Children:")
46 (doall (map text (.getChildren node)))))
48 (extend-type com.jme3.animation.AnimControl
49 Textual
50 (text [control]
51 (let [animations (.getAnimationNames control)]
52 (println "Animation Control with " (count animations) " animation(s):")
53 (dorun (map println animations)))))
55 (extend-type com.jme3.animation.SkeletonControl
56 Textual
57 (text [control]
58 (println "Skeleton Control with the following skeleton:")
59 (println (.getSkeleton control))))
61 (extend-type com.jme3.bullet.control.KinematicRagdollControl
62 Textual
63 (text [control]
64 (println "Ragdoll Control")))
67 (extend-type com.jme3.scene.Geometry
68 Textual
69 (text [control]
70 (println "...geo...")))
73 (defn green-x-ray []
74 (doto (Material. (asset-manager)
75 "Common/MatDefs/Misc/Unshaded.j3md")
76 (.setColor "Color" ColorRGBA/Green)
77 (-> (.getAdditionalRenderState)
78 (.setDepthTest false))))
81 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
83 ;;;;;;;;;;;; eve-style bodies ;;;;;;;;
85 (defn worm [segment-length num-segments interstitial-space radius]
86 (letfn [(nth-segment
87 [n]
88 (box segment-length radius radius :mass 0.1
89 :position
90 (Vector3f.
91 (* 2 n (+ interstitial-space segment-length)) 0 0)
92 :name (str "worm-segment" n)
93 :color (ColorRGBA/randomColor)))]
94 (map nth-segment (range num-segments))))
96 (defn nodify
97 "take a sequence of things that can be attached to a node and return
98 a node with all of them attached"
99 ([name children]
100 (let [node (Node. name)]
101 (dorun (map #(.attachChild node %) children))
102 node))
103 ([children] (nodify "" children)))
105 (defn connect-at-midpoint
106 [segmentA segmentB]
107 (let [centerA (.getWorldTranslation segmentA)
108 centerB (.getWorldTranslation segmentB)
109 midpoint (.mult (.add centerA centerB) (float 0.5))
110 pivotA (.subtract midpoint centerA)
111 pivotB (.subtract midpoint centerB)
112 joint (Point2PointJoint.
113 (.getControl segmentA RigidBodyControl)
114 (.getControl segmentB RigidBodyControl)
115 pivotA
116 pivotB)]
117 segmentB))
119 (defn point-worm []
120 (let [segments (worm 0.2 5 0.1 0.1)]
121 (dorun (map (partial apply connect-at-midpoint)
122 (partition 2 1 segments)))
123 (nodify "worm" segments)))
125 (defn test-worm []
126 (.start
127 (world
128 (doto (Node.)
129 ;;(.attachChild (point-worm))
130 (.attachChild (load-blender-model
131 "Models/anim2/joint-worm.blend"))
133 (.attachChild (box 10 1 10
134 :position (Vector3f. 0 -2 0) :mass 0
135 :color (ColorRGBA/Gray))))
136 {
137 "key-space" (fire-cannon-ball)
138 }
139 (fn [world]
140 (enable-debug world)
141 (light-up-everything world)
142 ;;(.setTimer world (NanoTimer.))
143 )
144 no-op)))
146 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
149 ;;;;;;;;; Mortor Control ;;;;;;;;;;;;;
152 ;; surprisingly ehough, terristerial creatures only move by using
153 ;; torque applied to their joints. There's not a single straight line
154 ;; of force in the human body at all! (a straight line of force would
155 ;; correspond to some sort of jet or rocket propulseion)
157 (defn node-seq
158 "Take a node and return a seq of all its children
159 recursively. There will be no nodes left in the resulting
160 structure"
161 [#^Node node]
162 (tree-seq #(isa? (class %) Node) #(.getChildren %) node))
165 (defn torque-controls [control]
166 (let [torques
167 (concat
168 (map #(Vector3f. 0 (Math/sin %) (Math/cos %))
169 (range 0 (* Math/PI 2) (/ (* Math/PI 2) 20)))
170 [Vector3f/UNIT_X])]
171 (map (fn [torque-axis]
172 (fn [torque]
173 (.applyTorque
174 control
175 (.mult (.mult (.getPhysicsRotation control)
176 torque-axis)
177 (float
178 (* (.getMass control) torque))))))
179 torques)))
181 (defn motor-map
182 "Take a creature and generate a function that will enable fine
183 grained control over all the creature's limbs."
184 [#^Node creature]
185 (let [controls (keep #(.getControl % RigidBodyControl)
186 (node-seq creature))
187 limb-controls (reduce concat (map torque-controls controls))
188 body-control (partial map #(%1 %2) limb-controls)]
189 body-control))
191 (defn test-motor-map
192 "see how torque works."
193 []
194 (let [finger (box 3 0.5 0.5 :position (Vector3f. 0 2 0)
195 :mass 1 :color ColorRGBA/Green)
196 motor-map (motor-map finger)]
197 (world
198 (nodify [finger
199 (box 10 0.5 10 :position (Vector3f. 0 -5 0) :mass 0
200 :color ColorRGBA/Gray)])
201 standard-debug-controls
202 (fn [world]
203 (set-gravity world Vector3f/ZERO)
204 (light-up-everything world)
205 (.setTimer world (NanoTimer.)))
206 (fn [_ _]
207 (dorun (motor-map [0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0]))))))
209 (defn test-torque
210 "see how torque works."
211 []
212 (let [finger (box 3 0.5 0.5 :position (Vector3f. 0 2 0)
213 :mass 1 :color ColorRGBA/Green)
214 move-left? (atom false)
215 move-right? (atom false)
216 control (.getControl finger RigidBodyControl)]
217 (world
218 (nodify [finger
219 (box 10 0.5 10 :position (Vector3f. 0 -5 0) :mass 0
220 :color ColorRGBA/Gray)])
221 (merge standard-debug-controls
222 {"key-k" (fn [_ pressed?] (reset! move-left? pressed?))
223 "key-l" (fn [_ pressed?] (reset! move-right? pressed?))})
224 (fn [world]
225 (set-gravity world Vector3f/ZERO)
226 (light-up-everything world)
227 (.setTimer world (NanoTimer.)))
228 (fn [_ _]
229 (if @move-left?
230 (.applyTorque control
231 (.mult (.getPhysicsRotation control)
232 (Vector3f. -3 20 0))))
233 (if @move-right?
234 (.applyTorque control (Vector3f. 0 0 1)))))))
236 (defn worm-pattern [time]
237 [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
239 0 0 0 0 0 0 0 0 0 0 0
241 (* 20 (Math/sin (* Math/PI 2 (/ (rem time 300 ) 300))))
243 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
244 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
245 0 0 0 0 0 0 0 0 0 0 0 0 0 0
247 ])
249 ;;;;;;;;;;;;;;;;;; Proprioception ;;;;;;;;;;;;;;;;;;;;;;;;
251 ;; this is not used as just getting the rotation would be simpler.
252 (defn proprioception-senses
253 "given a control , create a sequence of thunks that will report the
254 rotation of the control's object along the same axes as the motor-control map."
255 [control]
256 (let [torques
257 (concat
258 (map #(Vector3f. 0 (Math/sin %) (Math/cos %))
259 (range 0 (* Math/PI 2) (/ (* Math/PI 2) 20)))
260 [Vector3f/UNIT_X])]
261 (map (fn [torque-axis]
262 (fn []
263 (.getPhysicsRotation control)))
264 torques)))
266 (defn orthogonal-vect
267 "Return a vector orthogonal to the current one"
268 [vector]
269 (let [x (.getX vector)
270 y (.getY vector)
271 z (.getZ vector)]
272 (cond
273 (not= x (float 0)) (Vector3f. (- z) 0 x)
274 (not= y (float 0)) (Vector3f. 0 (- z) y)
275 (not= z (float 0)) (Vector3f. 0 (- z) y)
276 true Vector3f/ZERO)))
278 ;; from
279 ;; http://stackoverflow.com/questions/3684269/ \\
280 ;; component-of-a-quaternion-rotation-around-an-axis
281 (defn rot-about-axis [#^Quaternion q #^Vector3f axis]
282 (let [basis-1 (orthogonal-vect axis)
283 basis-2 (.cross axis basis-1)
284 rotated (.mult q basis-1)
285 alpha (.dot basis-1 (.project rotated basis-1))
286 beta (.dot basis-2 (.project rotated basis-2))]
287 (Math/atan2 beta alpha)))
290 (defn check-rot [a]
291 (rot-about-axis
292 (doto (Quaternion.)
293 (.fromAngleAxis
294 (float a)
295 (Vector3f. 1 0 0))) (Vector3f. 1 0 0)))
297 (defn relative-positions [joint]
298 (let [object-a (.getUserObject (.getBodyA joint))
299 object-b (.getUserObject (.getBodyB joint))
300 arm-a
301 (.normalize
302 (.subtract
303 (.localToWorld object-a (.getPivotA joint) nil)
304 (.getWorldTranslation object-a)))
305 rotate-a
306 (doto (Matrix3f.)
307 (.fromStartEndVectors arm-a Vector3f/UNIT_X))
308 arm-b
309 (.mult
310 rotate-a
311 (.normalize
312 (.subtract
313 (.localToWorld object-b (.getPivotB joint) nil)
314 (.getWorldTranslation object-b))))
315 pitch
316 (.angleBetween
317 (.normalize (Vector2f. (.getX arm-b) (.getY arm-b)))
318 (Vector2f. 1 0))
319 yaw
320 (.angleBetween
321 (.normalize (Vector2f. (.getX arm-b) (.getZ arm-b)))
322 (Vector2f. 1 0))
324 roll
325 (rot-about-axis
326 (.mult
327 (.getLocalRotation object-b)
328 (doto (Quaternion.)
329 (.fromRotationMatrix rotate-a)))
330 arm-b)
331 ]
335 ;;(println-repl
336 ;; "arm-b is " arm-b)
337 ;;(println-repl
338 ;; "pivot-b is " (.getPivotB joint))
339 ;;(println-repl
340 ;; (format "pitch: %1.2f\nyaw: %1.2f\nroll: %1.2f\n"
341 ;; pitch yaw roll))
342 [pitch yaw roll]))
350 (defn test-worm-control
351 []
352 (let [worm (point-worm)
353 time (atom 0)
354 worm-motor-map (motor-map worm)
355 ;;body-map (proprioception worm)
356 debug-segments
357 (map
358 #(doto
359 (make-shape
360 (assoc base-shape
361 :name "debug-line"
362 :physical? false
363 :shape
364 (com.jme3.scene.shape.Line.
365 (.add (.getWorldTranslation %)
366 (Vector3f. -0.2 0 0 ))
367 (.add (.getWorldTranslation %)
368 (Vector3f. 0.2 0 0)))))
369 (.setMaterial (green-x-ray)))
370 (drop 1 (node-seq worm)))]
371 (world
372 (nodify [worm
373 (box 10 0.5 10 :position (Vector3f. 0 -5 0) :mass 0
374 :color ColorRGBA/Gray)])
375 standard-debug-controls
376 (fn [world]
377 (.attachChild (.getRootNode world) (nodify debug-segments))
378 (enable-debug world)
379 (light-up-everything world)
380 (com.aurellem.capture.Capture/captureVideo
381 world
382 (file-str "/home/r/proj/cortex/tmp/moving-worm")))
384 (fn [_ _]
385 (dorun
386 (map
387 (fn [worm-segment
388 debug-segment]
389 (.rotate
390 debug-segment
391 (Quaternion. (float 0) (float 0.05) (float 0) (float 1))))
392 (drop 1 (node-seq worm))
393 debug-segments))
394 (swap! time inc)
395 ;;(println-repl (with-out-str (clojure.pprint/pprint (doall (body-map)))))
396 (Thread/sleep 200)
397 (dorun (worm-motor-map
398 (worm-pattern @time)))))))
404 (defn test-prop
405 "see how torque works."
406 []
407 (let [hand (box 1 0.2 0.2 :position (Vector3f. 0 2 0)
408 :mass 0 :color ColorRGBA/Green)
409 finger (box 1 0.2 0.2 :position (Vector3f. 2.4 2 0)
410 :mass 1 :color (ColorRGBA. 0.20 0.40 0.99 1.0))
411 floor (box 10 0.5 10 :position (Vector3f. 0 -5 0)
412 :mass 0 :color ColorRGBA/Gray)
414 move-up? (atom false)
415 move-down? (atom false)
416 move-left? (atom false)
417 move-right? (atom false)
418 roll-left? (atom false)
419 roll-right? (atom false)
420 control (.getControl finger RigidBodyControl)
421 joint
422 (doto
423 (Point2PointJoint.
424 (.getControl hand RigidBodyControl)
425 control
426 (Vector3f. 1.2 0 0)
427 (Vector3f. -1.2 0 0 ))
428 (.setCollisionBetweenLinkedBodys false))
429 time (atom 0)
430 ]
431 (world
432 (nodify [hand finger floor])
433 (merge standard-debug-controls
434 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
435 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
436 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
437 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
438 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
439 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
440 (fn [world]
441 (set-gravity world (Vector3f. 0 0 0))
442 (.setMoveSpeed (.getFlyByCamera world) 50)
443 (.setRotationSpeed (.getFlyByCamera world) 50)
444 (light-up-everything world)
445 (.setTimer world (NanoTimer.))
446 )
447 (fn [_ _]
448 (if @move-up?
449 (.applyTorque control
450 (.mult (.getPhysicsRotation control)
451 (Vector3f. 0 0 10))))
452 (if @move-down?
453 (.applyTorque control
454 (.mult (.getPhysicsRotation control)
455 (Vector3f. 0 0 -10))))
456 (if @move-left?
457 (.applyTorque control
458 (.mult (.getPhysicsRotation control)
459 (Vector3f. 0 10 0))))
460 (if @move-right?
461 (.applyTorque control
462 (.mult (.getPhysicsRotation control)
463 (Vector3f. 0 -10 0))))
464 (if @roll-left?
465 (.applyTorque control
466 (.mult (.getPhysicsRotation control)
467 (Vector3f. -1 0 0))))
468 (if @roll-right?
469 (.applyTorque control
470 (.mult (.getPhysicsRotation control)
471 (Vector3f. 1 0 0))))
473 (if (= 0 (rem (swap! time inc) 2000))
474 (do
476 (apply
477 (comp
478 println-repl
479 #(format "pitch: %1.2f\nyaw: %1.2f\nroll: %1.2f\n" %1 %2 %3))
480 (relative-positions joint))))))))
482 #+end_src
485 * COMMENT failed-clojure-code
486 #+begin_src clojure
487 ;;(.loadModel
488 ;; (doto (asset-manager)
489 ;; (.registerLoader BlenderModelLoader (into-array String ["blend"])))
490 ;; "Models/person/person.blend")
492 (defn view-model [^String model]
493 (view
494 (.loadModel
495 (doto (asset-manager)
496 (.registerLoader BlenderModelLoader (into-array String ["blend"])))
497 model)))
499 (defn load-blender-scene [^String model]
500 (.loadModel
501 (doto (asset-manager)
502 (.registerLoader BlenderLoader (into-array String ["blend"])))
503 model))
505 (defn worm
506 []
507 (.loadModel (asset-manager) "Models/anim2/Cube.mesh.xml"))
509 (defn oto
510 []
511 (.loadModel (asset-manager) "Models/Oto/Oto.mesh.xml"))
513 (defn sinbad
514 []
515 (.loadModel (asset-manager) "Models/Sinbad/Sinbad.mesh.xml"))
517 (defn worm-blender
518 []
519 (first (seq (.getChildren (load-blender-model
520 "Models/anim2/simple-worm.blend")))))
522 (defn body
523 "given a node with a SkeletonControl, will produce a body sutiable
524 for AI control with movement and proprioception."
525 [node]
526 (let [skeleton-control (.getControl node SkeletonControl)
527 krc (KinematicRagdollControl.)]
528 (comment
529 (dorun
530 (map #(.addBoneName krc %)
531 ["mid2" "tail" "head" "mid1" "mid3" "mid4" "Dummy-Root" ""]
532 ;;"mid2" "mid3" "tail" "head"]
533 )))
534 (.addControl node krc)
535 (.setRagdollMode krc)
536 )
537 node
538 )
539 (defn show-skeleton [node]
540 (let [sd
542 (doto
543 (SkeletonDebugger. "aurellem-skel-debug"
544 (skel node))
545 (.setMaterial (green-x-ray)))]
546 (.attachChild node sd)
547 node))
551 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
553 ;; this could be a good way to give objects special properties like
554 ;; being eyes and the like
556 (.getUserData
557 (.getChild
558 (load-blender-model "Models/property/test.blend") 0)
559 "properties")
561 ;; the properties are saved along with the blender file.
562 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
567 (defn init-debug-skel-node
568 [f debug-node skeleton]
569 (let [bones
570 (map #(.getBone skeleton %)
571 (range (.getBoneCount skeleton)))]
572 (dorun (map #(.setUserControl % true) bones))
573 (dorun (map (fn [b]
574 (println (.getName b)
575 " -- " (f b)))
576 bones))
577 (dorun
578 (map #(.attachChild
579 debug-node
580 (doto
581 (sphere 0.1
582 :position (f %)
583 :physical? false)
584 (.setMaterial (green-x-ray))))
585 bones)))
586 debug-node)
588 (import jme3test.bullet.PhysicsTestHelper)
591 (defn test-zzz [the-worm world value]
592 (if (not value)
593 (let [skeleton (skel the-worm)]
594 (println-repl "enabling bones")
595 (dorun
596 (map
597 #(.setUserControl (.getBone skeleton %) true)
598 (range (.getBoneCount skeleton))))
601 (let [b (.getBone skeleton 2)]
602 (println-repl "moving " (.getName b))
603 (println-repl (.getLocalPosition b))
604 (.setUserTransforms b
605 Vector3f/UNIT_X
606 Quaternion/IDENTITY
607 ;;(doto (Quaternion.)
608 ;; (.fromAngles (/ Math/PI 2)
609 ;; 0
610 ;; 0
612 (Vector3f. 1 1 1))
613 )
615 (println-repl "hi! <3"))))
618 (defn test-ragdoll []
620 (let [the-worm
622 ;;(.loadModel (asset-manager) "Models/anim2/Cube.mesh.xml")
623 (doto (show-skeleton (worm-blender))
624 (.setLocalTranslation (Vector3f. 0 10 0))
625 ;;(worm)
626 ;;(oto)
627 ;;(sinbad)
628 )
629 ]
632 (.start
633 (world
634 (doto (Node.)
635 (.attachChild the-worm))
636 {"key-return" (fire-cannon-ball)
637 "key-space" (partial test-zzz the-worm)
638 }
639 (fn [world]
640 (light-up-everything world)
641 (PhysicsTestHelper/createPhysicsTestWorld
642 (.getRootNode world)
643 (asset-manager)
644 (.getPhysicsSpace
645 (.getState (.getStateManager world) BulletAppState)))
646 (set-gravity world Vector3f/ZERO)
647 ;;(.setTimer world (NanoTimer.))
648 ;;(org.lwjgl.input.Mouse/setGrabbed false)
649 )
650 no-op
651 )
654 )))
657 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
658 ;;; here is the ragdoll stuff
660 (def worm-mesh (.getMesh (.getChild (worm-blender) 0)))
661 (def mesh worm-mesh)
663 (.getFloatBuffer mesh VertexBuffer$Type/Position)
664 (.getFloatBuffer mesh VertexBuffer$Type/BoneWeight)
665 (.getData (.getBuffer mesh VertexBuffer$Type/BoneIndex))
668 (defn position [index]
669 (.get
670 (.getFloatBuffer worm-mesh VertexBuffer$Type/Position)
671 index))
673 (defn bones [index]
674 (.get
675 (.getData (.getBuffer mesh VertexBuffer$Type/BoneIndex))
676 index))
678 (defn bone-weights [index]
679 (.get
680 (.getFloatBuffer mesh VertexBuffer$Type/BoneWeight)
681 index))
685 (defn vertex-bones [vertex]
686 (vec (map (comp int bones) (range (* vertex 4) (+ (* vertex 4) 4)))))
688 (defn vertex-weights [vertex]
689 (vec (map (comp float bone-weights) (range (* vertex 4) (+ (* vertex 4) 4)))))
691 (defn vertex-position [index]
692 (let [offset (* index 3)]
693 (Vector3f. (position offset)
694 (position (inc offset))
695 (position (inc(inc offset))))))
697 (def vertex-info (juxt vertex-position vertex-bones vertex-weights))
699 (defn bone-control-color [index]
700 (get {[1 0 0 0] ColorRGBA/Red
701 [1 2 0 0] ColorRGBA/Magenta
702 [2 0 0 0] ColorRGBA/Blue}
703 (vertex-bones index)
704 ColorRGBA/White))
706 (defn influence-color [index bone-num]
707 (get
708 {(float 0) ColorRGBA/Blue
709 (float 0.5) ColorRGBA/Green
710 (float 1) ColorRGBA/Red}
711 ;; find the weight of the desired bone
712 ((zipmap (vertex-bones index)(vertex-weights index))
713 bone-num)
714 ColorRGBA/Blue))
716 (def worm-vertices (set (map vertex-info (range 60))))
719 (defn test-info []
720 (let [points (Node.)]
721 (dorun
722 (map #(.attachChild points %)
723 (map #(sphere 0.01
724 :position (vertex-position %)
725 :color (influence-color % 1)
726 :physical? false)
727 (range 60))))
728 (view points)))
731 (defrecord JointControl [joint physics-space]
732 PhysicsControl
733 (setPhysicsSpace [this space]
734 (dosync
735 (ref-set (:physics-space this) space))
736 (.addJoint space (:joint this)))
737 (update [this tpf])
738 (setSpatial [this spatial])
739 (render [this rm vp])
740 (getPhysicsSpace [this] (deref (:physics-space this)))
741 (isEnabled [this] true)
742 (setEnabled [this state]))
744 (defn add-joint
745 "Add a joint to a particular object. When the object is added to the
746 PhysicsSpace of a simulation, the joint will also be added"
747 [object joint]
748 (let [control (JointControl. joint (ref nil))]
749 (.addControl object control))
750 object)
753 (defn hinge-world
754 []
755 (let [sphere1 (sphere)
756 sphere2 (sphere 1 :position (Vector3f. 3 3 3))
757 joint (Point2PointJoint.
758 (.getControl sphere1 RigidBodyControl)
759 (.getControl sphere2 RigidBodyControl)
760 Vector3f/ZERO (Vector3f. 3 3 3))]
761 (add-joint sphere1 joint)
762 (doto (Node. "hinge-world")
763 (.attachChild sphere1)
764 (.attachChild sphere2))))
767 (defn test-joint []
768 (view (hinge-world)))
770 ;; (defn copier-gen []
771 ;; (let [count (atom 0)]
772 ;; (fn [in]
773 ;; (swap! count inc)
774 ;; (clojure.contrib.duck-streams/copy
775 ;; in (File. (str "/home/r/tmp/mao-test/clojure-images/"
776 ;; ;;/home/r/tmp/mao-test/clojure-images
777 ;; (format "%08d.png" @count)))))))
778 ;; (defn decrease-framerate []
779 ;; (map
780 ;; (copier-gen)
781 ;; (sort
782 ;; (map first
783 ;; (partition
784 ;; 4
785 ;; (filter #(re-matches #".*.png$" (.getCanonicalPath %))
786 ;; (file-seq
787 ;; (file-str
788 ;; "/home/r/media/anime/mao-temp/images"))))))))
792 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
794 (defn proprioception
795 "Create a proprioception map that reports the rotations of the
796 various limbs of the creature's body"
797 [creature]
798 [#^Node creature]
799 (let [
800 nodes (node-seq creature)
801 joints
802 (map
803 :joint
804 (filter
805 #(isa? (class %) JointControl)
806 (reduce
807 concat
808 (map (fn [node]
809 (map (fn [num] (.getControl node num))
810 (range (.getNumControls node))))
811 nodes))))]
812 (fn []
813 (reduce concat (map relative-positions (list (first joints)))))))
816 #+end_src
824 * COMMENT generate Source.
825 #+begin_src clojure :tangle ../src/cortex/body.clj
826 <<body-main>>
827 #+end_src