Mercurial > cortex
view org/body.org @ 132:3206d5e20bee
still trying to fix proprioception
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Tue, 31 Jan 2012 01:40:47 -0700 |
parents | e98850b83c2c |
children | 2ed7e60d3821 |
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.RigidBodyControl))22 (defn quaternion-decompose [#^Quaternion q]23 (map24 #(arc-between % (.rotate q %))25 [Vector3f/UNIT_X26 Vector3f/UNIT_Y27 Vector3f/UNIT_Z]))29 (defn any-orthogonal30 "Generate an arbitray (but stable) orthogonal vector to a given31 vector."32 [vector]33 (let [x (.getX vector)34 y (.getY vector)35 z (.getZ vector)]36 (cond37 (not= x (float 0)) (Vector3f. (- z) 0 x)38 (not= y (float 0)) (Vector3f. 0 (- z) y)39 (not= z (float 0)) (Vector3f. 0 (- z) y)40 true Vector3f/ZERO)))42 (defn project-quaternion43 "From http://stackoverflow.com/questions/3684269/44 component-of-a-quaternion-rotation-around-an-axis.46 Determine the amount of rotation a quaternion will47 cause about a given axis."48 [#^Quaternion q #^Vector3f axis]49 (let [basis-1 (any-orthogonal axis)50 basis-2 (.cross axis basis-1)51 rotated (.mult q basis-1)52 alpha (.dot basis-1 (.project rotated basis-1))53 beta (.dot basis-2 (.project rotated basis-2))]54 (Math/atan2 beta alpha)))56 (defn right-handed? [vec1 vec2 vec3]57 (< 0 (.dot (.cross vec1 vec2) vec3)))59 (defn project-quaternion60 "From http://stackoverflow.com/questions/3684269/61 component-of-a-quaternion-rotation-around-an-axis.63 Determine the amount of rotation a quaternion will64 cause about a given axis."65 [#^Quaternion q #^Vector3f axis]66 (let [axis (.normalize axis)67 basis-1 (any-orthogonal axis)68 basis-2 (.cross axis basis-1)69 rotated (.mult q basis-1)70 rotated-in-plane (.add (.project rotated basis-1)71 (.project rotated basis-2))]73 ;; be sure to get sign from cross product74 (if (right-handed? basis-1 rotated-in-plane axis)75 (.angleBetween rotated-in-plane basis-1)76 (- (* 2 Math/PI) (.angleBetween rotated-in-plane basis-1)))))80 (defn joint-proprioception81 "Relative position information for a two-part system connected by a82 joint. Gives the pitch, yaw, and roll of the 'B' object relative to83 the 'A' object, as determined by the joint."84 [joint]85 (let [object-a (.getUserObject (.getBodyA joint))86 object-b (.getUserObject (.getBodyB joint))87 arm-a88 (.normalize89 (.subtract90 (.localToWorld object-a (.getPivotA joint) nil)91 (.getWorldTranslation object-a)))93 ;; this is probably wrong!94 rotate-a95 (doto (Matrix3f.)96 (.fromStartEndVectors arm-a Vector3f/UNIT_X))98 arm-b99 (.mult100 rotate-a101 (.normalize102 (.subtract103 (.localToWorld object-b (.getPivotB joint) nil)104 (.getWorldTranslation object-b))))105 pitch106 (.angleBetween107 (.normalize (Vector2f. (.getX arm-b) (.getY arm-b)))108 (Vector2f. 1 0))109 yaw110 (.angleBetween111 (.normalize (Vector2f. (.getX arm-b) (.getZ arm-b)))112 (Vector2f. 1 0))114 roll115 (project-quaternion116 (.mult117 (.getLocalRotation object-b)118 (doto (Quaternion.)119 (.fromRotationMatrix rotate-a)))120 arm-b)]121 ;;(println-repl (.getName object-a) (.getName object-b))122 [pitch yaw roll]))127 (defn absolute-angle-between128 [vec-1 vec-2]133 (defn joint-proprioception134 [joint]135 (let [object-a (.getUserObject (.getBodyA joint))136 object-b (.getUserObject (.getBodyB joint))138 arm-a139 (.normalize140 (.subtract141 (.localToWorld object-a (.getPivotA joint) nil)142 (.getWorldTranslation object-a)))143 arm-b144 (.normalize145 (.subtract146 (.localToWorld object-b (.getPivotB joint) nil)147 (.getWorldTranslation object-b)))149 rotate-a (.clone (.getWorldRotation object-a))150 unrotate-a (.inverse (.getWorldRotation object-a))152 canonical-arm-a (.mult unrotate-a arm-a)154 basis-1 (any-orthogonal canonical-arm-a)155 basis-2 (.normalize (.cross basis-1 canonical-arm-a))157 pitch (.angleBetween arm-b basis-1)158 yaw (.angleBetween arm-b basis-2)160 twist-a161 (project-quaternion162 (.getWorldRotation object-a) arm-a)164 twist-b165 (project-quaternion166 (.getWorldRotation object-b) arm-b)168 roll (- twist-b 0)169 ;; "un-rotate" arm-a to it's canonical position, get two170 ;; orthogonal basis vectors. Rotate those two vectors back to171 ;; the correct position get the rotations between them.173 ;; twist is the rotation about arm-a of obj-b minus the174 ;; rotation about arm-a of obj-a175 ]176 ;; object-a == hand177 ;; object-b == finger178 [pitch yaw roll]))180 ;; (defn joint-proprioception*181 ;; [joint]182 ;; (let [object-a (.getUserObject (.getBodyA joint))183 ;; object-b (.getUserObject (.getBodyB joint))185 ;; rotate-a (.clone (.getWorldRotation object-a))186 ;; rotate-b (.clone (.getWorldRotation object-b))188 ;; rotate-rel (.mult rotate-b (.inverse rotate-a))189 ;; ]190 ;; ((comp vec map) (partial project-quaternion rotate-rel)191 ;; [Vector3f/UNIT_X192 ;; Vector3f/UNIT_Y193 ;; Vector3f/UNIT_Z])))196 (defn proprioception197 "Create a function that provides proprioceptive information about an198 entire body."199 [body]200 ;; extract the body's joints201 (let [joints202 (distinct203 (reduce204 concat205 (map #(.getJoints %)206 (keep207 #(.getControl % RigidBodyControl)208 (node-seq body)))))]209 (fn []210 (map joint-proprioception joints))))212 #+end_src214 * Motor Control215 #+name: motor-control216 #+begin_src clojure217 (in-ns 'cortex.body)219 ;; surprisingly enough, terristerial creatures only move by using220 ;; torque applied about their joints. There's not a single straight221 ;; line of force in the human body at all! (A straight line of force222 ;; would correspond to some sort of jet or rocket propulseion.)224 (defn vector-motor-control225 "Create a function that accepts a sequence of Vector3f objects that226 describe the torque to be applied to each part of the body."227 [body]228 (let [nodes (node-seq body)229 controls (keep #(.getControl % RigidBodyControl) nodes)]230 (fn [torques]231 (map #(.applyTorque %1 %2)232 controls torques))))233 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;234 #+end_src236 ## note -- might want to add a lower dimensional, discrete version of237 ## this if it proves useful from a x-modal clustering perspective.239 * Examples241 #+name: test-body242 #+begin_src clojure243 (ns cortex.test.body244 (:use (cortex world util body))245 (:import246 com.jme3.math.Vector3f247 com.jme3.math.ColorRGBA248 com.jme3.bullet.joints.Point2PointJoint249 com.jme3.bullet.control.RigidBodyControl250 com.jme3.system.NanoTimer))252 (defn worm-segments253 "Create multiple evenly spaced box segments. They're fabulous!"254 [segment-length num-segments interstitial-space radius]255 (letfn [(nth-segment256 [n]257 (box segment-length radius radius :mass 0.1258 :position259 (Vector3f.260 (* 2 n (+ interstitial-space segment-length)) 0 0)261 :name (str "worm-segment" n)262 :color (ColorRGBA/randomColor)))]263 (map nth-segment (range num-segments))))265 (defn connect-at-midpoint266 "Connect two physics objects with a Point2Point joint constraint at267 the point equidistant from both objects' centers."268 [segmentA segmentB]269 (let [centerA (.getWorldTranslation segmentA)270 centerB (.getWorldTranslation segmentB)271 midpoint (.mult (.add centerA centerB) (float 0.5))272 pivotA (.subtract midpoint centerA)273 pivotB (.subtract midpoint centerB)275 ;; A side-effect of creating a joint registers276 ;; it with both physics objects which in turn277 ;; will register the joint with the physics system278 ;; when the simulation is started.279 joint (Point2PointJoint.280 (.getControl segmentA RigidBodyControl)281 (.getControl segmentB RigidBodyControl)282 pivotA283 pivotB)]284 segmentB))286 (defn eve-worm287 "Create a worm-like body bound by invisible joint constraints."288 []289 (let [segments (worm-segments 0.2 5 0.1 0.1)]290 (dorun (map (partial apply connect-at-midpoint)291 (partition 2 1 segments)))292 (nodify "worm" segments)))294 (defn worm-pattern295 "This is a simple, mindless motor control pattern that drives the296 second segment of the worm's body at an offset angle with297 sinusoidally varying strength."298 [time]299 (let [angle (* Math/PI (/ 9 20))300 direction (Vector3f. 0 (Math/sin angle) (Math/cos angle))]301 [Vector3f/ZERO302 (.mult303 direction304 (float (* 2 (Math/sin (* Math/PI 2 (/ (rem time 300 ) 300))))))305 Vector3f/ZERO306 Vector3f/ZERO307 Vector3f/ZERO]))309 (defn test-motor-control310 "Testing motor-control:311 You should see a multi-segmented worm-like object fall onto the312 table and begin writhing and moving."313 []314 (let [worm (eve-worm)315 time (atom 0)316 worm-motor-map (vector-motor-control worm)]317 (world318 (nodify [worm319 (box 10 0.5 10 :position (Vector3f. 0 -5 0) :mass 0320 :color ColorRGBA/Gray)])321 standard-debug-controls322 (fn [world]323 (enable-debug world)324 (light-up-everything world)325 (comment326 (com.aurellem.capture.Capture/captureVideo327 world328 (file-str "/home/r/proj/cortex/tmp/moving-worm")))329 )331 (fn [_ _]332 (swap! time inc)333 (Thread/sleep 20)334 (dorun (worm-motor-map335 (worm-pattern @time)))))))338 (require 'cortex.silly)339 (defn join-at-point [obj-a obj-b world-pivot]340 (cortex.silly/joint-dispatch341 {:type :point}342 (.getControl obj-a RigidBodyControl)343 (.getControl obj-b RigidBodyControl)344 (cortex.silly/world-to-local obj-a world-pivot)345 (cortex.silly/world-to-local obj-b world-pivot)346 nil347 ))351 (defn blab-* []352 (let [hand (box 0.5 0.2 0.2 :position (Vector3f. 0 0 0)353 :mass 0 :color ColorRGBA/Green)354 finger (box 0.5 0.2 0.2 :position (Vector3f. 2.4 0 0)355 :mass 1 :color ColorRGBA/Red)356 connection-point (Vector3f. 1.2 0 0)357 root (nodify [hand finger])]359 (join-at-point hand finger (Vector3f. 1.2 0 0))361 (.setCollisionGroup362 (.getControl hand RigidBodyControl)363 PhysicsCollisionObject/COLLISION_GROUP_NONE)364 (world365 root366 standard-debug-controls367 (fn [world]368 (enable-debug world)369 (.setTimer world (com.aurellem.capture.RatchetTimer. 60))370 (set-gravity world Vector3f/ZERO)371 )372 no-op)))373 (import java.awt.image.BufferedImage)375 (defn draw-sprite [image sprite x y color ]376 (dorun377 (for [[u v] sprite]378 (.setRGB image (+ u x) (+ v y) color))))380 (defn view-angle381 "create a debug view of an angle"382 [color]383 (let [image (BufferedImage. 50 50 BufferedImage/TYPE_INT_RGB)384 previous (atom [25 25])385 sprite [[0 0] [0 1]386 [0 -1] [-1 0] [1 0]]]387 (fn [angle]388 (let [angle (float angle)]389 (let [position390 [(+ 25 (int (* 20 (Math/cos angle))))391 (+ 25 (int (* 20(Math/sin angle))))]]392 (draw-sprite image sprite (@previous 0) (@previous 1) 0x000000)393 (draw-sprite image sprite (position 0) (position 1) color)394 (reset! previous position))395 image))))397 (defn proprioception-debug-window398 []399 (let [yaw (view-angle 0xFF0000)400 pitch (view-angle 0x00FF00)401 roll (view-angle 0xFFFFFF)402 v-yaw (view-image)403 v-pitch (view-image)404 v-roll (view-image)405 ]406 (fn [prop-data]407 (dorun408 (map409 (fn [[p y r]]410 (v-yaw (yaw y))411 (v-roll (roll r))412 (v-pitch (pitch p)))413 prop-data)))))415 (comment416 (dorun417 (map418 (comp419 println-repl420 (fn [[p y r]]421 (format422 "pitch: %1.2f\nyaw: %1.2f\nroll: %1.2f\n"423 p y r)))424 prop-data)))430 (defn test-proprioception431 "Testing proprioception:432 You should see two foating bars, and a printout of pitch, yaw, and433 roll. Pressing key-r/key-t should move the blue bar up and down and434 change only the value of pitch. key-f/key-g moves it side to side435 and changes yaw. key-v/key-b will spin the blue segment clockwise436 and counterclockwise, and only affect roll."437 []438 (let [hand (box 1 0.2 0.2 :position (Vector3f. 0 2 0)439 :mass 0 :color ColorRGBA/Green :name "hand")440 finger (box 1 0.2 0.2 :position (Vector3f. 2.4 2 0)441 :mass 1 :color ColorRGBA/Red :name "finger")442 floor (box 10 0.5 10 :position (Vector3f. 0 -5 0)443 :mass 0 :color ColorRGBA/Gray)445 move-up? (atom false)446 move-down? (atom false)447 move-left? (atom false)448 move-right? (atom false)449 roll-left? (atom false)450 roll-right? (atom false)451 control (.getControl finger RigidBodyControl)452 time (atom 0)453 joint (join-at-point hand finger (Vector3f. 1.2 2 0 ))454 creature (nodify [hand finger])455 prop (proprioception creature)457 prop-view (proprioception-debug-window)460 ]464 (.setCollisionGroup465 (.getControl hand RigidBodyControl)466 PhysicsCollisionObject/COLLISION_GROUP_NONE)469 (world470 (nodify [hand finger floor])471 (merge standard-debug-controls472 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))473 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))474 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))475 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))476 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))477 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})478 (fn [world]479 (.setTimer world (com.aurellem.capture.RatchetTimer. 60))480 (set-gravity world (Vector3f. 0 0 0))481 (light-up-everything world))482 (fn [_ _]483 (if @move-up?484 (.applyTorque control485 (.mult (.getPhysicsRotation control)486 (Vector3f. 0 0 10))))487 (if @move-down?488 (.applyTorque control489 (.mult (.getPhysicsRotation control)490 (Vector3f. 0 0 -10))))491 (if @move-left?492 (.applyTorque control493 (.mult (.getPhysicsRotation control)494 (Vector3f. 0 10 0))))495 (if @move-right?496 (.applyTorque control497 (.mult (.getPhysicsRotation control)498 (Vector3f. 0 -10 0))))499 (if @roll-left?500 (.applyTorque control501 (.mult (.getPhysicsRotation control)502 (Vector3f. -1 0 0))))503 (if @roll-right?504 (.applyTorque control505 (.mult (.getPhysicsRotation control)506 (Vector3f. 1 0 0))))508 ;;(if (= 0 (rem (swap! time inc) 20))509 (prop-view (prop))))))511 #+end_src513 #+results: test-body514 : #'cortex.test.body/test-proprioception517 * COMMENT code-limbo518 #+begin_src clojure519 ;;(.loadModel520 ;; (doto (asset-manager)521 ;; (.registerLoader BlenderModelLoader (into-array String ["blend"])))522 ;; "Models/person/person.blend")525 (defn load-blender-model526 "Load a .blend file using an asset folder relative path."527 [^String model]528 (.loadModel529 (doto (asset-manager)530 (.registerLoader BlenderModelLoader (into-array String ["blend"])))531 model))534 (defn view-model [^String model]535 (view536 (.loadModel537 (doto (asset-manager)538 (.registerLoader BlenderModelLoader (into-array String ["blend"])))539 model)))541 (defn load-blender-scene [^String model]542 (.loadModel543 (doto (asset-manager)544 (.registerLoader BlenderLoader (into-array String ["blend"])))545 model))547 (defn worm548 []549 (.loadModel (asset-manager) "Models/anim2/Cube.mesh.xml"))551 (defn oto552 []553 (.loadModel (asset-manager) "Models/Oto/Oto.mesh.xml"))555 (defn sinbad556 []557 (.loadModel (asset-manager) "Models/Sinbad/Sinbad.mesh.xml"))559 (defn worm-blender560 []561 (first (seq (.getChildren (load-blender-model562 "Models/anim2/simple-worm.blend")))))564 (defn body565 "given a node with a SkeletonControl, will produce a body sutiable566 for AI control with movement and proprioception."567 [node]568 (let [skeleton-control (.getControl node SkeletonControl)569 krc (KinematicRagdollControl.)]570 (comment571 (dorun572 (map #(.addBoneName krc %)573 ["mid2" "tail" "head" "mid1" "mid3" "mid4" "Dummy-Root" ""]574 ;;"mid2" "mid3" "tail" "head"]575 )))576 (.addControl node krc)577 (.setRagdollMode krc)578 )579 node580 )581 (defn show-skeleton [node]582 (let [sd584 (doto585 (SkeletonDebugger. "aurellem-skel-debug"586 (skel node))587 (.setMaterial (green-x-ray)))]588 (.attachChild node sd)589 node))593 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;595 ;; this could be a good way to give objects special properties like596 ;; being eyes and the like598 (.getUserData599 (.getChild600 (load-blender-model "Models/property/test.blend") 0)601 "properties")603 ;; the properties are saved along with the blender file.604 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;609 (defn init-debug-skel-node610 [f debug-node skeleton]611 (let [bones612 (map #(.getBone skeleton %)613 (range (.getBoneCount skeleton)))]614 (dorun (map #(.setUserControl % true) bones))615 (dorun (map (fn [b]616 (println (.getName b)617 " -- " (f b)))618 bones))619 (dorun620 (map #(.attachChild621 debug-node622 (doto623 (sphere 0.1624 :position (f %)625 :physical? false)626 (.setMaterial (green-x-ray))))627 bones)))628 debug-node)630 (import jme3test.bullet.PhysicsTestHelper)633 (defn test-zzz [the-worm world value]634 (if (not value)635 (let [skeleton (skel the-worm)]636 (println-repl "enabling bones")637 (dorun638 (map639 #(.setUserControl (.getBone skeleton %) true)640 (range (.getBoneCount skeleton))))643 (let [b (.getBone skeleton 2)]644 (println-repl "moving " (.getName b))645 (println-repl (.getLocalPosition b))646 (.setUserTransforms b647 Vector3f/UNIT_X648 Quaternion/IDENTITY649 ;;(doto (Quaternion.)650 ;; (.fromAngles (/ Math/PI 2)651 ;; 0652 ;; 0654 (Vector3f. 1 1 1))655 )657 (println-repl "hi! <3"))))660 (defn test-ragdoll []662 (let [the-worm664 ;;(.loadModel (asset-manager) "Models/anim2/Cube.mesh.xml")665 (doto (show-skeleton (worm-blender))666 (.setLocalTranslation (Vector3f. 0 10 0))667 ;;(worm)668 ;;(oto)669 ;;(sinbad)670 )671 ]674 (.start675 (world676 (doto (Node.)677 (.attachChild the-worm))678 {"key-return" (fire-cannon-ball)679 "key-space" (partial test-zzz the-worm)680 }681 (fn [world]682 (light-up-everything world)683 (PhysicsTestHelper/createPhysicsTestWorld684 (.getRootNode world)685 (asset-manager)686 (.getPhysicsSpace687 (.getState (.getStateManager world) BulletAppState)))688 (set-gravity world Vector3f/ZERO)689 ;;(.setTimer world (NanoTimer.))690 ;;(org.lwjgl.input.Mouse/setGrabbed false)691 )692 no-op693 )696 )))699 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;700 ;;; here is the ragdoll stuff702 (def worm-mesh (.getMesh (.getChild (worm-blender) 0)))703 (def mesh worm-mesh)705 (.getFloatBuffer mesh VertexBuffer$Type/Position)706 (.getFloatBuffer mesh VertexBuffer$Type/BoneWeight)707 (.getData (.getBuffer mesh VertexBuffer$Type/BoneIndex))710 (defn position [index]711 (.get712 (.getFloatBuffer worm-mesh VertexBuffer$Type/Position)713 index))715 (defn bones [index]716 (.get717 (.getData (.getBuffer mesh VertexBuffer$Type/BoneIndex))718 index))720 (defn bone-weights [index]721 (.get722 (.getFloatBuffer mesh VertexBuffer$Type/BoneWeight)723 index))727 (defn vertex-bones [vertex]728 (vec (map (comp int bones) (range (* vertex 4) (+ (* vertex 4) 4)))))730 (defn vertex-weights [vertex]731 (vec (map (comp float bone-weights) (range (* vertex 4) (+ (* vertex 4) 4)))))733 (defn vertex-position [index]734 (let [offset (* index 3)]735 (Vector3f. (position offset)736 (position (inc offset))737 (position (inc(inc offset))))))739 (def vertex-info (juxt vertex-position vertex-bones vertex-weights))741 (defn bone-control-color [index]742 (get {[1 0 0 0] ColorRGBA/Red743 [1 2 0 0] ColorRGBA/Magenta744 [2 0 0 0] ColorRGBA/Blue}745 (vertex-bones index)746 ColorRGBA/White))748 (defn influence-color [index bone-num]749 (get750 {(float 0) ColorRGBA/Blue751 (float 0.5) ColorRGBA/Green752 (float 1) ColorRGBA/Red}753 ;; find the weight of the desired bone754 ((zipmap (vertex-bones index)(vertex-weights index))755 bone-num)756 ColorRGBA/Blue))758 (def worm-vertices (set (map vertex-info (range 60))))761 (defn test-info []762 (let [points (Node.)]763 (dorun764 (map #(.attachChild points %)765 (map #(sphere 0.01766 :position (vertex-position %)767 :color (influence-color % 1)768 :physical? false)769 (range 60))))770 (view points)))773 (defrecord JointControl [joint physics-space]774 PhysicsControl775 (setPhysicsSpace [this space]776 (dosync777 (ref-set (:physics-space this) space))778 (.addJoint space (:joint this)))779 (update [this tpf])780 (setSpatial [this spatial])781 (render [this rm vp])782 (getPhysicsSpace [this] (deref (:physics-space this)))783 (isEnabled [this] true)784 (setEnabled [this state]))786 (defn add-joint787 "Add a joint to a particular object. When the object is added to the788 PhysicsSpace of a simulation, the joint will also be added"789 [object joint]790 (let [control (JointControl. joint (ref nil))]791 (.addControl object control))792 object)795 (defn hinge-world796 []797 (let [sphere1 (sphere)798 sphere2 (sphere 1 :position (Vector3f. 3 3 3))799 joint (Point2PointJoint.800 (.getControl sphere1 RigidBodyControl)801 (.getControl sphere2 RigidBodyControl)802 Vector3f/ZERO (Vector3f. 3 3 3))]803 (add-joint sphere1 joint)804 (doto (Node. "hinge-world")805 (.attachChild sphere1)806 (.attachChild sphere2))))809 (defn test-joint []810 (view (hinge-world)))812 ;; (defn copier-gen []813 ;; (let [count (atom 0)]814 ;; (fn [in]815 ;; (swap! count inc)816 ;; (clojure.contrib.duck-streams/copy817 ;; in (File. (str "/home/r/tmp/mao-test/clojure-images/"818 ;; ;;/home/r/tmp/mao-test/clojure-images819 ;; (format "%08d.png" @count)))))))820 ;; (defn decrease-framerate []821 ;; (map822 ;; (copier-gen)823 ;; (sort824 ;; (map first825 ;; (partition826 ;; 4827 ;; (filter #(re-matches #".*.png$" (.getCanonicalPath %))828 ;; (file-seq829 ;; (file-str830 ;; "/home/r/media/anime/mao-temp/images"))))))))834 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;836 (defn proprioception837 "Create a proprioception map that reports the rotations of the838 various limbs of the creature's body"839 [creature]840 [#^Node creature]841 (let [842 nodes (node-seq creature)843 joints844 (map845 :joint846 (filter847 #(isa? (class %) JointControl)848 (reduce849 concat850 (map (fn [node]851 (map (fn [num] (.getControl node num))852 (range (.getNumControls node))))853 nodes))))]854 (fn []855 (reduce concat (map relative-positions (list (first joints)))))))858 (defn skel [node]859 (doto860 (.getSkeleton861 (.getControl node SkeletonControl))862 ;; this is necessary to force the skeleton to have accurate world863 ;; transforms before it is rendered to the screen.864 (.resetAndUpdate)))866 (defn green-x-ray []867 (doto (Material. (asset-manager)868 "Common/MatDefs/Misc/Unshaded.j3md")869 (.setColor "Color" ColorRGBA/Green)870 (-> (.getAdditionalRenderState)871 (.setDepthTest false))))873 (defn test-worm []874 (.start875 (world876 (doto (Node.)877 ;;(.attachChild (point-worm))878 (.attachChild (load-blender-model879 "Models/anim2/joint-worm.blend"))881 (.attachChild (box 10 1 10882 :position (Vector3f. 0 -2 0) :mass 0883 :color (ColorRGBA/Gray))))884 {885 "key-space" (fire-cannon-ball)886 }887 (fn [world]888 (enable-debug world)889 (light-up-everything world)890 ;;(.setTimer world (NanoTimer.))891 )892 no-op)))896 ;; defunct movement stuff897 (defn torque-controls [control]898 (let [torques899 (concat900 (map #(Vector3f. 0 (Math/sin %) (Math/cos %))901 (range 0 (* Math/PI 2) (/ (* Math/PI 2) 20)))902 [Vector3f/UNIT_X])]903 (map (fn [torque-axis]904 (fn [torque]905 (.applyTorque906 control907 (.mult (.mult (.getPhysicsRotation control)908 torque-axis)909 (float910 (* (.getMass control) torque))))))911 torques)))913 (defn motor-map914 "Take a creature and generate a function that will enable fine915 grained control over all the creature's limbs."916 [#^Node creature]917 (let [controls (keep #(.getControl % RigidBodyControl)918 (node-seq creature))919 limb-controls (reduce concat (map torque-controls controls))920 body-control (partial map #(%1 %2) limb-controls)]921 body-control))923 (defn test-motor-map924 "see how torque works."925 []926 (let [finger (box 3 0.5 0.5 :position (Vector3f. 0 2 0)927 :mass 1 :color ColorRGBA/Green)928 motor-map (motor-map finger)]929 (world930 (nodify [finger931 (box 10 0.5 10 :position (Vector3f. 0 -5 0) :mass 0932 :color ColorRGBA/Gray)])933 standard-debug-controls934 (fn [world]935 (set-gravity world Vector3f/ZERO)936 (light-up-everything world)937 (.setTimer world (NanoTimer.)))938 (fn [_ _]939 (dorun (motor-map [0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0]))))))940 #+end_src948 * COMMENT generate Source949 #+begin_src clojure :tangle ../src/cortex/body.clj950 <<proprioception>>951 <<motor-control>>952 #+end_src954 #+begin_src clojure :tangle ../src/cortex/test/body.clj955 <<test-body>>956 #+end_src