Mercurial > cortex
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 McIntyre3 #+email: rlm@mit.edu4 #+description: Simulating a body (movement, touch, propioception) in jMonkeyEngine3.5 #+SETUPFILE: ../../aurellem/org/setup.org6 #+INCLUDE: ../../aurellem/org/level-0.org8 * Body10 #+srcname: body-main11 #+begin_src clojure12 (ns cortex.body13 (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-model20 [^String model]21 (.loadModel22 (doto (asset-manager)23 (.registerLoader BlenderModelLoader (into-array String ["blend"])))24 model))26 (defn skel [node]27 (doto28 (.getSkeleton29 (.getControl node SkeletonControl))30 ;; this is necessary to force the skeleton to have accurate world31 ;; transforms before it is rendered to the screen.32 (.resetAndUpdate)))34 (defprotocol Textual35 (text [something]36 "Display a detailed textual analysis of the given object."))38 (extend-type com.jme3.scene.Node39 Textual40 (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.AnimControl49 Textual50 (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.SkeletonControl56 Textual57 (text [control]58 (println "Skeleton Control with the following skeleton:")59 (println (.getSkeleton control))))61 (extend-type com.jme3.bullet.control.KinematicRagdollControl62 Textual63 (text [control]64 (println "Ragdoll Control")))67 (extend-type com.jme3.scene.Geometry68 Textual69 (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-segment87 [n]88 (box segment-length radius radius :mass 0.189 :position90 (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 nodify97 "take a sequence of things that can be attached to a node and return98 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-midpoint106 [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 pivotA116 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 (.start127 (world128 (doto (Node.)129 ;;(.attachChild (point-worm))130 (.attachChild (load-blender-model131 "Models/anim2/joint-worm.blend"))133 (.attachChild (box 10 1 10134 :position (Vector3f. 0 -2 0) :mass 0135 :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 using153 ;; torque applied to their joints. There's not a single straight line154 ;; of force in the human body at all! (a straight line of force would155 ;; correspond to some sort of jet or rocket propulseion)157 (defn node-seq158 "Take a node and return a seq of all its children159 recursively. There will be no nodes left in the resulting160 structure"161 [#^Node node]162 (tree-seq #(isa? (class %) Node) #(.getChildren %) node))165 (defn torque-controls [control]166 (let [torques167 (concat168 (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 (.applyTorque174 control175 (.mult (.mult (.getPhysicsRotation control)176 torque-axis)177 (float178 (* (.getMass control) torque))))))179 torques)))181 (defn motor-map182 "Take a creature and generate a function that will enable fine183 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-map192 "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 (world198 (nodify [finger199 (box 10 0.5 10 :position (Vector3f. 0 -5 0) :mass 0200 :color ColorRGBA/Gray)])201 standard-debug-controls202 (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-torque210 "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 (world218 (nodify [finger219 (box 10 0.5 10 :position (Vector3f. 0 -5 0) :mass 0220 :color ColorRGBA/Gray)])221 (merge standard-debug-controls222 {"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 control231 (.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 0239 0 0 0 0 0 0 0 0 0 0 0241 (* 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 0244 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 0245 0 0 0 0 0 0 0 0 0 0 0 0 0 0247 ])249 ;;;;;;;;;;;;;;;;;; Proprioception ;;;;;;;;;;;;;;;;;;;;;;;;251 ;; this is not used as just getting the rotation would be simpler.252 (defn proprioception-senses253 "given a control , create a sequence of thunks that will report the254 rotation of the control's object along the same axes as the motor-control map."255 [control]256 (let [torques257 (concat258 (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-vect267 "Return a vector orthogonal to the current one"268 [vector]269 (let [x (.getX vector)270 y (.getY vector)271 z (.getZ vector)]272 (cond273 (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 ;; from279 ;; http://stackoverflow.com/questions/3684269/ \\280 ;; component-of-a-quaternion-rotation-around-an-axis281 (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-axis292 (doto (Quaternion.)293 (.fromAngleAxis294 (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-a301 (.normalize302 (.subtract303 (.localToWorld object-a (.getPivotA joint) nil)304 (.getWorldTranslation object-a)))305 rotate-a306 (doto (Matrix3f.)307 (.fromStartEndVectors arm-a Vector3f/UNIT_X))308 arm-b309 (.mult310 rotate-a311 (.normalize312 (.subtract313 (.localToWorld object-b (.getPivotB joint) nil)314 (.getWorldTranslation object-b))))315 pitch316 (.angleBetween317 (.normalize (Vector2f. (.getX arm-b) (.getY arm-b)))318 (Vector2f. 1 0))319 yaw320 (.angleBetween321 (.normalize (Vector2f. (.getX arm-b) (.getZ arm-b)))322 (Vector2f. 1 0))324 roll325 (rot-about-axis326 (.mult327 (.getLocalRotation object-b)328 (doto (Quaternion.)329 (.fromRotationMatrix rotate-a)))330 arm-b)331 ]335 ;;(println-repl336 ;; "arm-b is " arm-b)337 ;;(println-repl338 ;; "pivot-b is " (.getPivotB joint))339 ;;(println-repl340 ;; (format "pitch: %1.2f\nyaw: %1.2f\nroll: %1.2f\n"341 ;; pitch yaw roll))342 [pitch yaw roll]))350 (defn test-worm-control351 []352 (let [worm (point-worm)353 time (atom 0)354 worm-motor-map (motor-map worm)355 ;;body-map (proprioception worm)356 debug-segments357 (map358 #(doto359 (make-shape360 (assoc base-shape361 :name "debug-line"362 :physical? false363 :shape364 (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 (world372 (nodify [worm373 (box 10 0.5 10 :position (Vector3f. 0 -5 0) :mass 0374 :color ColorRGBA/Gray)])375 standard-debug-controls376 (fn [world]377 (.attachChild (.getRootNode world) (nodify debug-segments))378 (enable-debug world)379 (light-up-everything world)380 (com.aurellem.capture.Capture/captureVideo381 world382 (file-str "/home/r/proj/cortex/tmp/moving-worm")))384 (fn [_ _]385 (dorun386 (map387 (fn [worm-segment388 debug-segment]389 (.rotate390 debug-segment391 (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-map398 (worm-pattern @time)))))))404 (defn test-prop405 "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 joint422 (doto423 (Point2PointJoint.424 (.getControl hand RigidBodyControl)425 control426 (Vector3f. 1.2 0 0)427 (Vector3f. -1.2 0 0 ))428 (.setCollisionBetweenLinkedBodys false))429 time (atom 0)430 ]431 (world432 (nodify [hand finger floor])433 (merge standard-debug-controls434 {"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 control450 (.mult (.getPhysicsRotation control)451 (Vector3f. 0 0 10))))452 (if @move-down?453 (.applyTorque control454 (.mult (.getPhysicsRotation control)455 (Vector3f. 0 0 -10))))456 (if @move-left?457 (.applyTorque control458 (.mult (.getPhysicsRotation control)459 (Vector3f. 0 10 0))))460 (if @move-right?461 (.applyTorque control462 (.mult (.getPhysicsRotation control)463 (Vector3f. 0 -10 0))))464 (if @roll-left?465 (.applyTorque control466 (.mult (.getPhysicsRotation control)467 (Vector3f. -1 0 0))))468 (if @roll-right?469 (.applyTorque control470 (.mult (.getPhysicsRotation control)471 (Vector3f. 1 0 0))))473 (if (= 0 (rem (swap! time inc) 2000))474 (do476 (apply477 (comp478 println-repl479 #(format "pitch: %1.2f\nyaw: %1.2f\nroll: %1.2f\n" %1 %2 %3))480 (relative-positions joint))))))))482 #+end_src485 * COMMENT failed-clojure-code486 #+begin_src clojure487 ;;(.loadModel488 ;; (doto (asset-manager)489 ;; (.registerLoader BlenderModelLoader (into-array String ["blend"])))490 ;; "Models/person/person.blend")492 (defn view-model [^String model]493 (view494 (.loadModel495 (doto (asset-manager)496 (.registerLoader BlenderModelLoader (into-array String ["blend"])))497 model)))499 (defn load-blender-scene [^String model]500 (.loadModel501 (doto (asset-manager)502 (.registerLoader BlenderLoader (into-array String ["blend"])))503 model))505 (defn worm506 []507 (.loadModel (asset-manager) "Models/anim2/Cube.mesh.xml"))509 (defn oto510 []511 (.loadModel (asset-manager) "Models/Oto/Oto.mesh.xml"))513 (defn sinbad514 []515 (.loadModel (asset-manager) "Models/Sinbad/Sinbad.mesh.xml"))517 (defn worm-blender518 []519 (first (seq (.getChildren (load-blender-model520 "Models/anim2/simple-worm.blend")))))522 (defn body523 "given a node with a SkeletonControl, will produce a body sutiable524 for AI control with movement and proprioception."525 [node]526 (let [skeleton-control (.getControl node SkeletonControl)527 krc (KinematicRagdollControl.)]528 (comment529 (dorun530 (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 node538 )539 (defn show-skeleton [node]540 (let [sd542 (doto543 (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 like554 ;; being eyes and the like556 (.getUserData557 (.getChild558 (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-node568 [f debug-node skeleton]569 (let [bones570 (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 (dorun578 (map #(.attachChild579 debug-node580 (doto581 (sphere 0.1582 :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 (dorun596 (map597 #(.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 b605 Vector3f/UNIT_X606 Quaternion/IDENTITY607 ;;(doto (Quaternion.)608 ;; (.fromAngles (/ Math/PI 2)609 ;; 0610 ;; 0612 (Vector3f. 1 1 1))613 )615 (println-repl "hi! <3"))))618 (defn test-ragdoll []620 (let [the-worm622 ;;(.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 (.start633 (world634 (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/createPhysicsTestWorld642 (.getRootNode world)643 (asset-manager)644 (.getPhysicsSpace645 (.getState (.getStateManager world) BulletAppState)))646 (set-gravity world Vector3f/ZERO)647 ;;(.setTimer world (NanoTimer.))648 ;;(org.lwjgl.input.Mouse/setGrabbed false)649 )650 no-op651 )654 )))657 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;658 ;;; here is the ragdoll stuff660 (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 (.get670 (.getFloatBuffer worm-mesh VertexBuffer$Type/Position)671 index))673 (defn bones [index]674 (.get675 (.getData (.getBuffer mesh VertexBuffer$Type/BoneIndex))676 index))678 (defn bone-weights [index]679 (.get680 (.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/Red701 [1 2 0 0] ColorRGBA/Magenta702 [2 0 0 0] ColorRGBA/Blue}703 (vertex-bones index)704 ColorRGBA/White))706 (defn influence-color [index bone-num]707 (get708 {(float 0) ColorRGBA/Blue709 (float 0.5) ColorRGBA/Green710 (float 1) ColorRGBA/Red}711 ;; find the weight of the desired bone712 ((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 (dorun722 (map #(.attachChild points %)723 (map #(sphere 0.01724 :position (vertex-position %)725 :color (influence-color % 1)726 :physical? false)727 (range 60))))728 (view points)))731 (defrecord JointControl [joint physics-space]732 PhysicsControl733 (setPhysicsSpace [this space]734 (dosync735 (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-joint745 "Add a joint to a particular object. When the object is added to the746 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-world754 []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/copy775 ;; in (File. (str "/home/r/tmp/mao-test/clojure-images/"776 ;; ;;/home/r/tmp/mao-test/clojure-images777 ;; (format "%08d.png" @count)))))))778 ;; (defn decrease-framerate []779 ;; (map780 ;; (copier-gen)781 ;; (sort782 ;; (map first783 ;; (partition784 ;; 4785 ;; (filter #(re-matches #".*.png$" (.getCanonicalPath %))786 ;; (file-seq787 ;; (file-str788 ;; "/home/r/media/anime/mao-temp/images"))))))))792 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;794 (defn proprioception795 "Create a proprioception map that reports the rotations of the796 various limbs of the creature's body"797 [creature]798 [#^Node creature]799 (let [800 nodes (node-seq creature)801 joints802 (map803 :joint804 (filter805 #(isa? (class %) JointControl)806 (reduce807 concat808 (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_src824 * COMMENT generate Source.825 #+begin_src clojure :tangle ../src/cortex/body.clj826 <<body-main>>827 #+end_src