changeset 60:e5e627f50a3a

finally got euler angle stuff working
author Robert McIntyre <rlm@mit.edu>
date Mon, 28 Nov 2011 02:54:48 -0700
parents 63951929fe44
children 7b44348af538
files assets/Models/property/test.blend org/body.org org/util.org
diffstat 3 files changed, 429 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
     1.1 Binary file assets/Models/property/test.blend has changed
     2.1 --- a/org/body.org	Sat Nov 19 23:59:12 2011 -0700
     2.2 +++ b/org/body.org	Mon Nov 28 02:54:48 2011 -0700
     2.3 @@ -143,6 +143,20 @@
     2.4      node))
     2.5  
     2.6    
     2.7 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
     2.8 +
     2.9 +;; this could be a good way to give objects special properties like
    2.10 +;; being eyes and the like
    2.11 +
    2.12 +(.getUserData 
    2.13 + (.getChild
    2.14 +  (load-blender-model "Models/property/test.blend") 0)
    2.15 + "properties")
    2.16 +
    2.17 +;; the properties are saved along with the blender file.
    2.18 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    2.19 +
    2.20 +
    2.21  
    2.22  (defn init-debug-skel-node
    2.23    [f debug-node skeleton]
    2.24 @@ -312,32 +326,27 @@
    2.25    
    2.26  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    2.27  
    2.28 +;;;;;;;;;;;;  eve-style bodies  ;;;;;;;;
    2.29  
    2.30  
    2.31 -
    2.32 -
    2.33 -
    2.34 -;;;;;;;;;;;;  eve-style bodies  ;;;;;;;;
    2.35 -(defn joint-control
    2.36 -  [joint]
    2.37 -  (let [physics-space (ref nil)]
    2.38 -    (reify PhysicsControl
    2.39 -      (setPhysicsSpace [this space]
    2.40 -        (dosync
    2.41 -         (ref-set physics-space space))
    2.42 -        (.addJoint space joint))
    2.43 -      (update [this tpf])
    2.44 -      (setSpatial [this spatial])
    2.45 -      (render [this rm vp])
    2.46 -      (getPhysicsSpace [this] (deref physics-space))
    2.47 -      (isEnabled [this] true)
    2.48 -      (setEnabled [this state]))))
    2.49 -
    2.50 +(defrecord JointControl [joint physics-space]
    2.51 +  PhysicsControl
    2.52 +  (setPhysicsSpace [this space]
    2.53 +    (dosync
    2.54 +     (ref-set (:physics-space this) space))
    2.55 +    (.addJoint space (:joint this)))
    2.56 +  (update [this tpf])
    2.57 +  (setSpatial [this spatial])
    2.58 +  (render [this rm vp])
    2.59 +  (getPhysicsSpace [this] (deref (:physics-space this)))
    2.60 +  (isEnabled [this] true)
    2.61 +  (setEnabled [this state]))
    2.62 +  
    2.63  (defn add-joint
    2.64    "Add a joint to a particular object. When the object is added to the
    2.65    PhysicsSpace of a simulation, the joint will also be added"
    2.66    [object joint]
    2.67 -  (let [control (joint-control joint)]
    2.68 +  (let [control (JointControl. joint (ref nil))]
    2.69      (.addControl object control))
    2.70    object)
    2.71  
    2.72 @@ -371,7 +380,7 @@
    2.73  
    2.74  (defn nodify
    2.75    "take a sequence of things that can be attached to a node and return
    2.76 -  a node with all of the attached"
    2.77 +  a node with all of them attached"
    2.78    ([name children]
    2.79       (let [node (Node. name)]
    2.80         (dorun (map #(.attachChild node %) children))
    2.81 @@ -427,19 +436,408 @@
    2.82  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    2.83  
    2.84  
    2.85 +;;;;;;;;;  Mortor Control  ;;;;;;;;;;;;;
    2.86  
    2.87  
    2.88 +;; surprisingly ehough, terristerial creatures only move by using
    2.89 +;; torque applied to their joints.  There's not a single straight line
    2.90 +;; of force in the human body at all!  (a straight line of force would
    2.91 +;; correspond to some sort of jet or rocket propulseion)
    2.92  
    2.93 +(defn node-seq
    2.94 +  "take a node and return a seq of all its children
    2.95 +   recursively. There will be no nodes left in the resulting
    2.96 +   structure"
    2.97 +  [#^Node node]
    2.98 +  (tree-seq #(isa? (class %) Node) #(.getChildren %) node))
    2.99 +  
   2.100 +  
   2.101 +(defn torque-controls [control]
   2.102 +  (let [torques
   2.103 +        (concat
   2.104 +         (map #(Vector3f. 0 (Math/sin %) (Math/cos %))
   2.105 +              (range 0 (* Math/PI 2) (/ (* Math/PI 2) 20)))
   2.106 +         [Vector3f/UNIT_X])]
   2.107 +    (map (fn [torque-axis]
   2.108 +           (fn [torque]
   2.109 +             (.applyTorque
   2.110 +              control
   2.111 +              (.mult (.mult (.getPhysicsRotation control)
   2.112 +                            torque-axis)
   2.113 +                     (float
   2.114 +                      (* (.getMass control) torque))))))
   2.115 +         torques)))
   2.116  
   2.117 +(defn motor-map
   2.118 +  "Take a creature and generate a function that will enable fine
   2.119 +   grained control over all the creature's limbs."  
   2.120 +  [#^Node creature]
   2.121 +  (let [controls (keep #(.getControl % RigidBodyControl)
   2.122 +                       (node-seq creature))
   2.123 +        limb-controls (reduce concat (map torque-controls controls))
   2.124 +        body-control  (partial map #(%1 %2) limb-controls)]
   2.125 +    body-control))
   2.126  
   2.127  
   2.128  
   2.129 +(defn test-motor-map
   2.130 +  "see how torque works."
   2.131 +  []
   2.132 +  (let [finger (box 3 0.5 0.5 :position (Vector3f. 0 2 0)
   2.133 +                    :mass 1 :color ColorRGBA/Green)
   2.134 +        motor-map (motor-map finger)]
   2.135 +    (world
   2.136 +     (nodify [finger
   2.137 +              (box 10 0.5 10 :position (Vector3f. 0 -5 0) :mass 0
   2.138 +                   :color ColorRGBA/Gray)])
   2.139 +     standard-debug-controls
   2.140 +     (fn [world]
   2.141 +       (set-gravity world Vector3f/ZERO)
   2.142 +       (light-up-everything world)
   2.143 +       (.setTimer world (NanoTimer.)))
   2.144 +     (fn [_ _]
   2.145 +       (dorun (motor-map [0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0]))))))
   2.146 +
   2.147 +
   2.148 +
   2.149 +(defn test-torque
   2.150 +  "see how torque works."
   2.151 +  []
   2.152 +  (let [finger (box 3 0.5 0.5 :position (Vector3f. 0 2 0)
   2.153 +                    :mass 1 :color ColorRGBA/Green)
   2.154 +        move-left? (atom false)
   2.155 +        move-right? (atom false)
   2.156 +        control (.getControl finger RigidBodyControl)]
   2.157 +    (world
   2.158 +     (nodify [finger
   2.159 +              (box 10 0.5 10 :position (Vector3f. 0 -5 0) :mass 0
   2.160 +                   :color ColorRGBA/Gray)])
   2.161 +     (merge standard-debug-controls
   2.162 +            {"key-k" (fn [_ pressed?] (reset! move-left? pressed?))
   2.163 +             "key-l" (fn [_ pressed?] (reset! move-right? pressed?))})
   2.164 +     (fn [world]
   2.165 +       (set-gravity world Vector3f/ZERO)
   2.166 +       (light-up-everything world)
   2.167 +       (.setTimer world (NanoTimer.)))
   2.168 +     (fn [_ _]
   2.169 +       (if @move-left?
   2.170 +         (.applyTorque control
   2.171 +                       (.mult (.getPhysicsRotation control)
   2.172 +                       (Vector3f. -3 20 0))))
   2.173 +       (if @move-right?
   2.174 +         (.applyTorque control (Vector3f. 0 0 1)))))))
   2.175 +
   2.176 +
   2.177 +(defn worm-pattern [time]
   2.178 +  [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
   2.179 +
   2.180 +   0 0 0 0 0 0 0 0 0 0 0
   2.181 +
   2.182 +   (* 20 (Math/sin (* Math/PI 2 (/ (rem time 300 ) 300))))
   2.183 +
   2.184 +   0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
   2.185 +  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
   2.186 +  0 0 0 0 0 0 0 0 0 0 0 0 0 0
   2.187 +
   2.188 +   ])
   2.189 +
   2.190 +
   2.191 +;; (defn copier-gen []
   2.192 +;;   (let [count (atom 0)]
   2.193 +;;     (fn [in]
   2.194 +;;       (swap! count inc)
   2.195 +;;       (clojure.contrib.duck-streams/copy
   2.196 +;;        in (File. (str "/home/r/tmp/mao-test/clojure-images/"
   2.197 +;;                      ;;/home/r/tmp/mao-test/clojure-images
   2.198 +;;                (format "%08d.png" @count)))))))
   2.199 +;; (defn decrease-framerate []
   2.200 +;;   (map
   2.201 +;;    (copier-gen)
   2.202 +;;    (sort
   2.203 +;;     (map first
   2.204 +;;          (partition
   2.205 +;;           4
   2.206 +;;           (filter #(re-matches #".*.png$" (.getCanonicalPath %))
   2.207 +;;                   (file-seq
   2.208 +;;                    (file-str
   2.209 +;;                     "/home/r/media/anime/mao-temp/images"))))))))
   2.210 +
   2.211 +
   2.212 +
   2.213 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   2.214 +
   2.215 +
   2.216 +
   2.217 +
   2.218 +;;;;;;;;;;;;;;;;;;  Proprioception  ;;;;;;;;;;;;;;;;;;;;;;;;
   2.219 +
   2.220 +
   2.221 +;; this is not used as just getting the rotation would be simpler.
   2.222 +(defn proprioception-senses 
   2.223 +  "given a control , create a sequence of thunks that will report the
   2.224 +  rotation of the control's object along the same axes as the motor-control map."
   2.225 +  [control]
   2.226 +  (let [torques
   2.227 +        (concat
   2.228 +         (map #(Vector3f. 0 (Math/sin %) (Math/cos %))
   2.229 +              (range 0 (* Math/PI 2) (/ (* Math/PI 2) 20)))
   2.230 +         [Vector3f/UNIT_X])]
   2.231 +    (map (fn [torque-axis]
   2.232 +           (fn []
   2.233 +             (.getPhysicsRotation control)))
   2.234 +           torques)))
   2.235 +
   2.236 +(defn orthogonal-vect
   2.237 +  "Return a vector orthogonal to the current one"
   2.238 +  [vector]
   2.239 +  (let [x (.getX vector)
   2.240 +        y (.getY vector)
   2.241 +        z (.getZ vector)]
   2.242 +    (cond
   2.243 +     (not= x (float 0)) (Vector3f. (- z) 0 x)
   2.244 +     (not= y (float 0)) (Vector3f. 0 (- z) y)
   2.245 +     (not= z (float 0)) (Vector3f. 0 (- z) y)
   2.246 +     true Vector3f/ZERO)))
   2.247 +
   2.248 +;; from
   2.249 +;; http://stackoverflow.com/questions/3684269/ \\
   2.250 +;;   component-of-a-quaternion-rotation-around-an-axis
   2.251 +(defn rot-about-axis [#^Quaternion q #^Vector3f axis]
   2.252 +  (let [basis-1 (orthogonal-vect axis)
   2.253 +        basis-2 (.cross axis basis-1)
   2.254 +        rotated (.mult q basis-1)
   2.255 +        alpha (.dot basis-1 (.project rotated basis-1))
   2.256 +        beta  (.dot basis-2 (.project rotated basis-2))]
   2.257 +    (println-repl alpha)
   2.258 +    (println-repl beta)
   2.259 +    (Math/atan2 beta alpha)))
   2.260 +
   2.261 +
   2.262 +(defn check-rot [a]
   2.263 +  (rot-about-axis
   2.264 +   (doto (Quaternion.)
   2.265 +     (.fromAngleAxis
   2.266 +      (float a)
   2.267 +      (Vector3f. 1 0 0))) (Vector3f. 1 0 0)))
   2.268 +
   2.269 +(defn relative-positions [joint]
   2.270 +  (let [object-a (.getUserObject (.getBodyA joint))
   2.271 +        object-b (.getUserObject (.getBodyB joint))
   2.272 +        arm-a
   2.273 +        (.normalize
   2.274 +         (.subtract 
   2.275 +          (.localToWorld object-a (.getPivotA joint) nil)
   2.276 +          (.getWorldTranslation object-a)))
   2.277 +        rotate-a
   2.278 +         (doto (Matrix3f.)
   2.279 +           (.fromStartEndVectors arm-a Vector3f/UNIT_X))
   2.280 +        arm-b
   2.281 +        (.mult
   2.282 +         rotate-a 
   2.283 +         (.normalize
   2.284 +          (.subtract 
   2.285 +           (.localToWorld object-b (.getPivotB joint) nil)
   2.286 +           (.getWorldTranslation object-b))))
   2.287 +        rotate-b
   2.288 +        (doto (Matrix3f.)
   2.289 +          (.fromStartEndVectors arm-b Vector3f/UNIT_X))
   2.290 +        
   2.291 +        pitch
   2.292 +        (.angleBetween
   2.293 +         (.normalize (Vector2f. (.getX arm-b) (.getY arm-b)))
   2.294 +         (Vector2f. 1 0))
   2.295 +        yaw
   2.296 +        (.angleBetween
   2.297 +         (.normalize (Vector2f. (.getX arm-b) (.getZ arm-b)))
   2.298 +         (Vector2f. 1 0))
   2.299 +                     
   2.300 +        roll
   2.301 +        (.mult 
   2.302 +         (.getLocalRotation object-b)
   2.303 +         (doto (Quaternion.)
   2.304 +           (.fromRotationMatrix rotate-a)))
   2.305 +         ]
   2.306 +         
   2.307 +                
   2.308 +
   2.309 +    ;;(println-repl
   2.310 +    ;; "arm-b is " arm-b)
   2.311 +    ;;(println-repl
   2.312 +    ;; "pivot-b is " (.getPivotB joint))
   2.313 +    ;;(println-repl
   2.314 +    ;; (format "pitch: %1.2f\nyaw: %1.2f\nroll: %1.2f\n"
   2.315 +    ;;         pitch yaw roll))
   2.316 +    [pitch yaw roll]))
   2.317 +
   2.318 +        
   2.319 +    
   2.320 +        
   2.321 +  
   2.322 +(defn proprioception
   2.323 +  "Create a proprioception map that reports the rotations of the
   2.324 +  various limbs of the creature's body"
   2.325 +  [creature]
   2.326 +  [#^Node creature]
   2.327 +  (let [
   2.328 +        nodes (node-seq creature)
   2.329 +        joints
   2.330 +        (map
   2.331 +         :joint 
   2.332 +         (filter
   2.333 +          #(isa? (class %) JointControl)
   2.334 +          (reduce
   2.335 +           concat
   2.336 +           (map (fn [node]
   2.337 +                  (map (fn [num] (.getControl node num))
   2.338 +                       (range (.getNumControls node))))
   2.339 +                nodes))))]
   2.340 +    (fn []
   2.341 +      (reduce concat (map relative-positions (list (first joints)))))))
   2.342 +        
   2.343 +
   2.344 +(defn test-worm-control
   2.345 +  []
   2.346 +  (let [worm (point-worm)
   2.347 +        time (atom 0)
   2.348 +        worm-motor-map (motor-map worm)
   2.349 +        body-map (proprioception worm)
   2.350 +        debug-segments
   2.351 +        (map
   2.352 +         #(doto
   2.353 +              (make-shape
   2.354 +               (assoc base-shape
   2.355 +                 :name "debug-line"
   2.356 +                 :physical? false
   2.357 +                 :shape
   2.358 +                 (com.jme3.scene.shape.Line.
   2.359 +                  (.add (.getWorldTranslation %)
   2.360 +                        (Vector3f. -0.2 0 0 ))
   2.361 +                  (.add (.getWorldTranslation %)
   2.362 +                        (Vector3f. 0.2 0 0)))))
   2.363 +                 (.setMaterial (green-x-ray)))
   2.364 +            (drop 1 (node-seq worm)))]
   2.365 +    (world
   2.366 +     (nodify [worm
   2.367 +              (box 10 0.5 10 :position (Vector3f. 0 -5 0) :mass 0
   2.368 +                   :color ColorRGBA/Gray)])
   2.369 +     standard-debug-controls
   2.370 +     (fn [world]
   2.371 +       (.attachChild (.getRootNode world) (nodify debug-segments))
   2.372 +       (enable-debug world)
   2.373 +       (light-up-everything world)
   2.374 +       (com.aurellem.capture.Capture/captureVideo
   2.375 +        world
   2.376 +        (file-str "/home/r/proj/cortex/tmp/moving-worm")))
   2.377 +     
   2.378 +     (fn [_ _]
   2.379 +       (dorun
   2.380 +        (map
   2.381 +         (fn [worm-segment
   2.382 +              debug-segment]
   2.383 +           (.rotate
   2.384 +            debug-segment
   2.385 +            (Quaternion. (float 0) (float 0.05) (float 0) (float 1))))
   2.386 +         (drop 1 (node-seq worm))
   2.387 +         debug-segments))
   2.388 +       (swap! time inc)
   2.389 +       (println-repl (with-out-str (clojure.pprint/pprint (doall (body-map)))))
   2.390 +       (Thread/sleep 200)
   2.391 +       (dorun (worm-motor-map
   2.392 +               (worm-pattern @time)))))))
   2.393 +
   2.394 +
   2.395 +
   2.396 +
   2.397 +
   2.398 +(defn test-prop
   2.399 +  "see how torque works."
   2.400 +  []
   2.401 +  (let [hand    (box 1 0.2 0.2 :position (Vector3f. 0 2 0)
   2.402 +                     :mass 0 :color ColorRGBA/Green)
   2.403 +        finger (box 1 0.2 0.2 :position (Vector3f. 2.4 2 0)
   2.404 +                     :mass 1 :color (ColorRGBA. 0.20 0.40 0.99 1.0))
   2.405 +        floor   (box 10 0.5 10 :position (Vector3f. 0 -5 0)
   2.406 +                     :mass 0 :color ColorRGBA/Gray)
   2.407 +
   2.408 +        move-up? (atom false)
   2.409 +        move-down? (atom false)
   2.410 +        move-left? (atom false)
   2.411 +        move-right? (atom false)
   2.412 +        roll-left? (atom false)
   2.413 +        roll-right? (atom false)
   2.414 +        control (.getControl finger RigidBodyControl)
   2.415 +        joint
   2.416 +        (doto 
   2.417 +            (Point2PointJoint.
   2.418 +             (.getControl hand RigidBodyControl)
   2.419 +             control
   2.420 +             (Vector3f. 1.2 0 0)
   2.421 +             (Vector3f. -1.2 0 0 ))
   2.422 +          (.setCollisionBetweenLinkedBodys false))
   2.423 +        time (atom 0)
   2.424 +        ]
   2.425 +    (world
   2.426 +     (nodify [hand finger floor])
   2.427 +     (merge standard-debug-controls
   2.428 +            {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
   2.429 +             "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
   2.430 +             "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
   2.431 +             "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
   2.432 +             "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
   2.433 +             "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})     
   2.434 +     (fn [world]
   2.435 +       (set-gravity world Vector3f/ZERO)
   2.436 +       (.setMoveSpeed (.getFlyByCamera world) 50)
   2.437 +       (.setRotationSpeed (.getFlyByCamera world) 50)
   2.438 +       (light-up-everything world)
   2.439 +       (.setTimer world (NanoTimer.))
   2.440 +       )
   2.441 +     (fn [_ _]
   2.442 +       (if @move-up?
   2.443 +         (.applyTorque control
   2.444 +                       (.mult (.getPhysicsRotation control)
   2.445 +                       (Vector3f. 0 0 1))))
   2.446 +       (if @move-down?
   2.447 +         (.applyTorque control
   2.448 +                       (.mult (.getPhysicsRotation control)
   2.449 +                              (Vector3f. 0 0 -1))))
   2.450 +       (if @move-left?
   2.451 +         (.applyTorque control
   2.452 +                       (.mult (.getPhysicsRotation control)
   2.453 +                              (Vector3f. 0 1 0))))
   2.454 +       (if @move-right?
   2.455 +         (.applyTorque control
   2.456 +                       (.mult (.getPhysicsRotation control)
   2.457 +                              (Vector3f. 0 -1 0))))
   2.458 +       (if @roll-left?
   2.459 +         (.applyTorque control
   2.460 +                       (.mult (.getPhysicsRotation control)
   2.461 +                              (Vector3f. -0.1 0 0))))
   2.462 +       (if @roll-right?
   2.463 +         (.applyTorque control
   2.464 +                       (.mult (.getPhysicsRotation control)
   2.465 +                              (Vector3f. 0.1 0 0))))
   2.466 +
   2.467 +       (if (= 0 (rem (swap! time inc) 2000))
   2.468 +         (do 
   2.469 +           ;;(println-repl (.getLocalRotation finger))
   2.470 +           (println-repl (nth (relative-positions joint) 2))))
   2.471 +
   2.472 +       ))))
   2.473 +
   2.474 +
   2.475 +
   2.476 +
   2.477 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   2.478  
   2.479  
   2.480  
   2.481  
   2.482  #+end_src
   2.483  
   2.484 +#+results: body-main
   2.485 +: #'cortex.body/test-prop
   2.486 +
   2.487  
   2.488  
   2.489  
   2.490 @@ -452,3 +850,4 @@
   2.491  <<body-main>>
   2.492  #+end_src
   2.493    
   2.494 +  
     3.1 --- a/org/util.org	Sat Nov 19 23:59:12 2011 -0700
     3.2 +++ b/org/util.org	Mon Nov 28 02:54:48 2011 -0700
     3.3 @@ -280,6 +280,8 @@
     3.4  *** Debug Actions
     3.5  #+srcname: debug-actions
     3.6  #+begin_src clojure :results silent
     3.7 +(in-ns 'cortex.util)
     3.8 +
     3.9  (defn basic-light-setup
    3.10    "returns a sequence of lights appropiate for fully lighting a scene"
    3.11    []
    3.12 @@ -333,6 +335,13 @@
    3.13             (add-element game cannon-ball (if node node (.getRootNode game)))))))
    3.14    ([]
    3.15      (fire-cannon-ball false)))
    3.16 +
    3.17 +(def standard-debug-controls 
    3.18 +  {"key-space" (fire-cannon-ball)})
    3.19 +
    3.20 +   
    3.21 +
    3.22 +
    3.23  #+end_src
    3.24  
    3.25