changeset 160:33278bf028e7

refactored joints
author Robert McIntyre <rlm@mit.edu>
date Fri, 03 Feb 2012 06:47:05 -0700
parents 75b6c2ebbf8e
children e401dafa5966
files org/body.org org/test-creature.org org/util.org
diffstat 3 files changed, 224 insertions(+), 215 deletions(-) [+]
line wrap: on
line diff
     1.1 --- a/org/body.org	Fri Feb 03 06:41:16 2012 -0700
     1.2 +++ b/org/body.org	Fri Feb 03 06:47:05 2012 -0700
     1.3 @@ -9,7 +9,7 @@
     1.4  #+name: proprioception
     1.5  #+begin_src clojure 
     1.6  (ns cortex.body
     1.7 -  (:use (cortex world util))
     1.8 +  (:use (cortex world util sense))
     1.9    (:import
    1.10     com.jme3.math.Vector3f
    1.11     com.jme3.math.Quaternion
    1.12 @@ -20,6 +20,8 @@
    1.13     com.jme3.bounding.BoundingBox
    1.14     com.jme3.scene.Node))
    1.15  
    1.16 +(cortex.import/mega-import-jme3)
    1.17 +
    1.18  (defn jme-to-blender
    1.19    "Convert from JME coordinates to Blender coordinates"
    1.20    [#^Vector3f in]
    1.21 @@ -27,6 +29,14 @@
    1.22               (- (.getZ in))
    1.23               (.getY in)))
    1.24  
    1.25 +(defn blender-to-jme
    1.26 +  "Convert from Blender coordinates to JME coordinates"
    1.27 +  [#^Vector3f in]
    1.28 +  (Vector3f. (.getX in)
    1.29 +             (.getZ in)
    1.30 +             (- (.getY in))))
    1.31 +
    1.32 +
    1.33  (defn joint-targets
    1.34    "Return the two closest two objects to the joint object, ordered
    1.35    from bottom to top according to the joint's rotation."
    1.36 @@ -62,61 +72,160 @@
    1.37      (seq (.getChildren joint-node))
    1.38      (do (println-repl "could not find JOINTS node") [])))
    1.39  
    1.40 -(defn tap [obj direction force]
    1.41 -  (let [control (.getControl obj RigidBodyControl)]
    1.42 -    (.applyTorque
    1.43 -     control
    1.44 -     (.mult (.getPhysicsRotation control)
    1.45 -            (.mult (.normalize direction) (float force))))))
    1.46 +(defmulti joint-dispatch
    1.47 +  "Translate blender pseudo-joints into real JME joints."
    1.48 +  (fn [constraints & _] 
    1.49 +    (:type constraints)))
    1.50  
    1.51 +(defmethod joint-dispatch :point
    1.52 +  [constraints control-a control-b pivot-a pivot-b rotation]
    1.53 +  (println-repl "creating POINT2POINT joint")
    1.54 +  ;; bullet's point2point joints are BROKEN, so we must use the
    1.55 +  ;; generic 6DOF joint instead of an actual Point2Point joint!
    1.56  
    1.57 -(defn with-movement
    1.58 -  [object
    1.59 -   [up down left right roll-up roll-down :as keyboard]
    1.60 -   forces
    1.61 -   [root-node
    1.62 -    keymap
    1.63 -    intilization
    1.64 -    world-loop]]
    1.65 -  (let [add-keypress
    1.66 -        (fn [state keymap key]
    1.67 -          (merge keymap
    1.68 -                  {key
    1.69 -                   (fn [_ pressed?]
    1.70 -                     (reset! state pressed?))}))
    1.71 -        move-up? (atom false)
    1.72 -        move-down? (atom false)
    1.73 -        move-left? (atom false)
    1.74 -        move-right? (atom false)
    1.75 -        roll-left? (atom false)
    1.76 -        roll-right? (atom false)
    1.77 -        
    1.78 -        directions [(Vector3f. 0 1 0)(Vector3f. 0 -1 0)
    1.79 -                    (Vector3f. 0 0 1)(Vector3f. 0 0 -1)
    1.80 -                    (Vector3f. -1 0 0)(Vector3f. 1 0 0)]
    1.81 -        atoms [move-left? move-right? move-up? move-down? 
    1.82 -                 roll-left? roll-right?]
    1.83 +  ;; should be able to do this:
    1.84 +  (comment 
    1.85 +    (Point2PointJoint.
    1.86 +     control-a
    1.87 +     control-b
    1.88 +     pivot-a
    1.89 +     pivot-b))
    1.90  
    1.91 -        keymap* (reduce merge
    1.92 -                        (map #(add-keypress %1 keymap %2)
    1.93 -                             atoms
    1.94 -                             keyboard))
    1.95 -        
    1.96 -        splice-loop (fn []
    1.97 -                      (dorun
    1.98 -                       (map
    1.99 -                        (fn [sym direction force]
   1.100 -                          (if @sym
   1.101 -                            (tap object direction force)))
   1.102 -                        atoms directions forces)))
   1.103 +  ;; but instead we must do this:
   1.104 +  (println-repl "substuting 6DOF joint for POINT2POINT joint!")
   1.105 +  (doto
   1.106 +      (SixDofJoint.
   1.107 +       control-a
   1.108 +       control-b
   1.109 +       pivot-a
   1.110 +       pivot-b
   1.111 +       false)
   1.112 +    (.setLinearLowerLimit Vector3f/ZERO)
   1.113 +    (.setLinearUpperLimit Vector3f/ZERO)
   1.114 +    ;;(.setAngularLowerLimit (Vector3f. 1 1 1))
   1.115 +    ;;(.setAngularUpperLimit (Vector3f. 0 0 0))
   1.116  
   1.117 -        world-loop* (fn [world tpf]
   1.118 -                       (world-loop world tpf)
   1.119 -                       (splice-loop))]
   1.120 -    [root-node
   1.121 -     keymap*
   1.122 -     intilization
   1.123 -     world-loop*]))
   1.124 +))
   1.125 +
   1.126 +
   1.127 +(defmethod joint-dispatch :hinge
   1.128 +  [constraints control-a control-b pivot-a pivot-b rotation]
   1.129 +  (println-repl "creating HINGE joint")
   1.130 +  (let [axis
   1.131 +        (if-let
   1.132 +            [axis (:axis constraints)]
   1.133 +          axis
   1.134 +          Vector3f/UNIT_X)
   1.135 +        [limit-1 limit-2] (:limit constraints)
   1.136 +        hinge-axis
   1.137 +        (.mult
   1.138 +         rotation
   1.139 +         (blender-to-jme axis))]
   1.140 +    (doto
   1.141 +        (HingeJoint.
   1.142 +         control-a
   1.143 +         control-b
   1.144 +         pivot-a
   1.145 +         pivot-b
   1.146 +         hinge-axis
   1.147 +         hinge-axis)
   1.148 +      (.setLimit limit-1 limit-2))))
   1.149 +
   1.150 +(defmethod joint-dispatch :cone
   1.151 +  [constraints control-a control-b pivot-a pivot-b rotation]
   1.152 +  (let [limit-xz (:limit-xz constraints)
   1.153 +        limit-xy (:limit-xy constraints)
   1.154 +        twist    (:twist constraints)]
   1.155 +    
   1.156 +    (println-repl "creating CONE joint")
   1.157 +    (println-repl rotation)
   1.158 +    (println-repl
   1.159 +     "UNIT_X --> " (.mult rotation (Vector3f. 1 0 0)))
   1.160 +    (println-repl
   1.161 +     "UNIT_Y --> " (.mult rotation (Vector3f. 0 1 0)))
   1.162 +    (println-repl
   1.163 +     "UNIT_Z --> " (.mult rotation (Vector3f. 0 0 1)))
   1.164 +    (doto
   1.165 +        (ConeJoint.
   1.166 +         control-a
   1.167 +         control-b
   1.168 +         pivot-a
   1.169 +         pivot-b
   1.170 +         rotation
   1.171 +         rotation)
   1.172 +      (.setLimit (float limit-xz)
   1.173 +                 (float limit-xy)
   1.174 +                 (float twist)))))
   1.175 +
   1.176 +(defn connect
   1.177 +  "here are some examples:
   1.178 +   {:type :point}
   1.179 +   {:type :hinge  :limit [0 (/ Math/PI 2)] :axis (Vector3f. 0 1 0)}
   1.180 +   (:axis defaults to (Vector3f. 1 0 0) if not provided for hinge joints)
   1.181 +
   1.182 +   {:type :cone :limit-xz 0]
   1.183 +                :limit-xy 0]
   1.184 +                :twist 0]}   (use XZY rotation mode in blender!)"
   1.185 +  [#^Node obj-a #^Node obj-b #^Node joint]
   1.186 +  (let [control-a (.getControl obj-a RigidBodyControl)
   1.187 +        control-b (.getControl obj-b RigidBodyControl)
   1.188 +        joint-center (.getWorldTranslation joint)
   1.189 +        joint-rotation (.toRotationMatrix (.getWorldRotation joint))
   1.190 +        pivot-a (world-to-local obj-a joint-center)
   1.191 +        pivot-b (world-to-local obj-b joint-center)]
   1.192 +   
   1.193 +    (if-let [constraints
   1.194 +             (map-vals
   1.195 +              eval
   1.196 +              (read-string
   1.197 +               (meta-data joint "joint")))]
   1.198 +      ;; A side-effect of creating a joint registers
   1.199 +      ;; it with both physics objects which in turn
   1.200 +      ;; will register the joint with the physics system
   1.201 +      ;; when the simulation is started.
   1.202 +      (do
   1.203 +        (println-repl "creating joint between"
   1.204 +                      (.getName obj-a) "and" (.getName obj-b))
   1.205 +        (joint-dispatch constraints
   1.206 +                        control-a control-b
   1.207 +                        pivot-a pivot-b
   1.208 +                        joint-rotation))
   1.209 +      (println-repl "could not find joint meta-data!"))))
   1.210 +
   1.211 +
   1.212 +
   1.213 +
   1.214 +(defn assemble-creature [#^Node pieces joints]
   1.215 +  (dorun
   1.216 +   (map
   1.217 +    (fn [geom]
   1.218 +      (let [physics-control
   1.219 +            (RigidBodyControl.
   1.220 +             (HullCollisionShape.
   1.221 +              (.getMesh geom))
   1.222 +             (if-let [mass (meta-data geom "mass")]
   1.223 +               (do
   1.224 +                 (println-repl
   1.225 +                  "setting" (.getName geom) "mass to" (float mass))
   1.226 +                 (float mass))
   1.227 +               (float 1)))]
   1.228 +               
   1.229 +        (.addControl geom physics-control)))
   1.230 +    (filter #(isa? (class %) Geometry )
   1.231 +            (node-seq pieces))))
   1.232 +  (dorun
   1.233 +   (map
   1.234 +    (fn [joint]
   1.235 +      (let [[obj-a obj-b] (joint-targets pieces joint)]
   1.236 +        (connect obj-a obj-b joint)))
   1.237 +    joints))
   1.238 +  pieces)
   1.239 +
   1.240 +
   1.241 +;; TODO implement a function that adds joints in the style of the
   1.242 +;; other sense functions
   1.243 +
   1.244 +
   1.245  
   1.246  (import java.awt.image.BufferedImage)
   1.247  
     2.1 --- a/org/test-creature.org	Fri Feb 03 06:41:16 2012 -0700
     2.2 +++ b/org/test-creature.org	Fri Feb 03 06:47:05 2012 -0700
     2.3 @@ -71,164 +71,14 @@
     2.4       (.registerLoader BlenderModelLoader (into-array String ["blend"])))
     2.5     model))
     2.6  
     2.7 -(defn blender-to-jme
     2.8 -  "Convert from Blender coordinates to JME coordinates"
     2.9 -  [#^Vector3f in]
    2.10 -  (Vector3f. (.getX in)
    2.11 -             (.getZ in)
    2.12 -             (- (.getY in))))
    2.13 +(declare blender-creature)
    2.14  
    2.15 -
    2.16 -(defmulti joint-dispatch
    2.17 -  "Translate blender pseudo-joints into real JME joints."
    2.18 -  (fn [constraints & _] 
    2.19 -    (:type constraints)))
    2.20 -
    2.21 -(defmethod joint-dispatch :point
    2.22 -  [constraints control-a control-b pivot-a pivot-b rotation]
    2.23 -  (println-repl "creating POINT2POINT joint")
    2.24 -  ;; bullet's point2point joints are BROKEN, so we must use the
    2.25 -  ;; generic 6DOF joint instead of an actual Point2Point joint!
    2.26 -
    2.27 -  ;; should be able to do this:
    2.28 -  (comment 
    2.29 -    (Point2PointJoint.
    2.30 -     control-a
    2.31 -     control-b
    2.32 -     pivot-a
    2.33 -     pivot-b))
    2.34 -
    2.35 -  ;; but instead we must do this:
    2.36 -  (println-repl "substuting 6DOF joint for POINT2POINT joint!")
    2.37 -  (doto
    2.38 -      (SixDofJoint.
    2.39 -       control-a
    2.40 -       control-b
    2.41 -       pivot-a
    2.42 -       pivot-b
    2.43 -       false)
    2.44 -    (.setLinearLowerLimit Vector3f/ZERO)
    2.45 -    (.setLinearUpperLimit Vector3f/ZERO)
    2.46 -    ;;(.setAngularLowerLimit (Vector3f. 1 1 1))
    2.47 -    ;;(.setAngularUpperLimit (Vector3f. 0 0 0))
    2.48 -
    2.49 -))
    2.50 -
    2.51 -
    2.52 -(defmethod joint-dispatch :hinge
    2.53 -  [constraints control-a control-b pivot-a pivot-b rotation]
    2.54 -  (println-repl "creating HINGE joint")
    2.55 -  (let [axis
    2.56 -        (if-let
    2.57 -            [axis (:axis constraints)]
    2.58 -          axis
    2.59 -          Vector3f/UNIT_X)
    2.60 -        [limit-1 limit-2] (:limit constraints)
    2.61 -        hinge-axis
    2.62 -        (.mult
    2.63 -         rotation
    2.64 -         (blender-to-jme axis))]
    2.65 -    (doto
    2.66 -        (HingeJoint.
    2.67 -         control-a
    2.68 -         control-b
    2.69 -         pivot-a
    2.70 -         pivot-b
    2.71 -         hinge-axis
    2.72 -         hinge-axis)
    2.73 -      (.setLimit limit-1 limit-2))))
    2.74 -
    2.75 -(defmethod joint-dispatch :cone
    2.76 -  [constraints control-a control-b pivot-a pivot-b rotation]
    2.77 -  (let [limit-xz (:limit-xz constraints)
    2.78 -        limit-xy (:limit-xy constraints)
    2.79 -        twist    (:twist constraints)]
    2.80 -    
    2.81 -    (println-repl "creating CONE joint")
    2.82 -    (println-repl rotation)
    2.83 -    (println-repl
    2.84 -     "UNIT_X --> " (.mult rotation (Vector3f. 1 0 0)))
    2.85 -    (println-repl
    2.86 -     "UNIT_Y --> " (.mult rotation (Vector3f. 0 1 0)))
    2.87 -    (println-repl
    2.88 -     "UNIT_Z --> " (.mult rotation (Vector3f. 0 0 1)))
    2.89 -    (doto
    2.90 -        (ConeJoint.
    2.91 -         control-a
    2.92 -         control-b
    2.93 -         pivot-a
    2.94 -         pivot-b
    2.95 -         rotation
    2.96 -         rotation)
    2.97 -      (.setLimit (float limit-xz)
    2.98 -                 (float limit-xy)
    2.99 -                 (float twist)))))
   2.100 -
   2.101 -(defn connect
   2.102 -  "here are some examples:
   2.103 -   {:type :point}
   2.104 -   {:type :hinge  :limit [0 (/ Math/PI 2)] :axis (Vector3f. 0 1 0)}
   2.105 -   (:axis defaults to (Vector3f. 1 0 0) if not provided for hinge joints)
   2.106 -
   2.107 -   {:type :cone :limit-xz 0]
   2.108 -                :limit-xy 0]
   2.109 -                :twist 0]}   (use XZY rotation mode in blender!)"
   2.110 -  [#^Node obj-a #^Node obj-b #^Node joint]
   2.111 -  (let [control-a (.getControl obj-a RigidBodyControl)
   2.112 -        control-b (.getControl obj-b RigidBodyControl)
   2.113 -        joint-center (.getWorldTranslation joint)
   2.114 -        joint-rotation (.toRotationMatrix (.getWorldRotation joint))
   2.115 -        pivot-a (world-to-local obj-a joint-center)
   2.116 -        pivot-b (world-to-local obj-b joint-center)]
   2.117 -   
   2.118 -    (if-let [constraints
   2.119 -             (map-vals
   2.120 -              eval
   2.121 -              (read-string
   2.122 -               (meta-data joint "joint")))]
   2.123 -      ;; A side-effect of creating a joint registers
   2.124 -      ;; it with both physics objects which in turn
   2.125 -      ;; will register the joint with the physics system
   2.126 -      ;; when the simulation is started.
   2.127 -      (do
   2.128 -        (println-repl "creating joint between"
   2.129 -                      (.getName obj-a) "and" (.getName obj-b))
   2.130 -        (joint-dispatch constraints
   2.131 -                        control-a control-b
   2.132 -                        pivot-a pivot-b
   2.133 -                        joint-rotation))
   2.134 -      (println-repl "could not find joint meta-data!"))))
   2.135 -
   2.136 -
   2.137 -
   2.138 -
   2.139 -(defn assemble-creature [#^Node pieces joints]
   2.140 -  (dorun
   2.141 -   (map
   2.142 -    (fn [geom]
   2.143 -      (let [physics-control
   2.144 -            (RigidBodyControl.
   2.145 -             (HullCollisionShape.
   2.146 -              (.getMesh geom))
   2.147 -             (if-let [mass (meta-data geom "mass")]
   2.148 -               (do
   2.149 -                 (println-repl
   2.150 -                  "setting" (.getName geom) "mass to" (float mass))
   2.151 -                 (float mass))
   2.152 -               (float 1)))]
   2.153 -               
   2.154 -        (.addControl geom physics-control)))
   2.155 -    (filter #(isa? (class %) Geometry )
   2.156 -            (node-seq pieces))))
   2.157 -  (dorun
   2.158 -   (map
   2.159 -    (fn [joint]
   2.160 -      (let [[obj-a obj-b] (joint-targets pieces joint)]
   2.161 -        (connect obj-a obj-b joint)))
   2.162 -    joints))
   2.163 -  pieces)
   2.164 -
   2.165 -(declare blender-creature)
   2.166 +(defn blender-creature
   2.167 +  "Return a creature with all joints in place."
   2.168 +  [blender-path]
   2.169 +  (let [model (load-blender-model blender-path)
   2.170 +        joints (creature-joints model)]
   2.171 +    (assemble-creature model joints)))
   2.172  
   2.173  (def hand "Models/creature1/one.blend")
   2.174  
   2.175 @@ -271,12 +121,6 @@
   2.176  
   2.177  
   2.178  
   2.179 -(defn blender-creature
   2.180 -  "Return a creature with all joints in place."
   2.181 -  [blender-path]
   2.182 -  (let [model (load-blender-model blender-path)
   2.183 -        joints (creature-joints model)]
   2.184 -    (assemble-creature model joints)))
   2.185  
   2.186  (defn gray-scale [num]
   2.187    (+ num
     3.1 --- a/org/util.org	Fri Feb 03 06:41:16 2012 -0700
     3.2 +++ b/org/util.org	Fri Feb 03 06:47:05 2012 -0700
     3.3 @@ -398,6 +398,62 @@
     3.4    {"key-space" (fire-cannon-ball)})
     3.5  
     3.6     
     3.7 +(defn tap [obj direction force]
     3.8 +  (let [control (.getControl obj RigidBodyControl)]
     3.9 +    (.applyTorque
    3.10 +     control
    3.11 +     (.mult (.getPhysicsRotation control)
    3.12 +            (.mult (.normalize direction) (float force))))))
    3.13 +
    3.14 +
    3.15 +(defn with-movement
    3.16 +  [object
    3.17 +   [up down left right roll-up roll-down :as keyboard]
    3.18 +   forces
    3.19 +   [root-node
    3.20 +    keymap
    3.21 +    intilization
    3.22 +    world-loop]]
    3.23 +  (let [add-keypress
    3.24 +        (fn [state keymap key]
    3.25 +          (merge keymap
    3.26 +                  {key
    3.27 +                   (fn [_ pressed?]
    3.28 +                     (reset! state pressed?))}))
    3.29 +        move-up? (atom false)
    3.30 +        move-down? (atom false)
    3.31 +        move-left? (atom false)
    3.32 +        move-right? (atom false)
    3.33 +        roll-left? (atom false)
    3.34 +        roll-right? (atom false)
    3.35 +        
    3.36 +        directions [(Vector3f. 0 1 0)(Vector3f. 0 -1 0)
    3.37 +                    (Vector3f. 0 0 1)(Vector3f. 0 0 -1)
    3.38 +                    (Vector3f. -1 0 0)(Vector3f. 1 0 0)]
    3.39 +        atoms [move-left? move-right? move-up? move-down? 
    3.40 +                 roll-left? roll-right?]
    3.41 +
    3.42 +        keymap* (reduce merge
    3.43 +                        (map #(add-keypress %1 keymap %2)
    3.44 +                             atoms
    3.45 +                             keyboard))
    3.46 +        
    3.47 +        splice-loop (fn []
    3.48 +                      (dorun
    3.49 +                       (map
    3.50 +                        (fn [sym direction force]
    3.51 +                          (if @sym
    3.52 +                            (tap object direction force)))
    3.53 +                        atoms directions forces)))
    3.54 +
    3.55 +        world-loop* (fn [world tpf]
    3.56 +                       (world-loop world tpf)
    3.57 +                       (splice-loop))]
    3.58 +    [root-node
    3.59 +     keymap*
    3.60 +     intilization
    3.61 +     world-loop*]))
    3.62 +
    3.63  
    3.64  
    3.65  #+end_src