Mercurial > cortex
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 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 * Proprioception9 #+name: proprioception10 #+begin_src clojure11 (ns cortex.body12 (:use (cortex world util))13 (:import14 com.jme3.math.Vector3f15 com.jme3.math.Quaternion16 com.jme3.math.Vector2f17 com.jme3.math.Matrix3f18 com.jme3.bullet.control.RigidBodyControl19 com.jme3.collision.CollisionResults20 com.jme3.bounding.BoundingBox))22 (import com.jme3.scene.Node)24 (defn jme-to-blender25 "Convert from JME coordinates to Blender coordinates"26 [#^Vector3f in]27 (Vector3f. (.getX in)28 (- (.getZ in))29 (.getY in)))31 (defn joint-targets32 "Return the two closest two objects to the joint object, ordered33 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 (.collideWith38 parts39 (BoundingBox. (.getWorldTranslation joint)40 radius radius radius)41 results)42 (let [targets43 (distinct44 (map #(.getGeometry %) results))]45 (if (>= (count targets) 2)46 (sort-by47 #(let [v48 (jme-to-blender49 (.mult50 (.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-joints60 "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 the73 ;; joint.74 (fn []75 ;; x is the "twist" axis, y and z are the "bend" axes76 (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-joint84 (doto (Quaternion.)85 (.fromRotationMatrix86 (.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 basis91 [yaw roll pitch]92 ))))95 (defn proprioception96 "Create a function that provides proprioceptive information about an97 entire body."98 [#^Node creature]99 ;; extract the body's joints100 (let [joints (creature-joints creature)101 senses (map (partial joint-proprioception creature) joints)]102 (fn []103 (map #(%) senses))))105 #+end_src107 #+results: proprioception108 : #'cortex.body/proprioception110 * Motor Control111 #+name: motor-control112 #+begin_src clojure113 (in-ns 'cortex.body)115 ;; surprisingly enough, terristerial creatures only move by using116 ;; torque applied about their joints. There's not a single straight117 ;; line of force in the human body at all! (A straight line of force118 ;; would correspond to some sort of jet or rocket propulseion.)120 (defn vector-motor-control121 "Create a function that accepts a sequence of Vector3f objects that122 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_src132 ## note -- might want to add a lower dimensional, discrete version of133 ## this if it proves useful from a x-modal clustering perspective.135 * Examples137 #+name: test-body138 #+begin_src clojure139 (ns cortex.test.body140 (:use (cortex world util body))141 (:require cortex.silly)142 (:import143 com.jme3.math.Vector3f144 com.jme3.math.ColorRGBA145 com.jme3.bullet.joints.Point2PointJoint146 com.jme3.bullet.control.RigidBodyControl147 com.jme3.system.NanoTimer))149 (defn worm-segments150 "Create multiple evenly spaced box segments. They're fabulous!"151 [segment-length num-segments interstitial-space radius]152 (letfn [(nth-segment153 [n]154 (box segment-length radius radius :mass 0.1155 :position156 (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-midpoint163 "Connect two physics objects with a Point2Point joint constraint at164 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 registers173 ;; it with both physics objects which in turn174 ;; will register the joint with the physics system175 ;; when the simulation is started.176 joint (Point2PointJoint.177 (.getControl segmentA RigidBodyControl)178 (.getControl segmentB RigidBodyControl)179 pivotA180 pivotB)]181 segmentB))183 (defn eve-worm184 "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-pattern192 "This is a simple, mindless motor control pattern that drives the193 second segment of the worm's body at an offset angle with194 sinusoidally varying strength."195 [time]196 (let [angle (* Math/PI (/ 9 20))197 direction (Vector3f. 0 (Math/sin angle) (Math/cos angle))]198 [Vector3f/ZERO199 (.mult200 direction201 (float (* 2 (Math/sin (* Math/PI 2 (/ (rem time 300 ) 300))))))202 Vector3f/ZERO203 Vector3f/ZERO204 Vector3f/ZERO]))206 (defn test-motor-control207 "Testing motor-control:208 You should see a multi-segmented worm-like object fall onto the209 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 (world215 (nodify [worm216 (box 10 0.5 10 :position (Vector3f. 0 -5 0) :mass 0217 :color ColorRGBA/Gray)])218 standard-debug-controls219 (fn [world]220 (enable-debug world)221 (light-up-everything world)222 (comment223 (com.aurellem.capture.Capture/captureVideo224 world225 (file-str "/home/r/proj/cortex/tmp/moving-worm")))226 )228 (fn [_ _]229 (swap! time inc)230 (Thread/sleep 20)231 (dorun (worm-motor-map232 (worm-pattern @time)))))))236 (defn join-at-point [obj-a obj-b world-pivot]237 (cortex.silly/joint-dispatch238 {: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 nil244 ))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 (.setCollisionGroup259 (.getControl hand RigidBodyControl)260 PhysicsCollisionObject/COLLISION_GROUP_NONE)261 (world262 root263 standard-debug-controls264 (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 (dorun274 (for [[u v] sprite]275 (.setRGB image (+ u x) (+ v y) color))))277 (defn view-angle278 "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 [position287 [(+ 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-window295 []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 (dorun305 (map306 (fn [[y r p]]307 (v-yaw (yaw y))308 (v-roll (roll r))309 (v-pitch (pitch p)))310 prop-data)))))311 (comment313 (defn proprioception-debug-window314 []315 (let [time (atom 0)]316 (fn [prop-data]317 (if (= 0 (rem (swap! time inc) 40))318 (println-repl prop-data)))))319 )321 (comment322 (dorun323 (map324 (comp325 println-repl326 (fn [[p y r]]327 (format328 "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 (.applyTorque337 control338 (.mult (.getPhysicsRotation control)339 (.mult (.normalize direction) (float force))))))343 (defn test-proprioception344 "Testing proprioception:345 You should see two foating bars, and a printout of pitch, yaw, and346 roll. Pressing key-r/key-t should move the blue bar up and down and347 change only the value of pitch. key-f/key-g moves it side to side348 and changes yaw. key-v/key-b will spin the blue segment clockwise349 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/Yellow356 :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/Gray366 :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 (comment390 (.setCollisionGroup391 (.getControl hand RigidBodyControl)392 PhysicsCollisionObject/COLLISION_GROUP_NONE)393 )396 (world397 root398 (merge standard-debug-controls399 {"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 10411 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_src427 #+results: test-body428 : #'cortex.test.body/test-proprioception431 * COMMENT code-limbo432 #+begin_src clojure433 ;;(.loadModel434 ;; (doto (asset-manager)435 ;; (.registerLoader BlenderModelLoader (into-array String ["blend"])))436 ;; "Models/person/person.blend")439 (defn load-blender-model440 "Load a .blend file using an asset folder relative path."441 [^String model]442 (.loadModel443 (doto (asset-manager)444 (.registerLoader BlenderModelLoader (into-array String ["blend"])))445 model))448 (defn view-model [^String model]449 (view450 (.loadModel451 (doto (asset-manager)452 (.registerLoader BlenderModelLoader (into-array String ["blend"])))453 model)))455 (defn load-blender-scene [^String model]456 (.loadModel457 (doto (asset-manager)458 (.registerLoader BlenderLoader (into-array String ["blend"])))459 model))461 (defn worm462 []463 (.loadModel (asset-manager) "Models/anim2/Cube.mesh.xml"))465 (defn oto466 []467 (.loadModel (asset-manager) "Models/Oto/Oto.mesh.xml"))469 (defn sinbad470 []471 (.loadModel (asset-manager) "Models/Sinbad/Sinbad.mesh.xml"))473 (defn worm-blender474 []475 (first (seq (.getChildren (load-blender-model476 "Models/anim2/simple-worm.blend")))))478 (defn body479 "given a node with a SkeletonControl, will produce a body sutiable480 for AI control with movement and proprioception."481 [node]482 (let [skeleton-control (.getControl node SkeletonControl)483 krc (KinematicRagdollControl.)]484 (comment485 (dorun486 (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 node494 )495 (defn show-skeleton [node]496 (let [sd498 (doto499 (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 like510 ;; being eyes and the like512 (.getUserData513 (.getChild514 (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-node524 [f debug-node skeleton]525 (let [bones526 (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 (dorun534 (map #(.attachChild535 debug-node536 (doto537 (sphere 0.1538 :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 (dorun552 (map553 #(.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 b561 Vector3f/UNIT_X562 Quaternion/IDENTITY563 ;;(doto (Quaternion.)564 ;; (.fromAngles (/ Math/PI 2)565 ;; 0566 ;; 0568 (Vector3f. 1 1 1))569 )571 (println-repl "hi! <3"))))574 (defn test-ragdoll []576 (let [the-worm578 ;;(.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 (.start589 (world590 (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/createPhysicsTestWorld598 (.getRootNode world)599 (asset-manager)600 (.getPhysicsSpace601 (.getState (.getStateManager world) BulletAppState)))602 (set-gravity world Vector3f/ZERO)603 ;;(.setTimer world (NanoTimer.))604 ;;(org.lwjgl.input.Mouse/setGrabbed false)605 )606 no-op607 )610 )))613 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;614 ;;; here is the ragdoll stuff616 (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 (.get626 (.getFloatBuffer worm-mesh VertexBuffer$Type/Position)627 index))629 (defn bones [index]630 (.get631 (.getData (.getBuffer mesh VertexBuffer$Type/BoneIndex))632 index))634 (defn bone-weights [index]635 (.get636 (.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/Red657 [1 2 0 0] ColorRGBA/Magenta658 [2 0 0 0] ColorRGBA/Blue}659 (vertex-bones index)660 ColorRGBA/White))662 (defn influence-color [index bone-num]663 (get664 {(float 0) ColorRGBA/Blue665 (float 0.5) ColorRGBA/Green666 (float 1) ColorRGBA/Red}667 ;; find the weight of the desired bone668 ((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 (dorun678 (map #(.attachChild points %)679 (map #(sphere 0.01680 :position (vertex-position %)681 :color (influence-color % 1)682 :physical? false)683 (range 60))))684 (view points)))687 (defrecord JointControl [joint physics-space]688 PhysicsControl689 (setPhysicsSpace [this space]690 (dosync691 (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-joint701 "Add a joint to a particular object. When the object is added to the702 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-world710 []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/copy731 ;; in (File. (str "/home/r/tmp/mao-test/clojure-images/"732 ;; ;;/home/r/tmp/mao-test/clojure-images733 ;; (format "%08d.png" @count)))))))734 ;; (defn decrease-framerate []735 ;; (map736 ;; (copier-gen)737 ;; (sort738 ;; (map first739 ;; (partition740 ;; 4741 ;; (filter #(re-matches #".*.png$" (.getCanonicalPath %))742 ;; (file-seq743 ;; (file-str744 ;; "/home/r/media/anime/mao-temp/images"))))))))748 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;750 (defn proprioception751 "Create a proprioception map that reports the rotations of the752 various limbs of the creature's body"753 [creature]754 [#^Node creature]755 (let [756 nodes (node-seq creature)757 joints758 (map759 :joint760 (filter761 #(isa? (class %) JointControl)762 (reduce763 concat764 (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 (doto774 (.getSkeleton775 (.getControl node SkeletonControl))776 ;; this is necessary to force the skeleton to have accurate world777 ;; 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 (.start789 (world790 (doto (Node.)791 ;;(.attachChild (point-worm))792 (.attachChild (load-blender-model793 "Models/anim2/joint-worm.blend"))795 (.attachChild (box 10 1 10796 :position (Vector3f. 0 -2 0) :mass 0797 :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 stuff811 (defn torque-controls [control]812 (let [torques813 (concat814 (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 (.applyTorque820 control821 (.mult (.mult (.getPhysicsRotation control)822 torque-axis)823 (float824 (* (.getMass control) torque))))))825 torques)))827 (defn motor-map828 "Take a creature and generate a function that will enable fine829 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-map838 "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 (world844 (nodify [finger845 (box 10 0.5 10 :position (Vector3f. 0 -5 0) :mass 0846 :color ColorRGBA/Gray)])847 standard-debug-controls848 (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_src862 * COMMENT generate Source863 #+begin_src clojure :tangle ../src/cortex/body.clj864 <<proprioception>>865 <<motor-control>>866 #+end_src868 #+begin_src clojure :tangle ../src/cortex/test/body.clj869 <<test-body>>870 #+end_src