view org/body.org @ 135:421cc43441ae

cleaned up test, moved some functions
author Robert McIntyre <rlm@mit.edu>
date Wed, 01 Feb 2012 05:43:51 -0700
parents ac350a0ac6b0
children 47a4d74761f0
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 * Proprioception
9 #+name: proprioception
10 #+begin_src clojure
11 (ns cortex.body
12 (:use (cortex world util))
13 (:import
14 com.jme3.math.Vector3f
15 com.jme3.math.Quaternion
16 com.jme3.math.Vector2f
17 com.jme3.math.Matrix3f
18 com.jme3.bullet.control.RigidBodyControl
19 com.jme3.collision.CollisionResults
20 com.jme3.bounding.BoundingBox))
22 (import com.jme3.scene.Node)
24 (defn jme-to-blender
25 "Convert from JME coordinates to Blender coordinates"
26 [#^Vector3f in]
27 (Vector3f. (.getX in)
28 (- (.getZ in))
29 (.getY in)))
31 (defn joint-targets
32 "Return the two closest two objects to the joint object, ordered
33 from bottom to top according to the joint's rotation."
34 [#^Node parts #^Node joint]
35 (loop [radius (float 0.01)]
36 (let [results (CollisionResults.)]
37 (.collideWith
38 parts
39 (BoundingBox. (.getWorldTranslation joint)
40 radius radius radius)
41 results)
42 (let [targets
43 (distinct
44 (map #(.getGeometry %) results))]
45 (if (>= (count targets) 2)
46 (sort-by
47 #(let [v
48 (jme-to-blender
49 (.mult
50 (.inverse (.getWorldRotation joint))
51 (.subtract (.getWorldTranslation %)
52 (.getWorldTranslation joint))))]
53 (println-repl (.getName %) ":" v)
54 (.dot (Vector3f. 1 1 1)
55 v))
56 (take 2 targets))
57 (recur (float (* radius 2))))))))
59 (defn creature-joints
60 "Return the children of the creature's \"joints\" node."
61 [#^Node creature]
62 (if-let [joint-node (.getChild creature "joints")]
63 (seq (.getChildren joint-node))
64 (do (println-repl "could not find JOINTS node") [])))
66 (defn joint-proprioception [#^Node parts #^Node joint]
67 (let [[obj-a obj-b] (joint-targets parts joint)
68 joint-rot (.getWorldRotation joint)
69 x (.mult joint-rot Vector3f/UNIT_X)
70 y (.mult joint-rot Vector3f/UNIT_Y)
71 z (.mult joint-rot Vector3f/UNIT_Z)]
72 ;; this function will report proprioceptive information for the
73 ;; joint.
74 (fn []
75 ;; x is the "twist" axis, y and z are the "bend" axes
76 (let [rot-a (.getWorldRotation obj-a)
77 rot-b (.getWorldRotation obj-b)
78 relative (.mult rot-b (.inverse rot-a))
79 basis (doto (Matrix3f.)
80 (.setColumn 0 x)
81 (.setColumn 1 y)
82 (.setColumn 2 z))
83 rotation-about-joint
84 (doto (Quaternion.)
85 (.fromRotationMatrix
86 (.mult (.invert basis)
87 (.toRotationMatrix relative))))
88 [yaw roll pitch]
89 (seq (.toAngles rotation-about-joint nil))]
90 ;;return euler angles of the quaternion around the new basis
91 [yaw roll pitch]
92 ))))
95 (defn proprioception
96 "Create a function that provides proprioceptive information about an
97 entire body."
98 [#^Node creature]
99 ;; extract the body's joints
100 (let [joints (creature-joints creature)
101 senses (map (partial joint-proprioception creature) joints)]
102 (fn []
103 (map #(%) senses))))
105 #+end_src
107 #+results: proprioception
108 : #'cortex.body/proprioception
110 * Motor Control
111 #+name: motor-control
112 #+begin_src clojure
113 (in-ns 'cortex.body)
115 ;; surprisingly enough, terristerial creatures only move by using
116 ;; torque applied about their joints. There's not a single straight
117 ;; line of force in the human body at all! (A straight line of force
118 ;; would correspond to some sort of jet or rocket propulseion.)
120 (defn vector-motor-control
121 "Create a function that accepts a sequence of Vector3f objects that
122 describe the torque to be applied to each part of the body."
123 [body]
124 (let [nodes (node-seq body)
125 controls (keep #(.getControl % RigidBodyControl) nodes)]
126 (fn [torques]
127 (map #(.applyTorque %1 %2)
128 controls torques))))
129 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
130 #+end_src
132 ## note -- might want to add a lower dimensional, discrete version of
133 ## this if it proves useful from a x-modal clustering perspective.
135 * Examples
137 #+name: test-body
138 #+begin_src clojure
139 (ns cortex.test.body
140 (:use (cortex world util body))
141 (:require cortex.silly)
142 (:import
143 com.jme3.math.Vector3f
144 com.jme3.math.ColorRGBA
145 com.jme3.bullet.joints.Point2PointJoint
146 com.jme3.bullet.control.RigidBodyControl
147 com.jme3.system.NanoTimer))
149 (defn worm-segments
150 "Create multiple evenly spaced box segments. They're fabulous!"
151 [segment-length num-segments interstitial-space radius]
152 (letfn [(nth-segment
153 [n]
154 (box segment-length radius radius :mass 0.1
155 :position
156 (Vector3f.
157 (* 2 n (+ interstitial-space segment-length)) 0 0)
158 :name (str "worm-segment" n)
159 :color (ColorRGBA/randomColor)))]
160 (map nth-segment (range num-segments))))
162 (defn connect-at-midpoint
163 "Connect two physics objects with a Point2Point joint constraint at
164 the point equidistant from both objects' centers."
165 [segmentA segmentB]
166 (let [centerA (.getWorldTranslation segmentA)
167 centerB (.getWorldTranslation segmentB)
168 midpoint (.mult (.add centerA centerB) (float 0.5))
169 pivotA (.subtract midpoint centerA)
170 pivotB (.subtract midpoint centerB)
172 ;; A side-effect of creating a joint registers
173 ;; it with both physics objects which in turn
174 ;; will register the joint with the physics system
175 ;; when the simulation is started.
176 joint (Point2PointJoint.
177 (.getControl segmentA RigidBodyControl)
178 (.getControl segmentB RigidBodyControl)
179 pivotA
180 pivotB)]
181 segmentB))
183 (defn eve-worm
184 "Create a worm-like body bound by invisible joint constraints."
185 []
186 (let [segments (worm-segments 0.2 5 0.1 0.1)]
187 (dorun (map (partial apply connect-at-midpoint)
188 (partition 2 1 segments)))
189 (nodify "worm" segments)))
191 (defn worm-pattern
192 "This is a simple, mindless motor control pattern that drives the
193 second segment of the worm's body at an offset angle with
194 sinusoidally varying strength."
195 [time]
196 (let [angle (* Math/PI (/ 9 20))
197 direction (Vector3f. 0 (Math/sin angle) (Math/cos angle))]
198 [Vector3f/ZERO
199 (.mult
200 direction
201 (float (* 2 (Math/sin (* Math/PI 2 (/ (rem time 300 ) 300))))))
202 Vector3f/ZERO
203 Vector3f/ZERO
204 Vector3f/ZERO]))
206 (defn test-motor-control
207 "Testing motor-control:
208 You should see a multi-segmented worm-like object fall onto the
209 table and begin writhing and moving."
210 []
211 (let [worm (eve-worm)
212 time (atom 0)
213 worm-motor-map (vector-motor-control worm)]
214 (world
215 (nodify [worm
216 (box 10 0.5 10 :position (Vector3f. 0 -5 0) :mass 0
217 :color ColorRGBA/Gray)])
218 standard-debug-controls
219 (fn [world]
220 (enable-debug world)
221 (light-up-everything world)
222 (comment
223 (com.aurellem.capture.Capture/captureVideo
224 world
225 (file-str "/home/r/proj/cortex/tmp/moving-worm")))
226 )
228 (fn [_ _]
229 (swap! time inc)
230 (Thread/sleep 20)
231 (dorun (worm-motor-map
232 (worm-pattern @time)))))))
236 (defn join-at-point [obj-a obj-b world-pivot]
237 (cortex.silly/joint-dispatch
238 {:type :point}
239 (.getControl obj-a RigidBodyControl)
240 (.getControl obj-b RigidBodyControl)
241 (cortex.silly/world-to-local obj-a world-pivot)
242 (cortex.silly/world-to-local obj-b world-pivot)
243 nil
244 ))
246 (import com.jme3.bullet.collision.PhysicsCollisionObject)
248 (defn blab-* []
249 (let [hand (box 0.5 0.2 0.2 :position (Vector3f. 0 0 0)
250 :mass 0 :color ColorRGBA/Green)
251 finger (box 0.5 0.2 0.2 :position (Vector3f. 2.4 0 0)
252 :mass 1 :color ColorRGBA/Red)
253 connection-point (Vector3f. 1.2 0 0)
254 root (nodify [hand finger])]
256 (join-at-point hand finger (Vector3f. 1.2 0 0))
258 (.setCollisionGroup
259 (.getControl hand RigidBodyControl)
260 PhysicsCollisionObject/COLLISION_GROUP_NONE)
261 (world
262 root
263 standard-debug-controls
264 (fn [world]
265 (enable-debug world)
266 (.setTimer world (com.aurellem.capture.RatchetTimer. 60))
267 (set-gravity world Vector3f/ZERO)
268 )
269 no-op)))
270 (import java.awt.image.BufferedImage)
272 (defn draw-sprite [image sprite x y color ]
273 (dorun
274 (for [[u v] sprite]
275 (.setRGB image (+ u x) (+ v y) color))))
277 (defn view-angle
278 "create a debug view of an angle"
279 [color]
280 (let [image (BufferedImage. 50 50 BufferedImage/TYPE_INT_RGB)
281 previous (atom [25 25])
282 sprite [[0 0] [0 1]
283 [0 -1] [-1 0] [1 0]]]
284 (fn [angle]
285 (let [angle (float angle)]
286 (let [position
287 [(+ 25 (int (* 20 (Math/cos angle))))
288 (+ 25 (int (* 20(Math/sin angle))))]]
289 (draw-sprite image sprite (@previous 0) (@previous 1) 0x000000)
290 (draw-sprite image sprite (position 0) (position 1) color)
291 (reset! previous position))
292 image))))
294 (defn proprioception-debug-window
295 []
296 (let [yaw (view-angle 0xFF0000)
297 roll (view-angle 0x00FF00)
298 pitch (view-angle 0xFFFFFF)
299 v-yaw (view-image)
300 v-roll (view-image)
301 v-pitch (view-image)
302 ]
303 (fn [prop-data]
304 (dorun
305 (map
306 (fn [[y r p]]
307 (v-yaw (yaw y))
308 (v-roll (roll r))
309 (v-pitch (pitch p)))
310 prop-data)))))
311 (comment
313 (defn proprioception-debug-window
314 []
315 (let [time (atom 0)]
316 (fn [prop-data]
317 (if (= 0 (rem (swap! time inc) 40))
318 (println-repl prop-data)))))
319 )
321 (comment
322 (dorun
323 (map
324 (comp
325 println-repl
326 (fn [[p y r]]
327 (format
328 "pitch: %1.2f\nyaw: %1.2f\nroll: %1.2f\n"
329 p y r)))
330 prop-data)))
334 (defn tap [obj direction force]
335 (let [control (.getControl obj RigidBodyControl)]
336 (.applyTorque
337 control
338 (.mult (.getPhysicsRotation control)
339 (.mult (.normalize direction) (float force))))))
343 (defn test-proprioception
344 "Testing proprioception:
345 You should see two foating bars, and a printout of pitch, yaw, and
346 roll. Pressing key-r/key-t should move the blue bar up and down and
347 change only the value of pitch. key-f/key-g moves it side to side
348 and changes yaw. key-v/key-b will spin the blue segment clockwise
349 and counterclockwise, and only affect roll."
350 []
351 (let [hand (box 1 0.2 0.2 :position (Vector3f. 0 2 0)
352 :mass 0 :color ColorRGBA/Green :name "hand")
353 finger (box 1 0.2 0.2 :position (Vector3f. 2.4 2 0)
354 :mass 1 :color ColorRGBA/Red :name "finger")
355 joint-node (box 0.1 0.05 0.05 :color ColorRGBA/Yellow
356 :position (Vector3f. 1.2 2 0)
357 :physical? false)
358 joint (join-at-point hand finger (Vector3f. 1.2 2 0 ))
359 creature (nodify [hand finger joint-node])
360 ;; *******************************************
361 hand2 (box 1 0.2 0.2 :position (Vector3f. 0 1.5 -3)
362 :mass 0 :color ColorRGBA/Blue)
363 finger2 (box 1 0.2 0.2 :position (Vector3f. 2.4 1.5 -3)
364 :mass 1 :color ColorRGBA/Magenta)
365 joint-node2 (box 0.1 0.05 0.05 :color ColorRGBA/Gray
366 :position (Vector3f. 1.2 1.5 -3)
367 :physical? false)
368 joint2 (join-at-point hand2 finger2 (Vector3f. 1.2 1.5 -3))
369 creature2 (nodify [hand2 finger2 joint-node2])
370 ;; *******************************************
372 floor (box 10 10 10 :position (Vector3f. 0 -15 0)
373 :mass 0 :color ColorRGBA/Gray)
375 move-up? (atom false)
376 move-down? (atom false)
377 move-left? (atom false)
378 move-right? (atom false)
379 roll-left? (atom false)
380 roll-right? (atom false)
383 root (nodify [creature creature2 floor])
384 prop (joint-proprioception creature joint-node)
385 prop-view (proprioception-debug-window)]
389 (comment
390 (.setCollisionGroup
391 (.getControl hand RigidBodyControl)
392 PhysicsCollisionObject/COLLISION_GROUP_NONE)
393 )
396 (world
397 root
398 (merge standard-debug-controls
399 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
400 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
401 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
402 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
403 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
404 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
405 (fn [world]
406 (.setTimer world (com.aurellem.capture.RatchetTimer. 60))
407 (set-gravity world (Vector3f. 0 0 0))
408 (light-up-everything world))
409 (fn [_ _]
410 (let [force 10
411 left (Vector3f. 0 1 0)
412 right (Vector3f. 0 -1 0)
413 up (Vector3f. 0 0 1)
414 down (Vector3f. 0 0 -1)
415 roll-left (Vector3f. -1 0 0)
416 roll-right (Vector3f. 1 0 0)]
417 (if @move-up? (tap finger up force))
418 (if @move-down? (tap finger down force))
419 (if @move-left? (tap finger left force))
420 (if @move-right? (tap finger right force))
421 (if @roll-left? (tap finger roll-left (/ force 10)))
422 (if @roll-right? (tap finger roll-right (/ force 10))))
423 (prop-view (list (prop)))))))
425 #+end_src
427 #+results: test-body
428 : #'cortex.test.body/test-proprioception
431 * COMMENT code-limbo
432 #+begin_src clojure
433 ;;(.loadModel
434 ;; (doto (asset-manager)
435 ;; (.registerLoader BlenderModelLoader (into-array String ["blend"])))
436 ;; "Models/person/person.blend")
439 (defn load-blender-model
440 "Load a .blend file using an asset folder relative path."
441 [^String model]
442 (.loadModel
443 (doto (asset-manager)
444 (.registerLoader BlenderModelLoader (into-array String ["blend"])))
445 model))
448 (defn view-model [^String model]
449 (view
450 (.loadModel
451 (doto (asset-manager)
452 (.registerLoader BlenderModelLoader (into-array String ["blend"])))
453 model)))
455 (defn load-blender-scene [^String model]
456 (.loadModel
457 (doto (asset-manager)
458 (.registerLoader BlenderLoader (into-array String ["blend"])))
459 model))
461 (defn worm
462 []
463 (.loadModel (asset-manager) "Models/anim2/Cube.mesh.xml"))
465 (defn oto
466 []
467 (.loadModel (asset-manager) "Models/Oto/Oto.mesh.xml"))
469 (defn sinbad
470 []
471 (.loadModel (asset-manager) "Models/Sinbad/Sinbad.mesh.xml"))
473 (defn worm-blender
474 []
475 (first (seq (.getChildren (load-blender-model
476 "Models/anim2/simple-worm.blend")))))
478 (defn body
479 "given a node with a SkeletonControl, will produce a body sutiable
480 for AI control with movement and proprioception."
481 [node]
482 (let [skeleton-control (.getControl node SkeletonControl)
483 krc (KinematicRagdollControl.)]
484 (comment
485 (dorun
486 (map #(.addBoneName krc %)
487 ["mid2" "tail" "head" "mid1" "mid3" "mid4" "Dummy-Root" ""]
488 ;;"mid2" "mid3" "tail" "head"]
489 )))
490 (.addControl node krc)
491 (.setRagdollMode krc)
492 )
493 node
494 )
495 (defn show-skeleton [node]
496 (let [sd
498 (doto
499 (SkeletonDebugger. "aurellem-skel-debug"
500 (skel node))
501 (.setMaterial (green-x-ray)))]
502 (.attachChild node sd)
503 node))
507 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
509 ;; this could be a good way to give objects special properties like
510 ;; being eyes and the like
512 (.getUserData
513 (.getChild
514 (load-blender-model "Models/property/test.blend") 0)
515 "properties")
517 ;; the properties are saved along with the blender file.
518 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
523 (defn init-debug-skel-node
524 [f debug-node skeleton]
525 (let [bones
526 (map #(.getBone skeleton %)
527 (range (.getBoneCount skeleton)))]
528 (dorun (map #(.setUserControl % true) bones))
529 (dorun (map (fn [b]
530 (println (.getName b)
531 " -- " (f b)))
532 bones))
533 (dorun
534 (map #(.attachChild
535 debug-node
536 (doto
537 (sphere 0.1
538 :position (f %)
539 :physical? false)
540 (.setMaterial (green-x-ray))))
541 bones)))
542 debug-node)
544 (import jme3test.bullet.PhysicsTestHelper)
547 (defn test-zzz [the-worm world value]
548 (if (not value)
549 (let [skeleton (skel the-worm)]
550 (println-repl "enabling bones")
551 (dorun
552 (map
553 #(.setUserControl (.getBone skeleton %) true)
554 (range (.getBoneCount skeleton))))
557 (let [b (.getBone skeleton 2)]
558 (println-repl "moving " (.getName b))
559 (println-repl (.getLocalPosition b))
560 (.setUserTransforms b
561 Vector3f/UNIT_X
562 Quaternion/IDENTITY
563 ;;(doto (Quaternion.)
564 ;; (.fromAngles (/ Math/PI 2)
565 ;; 0
566 ;; 0
568 (Vector3f. 1 1 1))
569 )
571 (println-repl "hi! <3"))))
574 (defn test-ragdoll []
576 (let [the-worm
578 ;;(.loadModel (asset-manager) "Models/anim2/Cube.mesh.xml")
579 (doto (show-skeleton (worm-blender))
580 (.setLocalTranslation (Vector3f. 0 10 0))
581 ;;(worm)
582 ;;(oto)
583 ;;(sinbad)
584 )
585 ]
588 (.start
589 (world
590 (doto (Node.)
591 (.attachChild the-worm))
592 {"key-return" (fire-cannon-ball)
593 "key-space" (partial test-zzz the-worm)
594 }
595 (fn [world]
596 (light-up-everything world)
597 (PhysicsTestHelper/createPhysicsTestWorld
598 (.getRootNode world)
599 (asset-manager)
600 (.getPhysicsSpace
601 (.getState (.getStateManager world) BulletAppState)))
602 (set-gravity world Vector3f/ZERO)
603 ;;(.setTimer world (NanoTimer.))
604 ;;(org.lwjgl.input.Mouse/setGrabbed false)
605 )
606 no-op
607 )
610 )))
613 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
614 ;;; here is the ragdoll stuff
616 (def worm-mesh (.getMesh (.getChild (worm-blender) 0)))
617 (def mesh worm-mesh)
619 (.getFloatBuffer mesh VertexBuffer$Type/Position)
620 (.getFloatBuffer mesh VertexBuffer$Type/BoneWeight)
621 (.getData (.getBuffer mesh VertexBuffer$Type/BoneIndex))
624 (defn position [index]
625 (.get
626 (.getFloatBuffer worm-mesh VertexBuffer$Type/Position)
627 index))
629 (defn bones [index]
630 (.get
631 (.getData (.getBuffer mesh VertexBuffer$Type/BoneIndex))
632 index))
634 (defn bone-weights [index]
635 (.get
636 (.getFloatBuffer mesh VertexBuffer$Type/BoneWeight)
637 index))
641 (defn vertex-bones [vertex]
642 (vec (map (comp int bones) (range (* vertex 4) (+ (* vertex 4) 4)))))
644 (defn vertex-weights [vertex]
645 (vec (map (comp float bone-weights) (range (* vertex 4) (+ (* vertex 4) 4)))))
647 (defn vertex-position [index]
648 (let [offset (* index 3)]
649 (Vector3f. (position offset)
650 (position (inc offset))
651 (position (inc(inc offset))))))
653 (def vertex-info (juxt vertex-position vertex-bones vertex-weights))
655 (defn bone-control-color [index]
656 (get {[1 0 0 0] ColorRGBA/Red
657 [1 2 0 0] ColorRGBA/Magenta
658 [2 0 0 0] ColorRGBA/Blue}
659 (vertex-bones index)
660 ColorRGBA/White))
662 (defn influence-color [index bone-num]
663 (get
664 {(float 0) ColorRGBA/Blue
665 (float 0.5) ColorRGBA/Green
666 (float 1) ColorRGBA/Red}
667 ;; find the weight of the desired bone
668 ((zipmap (vertex-bones index)(vertex-weights index))
669 bone-num)
670 ColorRGBA/Blue))
672 (def worm-vertices (set (map vertex-info (range 60))))
675 (defn test-info []
676 (let [points (Node.)]
677 (dorun
678 (map #(.attachChild points %)
679 (map #(sphere 0.01
680 :position (vertex-position %)
681 :color (influence-color % 1)
682 :physical? false)
683 (range 60))))
684 (view points)))
687 (defrecord JointControl [joint physics-space]
688 PhysicsControl
689 (setPhysicsSpace [this space]
690 (dosync
691 (ref-set (:physics-space this) space))
692 (.addJoint space (:joint this)))
693 (update [this tpf])
694 (setSpatial [this spatial])
695 (render [this rm vp])
696 (getPhysicsSpace [this] (deref (:physics-space this)))
697 (isEnabled [this] true)
698 (setEnabled [this state]))
700 (defn add-joint
701 "Add a joint to a particular object. When the object is added to the
702 PhysicsSpace of a simulation, the joint will also be added"
703 [object joint]
704 (let [control (JointControl. joint (ref nil))]
705 (.addControl object control))
706 object)
709 (defn hinge-world
710 []
711 (let [sphere1 (sphere)
712 sphere2 (sphere 1 :position (Vector3f. 3 3 3))
713 joint (Point2PointJoint.
714 (.getControl sphere1 RigidBodyControl)
715 (.getControl sphere2 RigidBodyControl)
716 Vector3f/ZERO (Vector3f. 3 3 3))]
717 (add-joint sphere1 joint)
718 (doto (Node. "hinge-world")
719 (.attachChild sphere1)
720 (.attachChild sphere2))))
723 (defn test-joint []
724 (view (hinge-world)))
726 ;; (defn copier-gen []
727 ;; (let [count (atom 0)]
728 ;; (fn [in]
729 ;; (swap! count inc)
730 ;; (clojure.contrib.duck-streams/copy
731 ;; in (File. (str "/home/r/tmp/mao-test/clojure-images/"
732 ;; ;;/home/r/tmp/mao-test/clojure-images
733 ;; (format "%08d.png" @count)))))))
734 ;; (defn decrease-framerate []
735 ;; (map
736 ;; (copier-gen)
737 ;; (sort
738 ;; (map first
739 ;; (partition
740 ;; 4
741 ;; (filter #(re-matches #".*.png$" (.getCanonicalPath %))
742 ;; (file-seq
743 ;; (file-str
744 ;; "/home/r/media/anime/mao-temp/images"))))))))
748 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
750 (defn proprioception
751 "Create a proprioception map that reports the rotations of the
752 various limbs of the creature's body"
753 [creature]
754 [#^Node creature]
755 (let [
756 nodes (node-seq creature)
757 joints
758 (map
759 :joint
760 (filter
761 #(isa? (class %) JointControl)
762 (reduce
763 concat
764 (map (fn [node]
765 (map (fn [num] (.getControl node num))
766 (range (.getNumControls node))))
767 nodes))))]
768 (fn []
769 (reduce concat (map relative-positions (list (first joints)))))))
772 (defn skel [node]
773 (doto
774 (.getSkeleton
775 (.getControl node SkeletonControl))
776 ;; this is necessary to force the skeleton to have accurate world
777 ;; transforms before it is rendered to the screen.
778 (.resetAndUpdate)))
780 (defn green-x-ray []
781 (doto (Material. (asset-manager)
782 "Common/MatDefs/Misc/Unshaded.j3md")
783 (.setColor "Color" ColorRGBA/Green)
784 (-> (.getAdditionalRenderState)
785 (.setDepthTest false))))
787 (defn test-worm []
788 (.start
789 (world
790 (doto (Node.)
791 ;;(.attachChild (point-worm))
792 (.attachChild (load-blender-model
793 "Models/anim2/joint-worm.blend"))
795 (.attachChild (box 10 1 10
796 :position (Vector3f. 0 -2 0) :mass 0
797 :color (ColorRGBA/Gray))))
798 {
799 "key-space" (fire-cannon-ball)
800 }
801 (fn [world]
802 (enable-debug world)
803 (light-up-everything world)
804 ;;(.setTimer world (NanoTimer.))
805 )
806 no-op)))
810 ;; defunct movement stuff
811 (defn torque-controls [control]
812 (let [torques
813 (concat
814 (map #(Vector3f. 0 (Math/sin %) (Math/cos %))
815 (range 0 (* Math/PI 2) (/ (* Math/PI 2) 20)))
816 [Vector3f/UNIT_X])]
817 (map (fn [torque-axis]
818 (fn [torque]
819 (.applyTorque
820 control
821 (.mult (.mult (.getPhysicsRotation control)
822 torque-axis)
823 (float
824 (* (.getMass control) torque))))))
825 torques)))
827 (defn motor-map
828 "Take a creature and generate a function that will enable fine
829 grained control over all the creature's limbs."
830 [#^Node creature]
831 (let [controls (keep #(.getControl % RigidBodyControl)
832 (node-seq creature))
833 limb-controls (reduce concat (map torque-controls controls))
834 body-control (partial map #(%1 %2) limb-controls)]
835 body-control))
837 (defn test-motor-map
838 "see how torque works."
839 []
840 (let [finger (box 3 0.5 0.5 :position (Vector3f. 0 2 0)
841 :mass 1 :color ColorRGBA/Green)
842 motor-map (motor-map finger)]
843 (world
844 (nodify [finger
845 (box 10 0.5 10 :position (Vector3f. 0 -5 0) :mass 0
846 :color ColorRGBA/Gray)])
847 standard-debug-controls
848 (fn [world]
849 (set-gravity world Vector3f/ZERO)
850 (light-up-everything world)
851 (.setTimer world (NanoTimer.)))
852 (fn [_ _]
853 (dorun (motor-map [0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0]))))))
854 #+end_src
862 * COMMENT generate Source
863 #+begin_src clojure :tangle ../src/cortex/body.clj
864 <<proprioception>>
865 <<motor-control>>
866 #+end_src
868 #+begin_src clojure :tangle ../src/cortex/test/body.clj
869 <<test-body>>
870 #+end_src