diff org/test-creature.org @ 78:77b506ac64f3

trying to make offset cone joints
author Robert McIntyre <rlm@mit.edu>
date Wed, 04 Jan 2012 20:34:00 -0700
parents 1f84f425e05d
children 01dbdb0d5500
line wrap: on
line diff
     1.1 --- a/org/test-creature.org	Wed Jan 04 08:36:42 2012 -0700
     1.2 +++ b/org/test-creature.org	Wed Jan 04 20:34:00 2012 -0700
     1.3 @@ -48,9 +48,6 @@
     1.4  (cortex.import/mega-import-jme3)
     1.5  (use '(cortex world util body hearing touch vision))
     1.6  
     1.7 -(use '[clojure.contrib [seq :only [find-first]]])
     1.8 -
     1.9 -
    1.10  (rlm.rlm-commands/help)
    1.11  
    1.12  (defn load-blender-model
    1.13 @@ -66,52 +63,351 @@
    1.14      (.findValue data key)
    1.15      nil))
    1.16  
    1.17 +(defn blender-to-jme
    1.18 +  "Convert from Blender coordinates to JME coordinates"
    1.19 +  [#^Vector3f in]
    1.20 +  (Vector3f. (.getX in)
    1.21 +             (.getZ in)
    1.22 +             (- (.getY in))))
    1.23  
    1.24 -(defn hand []
    1.25 -  (load-blender-model "Models/creature1/one.blend"))
    1.26 +(defn joint-targets
    1.27 +  "Return the two closest two objects to the joint object, ordered
    1.28 +  from bottom to top according to the joint's rotation."
    1.29 +  [#^Node parts #^Node joint]
    1.30 +  ;;(println (meta-data joint "joint"))
    1.31 +  (.getWorldRotation joint)
    1.32 +  (loop [radius (float 0.01)]
    1.33 +    (let [results (CollisionResults.)]
    1.34 +      (.collideWith
    1.35 +       parts
    1.36 +       (BoundingBox. (.getWorldTranslation joint)
    1.37 +                     radius radius radius)
    1.38 +       results)
    1.39 +      (let [targets
    1.40 +            (distinct
    1.41 +             (map  #(.getGeometry %) results))]
    1.42 +        (if (>= (count targets) 2)
    1.43 +          (sort-by
    1.44 +           #(.getY
    1.45 +             (.mult
    1.46 +              (.inverse (.getWorldRotation joint))
    1.47 +              (.subtract (.getWorldTranslation %)
    1.48 +                         (.getWorldTranslation joint))))
    1.49 +           (take 2 targets))
    1.50 +          (recur (float (* radius 2))))))))
    1.51  
    1.52 +(defn connect
    1.53 +  "here are some examples:
    1.54 +   {:type :point}
    1.55 +   {:type :hinge  :limit [0 (/ Math/PI 2)] :axis (Vector3f. 0 1 0)}
    1.56 +   (:axis defaults to (Vector3f. 1 0 0) if not provided for hinge joints)
    1.57  
    1.58 -  
    1.59 -(def hand-names
    1.60 -  #{
    1.61 -    "middle-1"
    1.62 -    "middle-2"
    1.63 -    "middle-3"
    1.64 -    "palm"
    1.65 -    "pinky-1"
    1.66 -    "pinky-2"
    1.67 -    "pinky-3"
    1.68 -    "pointer-1"
    1.69 -    "pointer-2"
    1.70 -    "pointer-3"
    1.71 -    "ring-1"
    1.72 -    "ring-2"
    1.73 -    "ring-3"
    1.74 -    "thumb-1"
    1.75 -    "thumb-2"})
    1.76 +   {:type :cone   :limit-xz 0]
    1.77 +                  :limit-yz 0]
    1.78 +                  :twist 0]}"
    1.79 +  ([#^Node obj-a #^Node obj-b #^Node joint]
    1.80 +     (let [center-a (.getWorldTranslation obj-a)
    1.81 +           center-b (.getWorldTranslation obj-b)
    1.82 +           joint-center (.getWorldTranslation joint)
    1.83 +           pivot-a (.subtract joint-center center-a)
    1.84 +           pivot-b (.subtract joint-center center-b)
    1.85 +           control-a (.getControl obj-a RigidBodyControl)
    1.86 +           control-b (.getControl obj-b RigidBodyControl)]
    1.87 +           ;; A side-effect of creating a joint registers
    1.88 +           ;; it with both physics objects which in turn
    1.89 +           ;; will register the joint with the physics system
    1.90 +           ;; when the simulation is started.
    1.91 +       (if-let [constraints
    1.92 +                (map-vals
    1.93 +                 eval
    1.94 +                 (read-string
    1.95 +                  (meta-data joint "joint")))]
    1.96  
    1.97 -(defn hand-pieces []
    1.98 -  (filter
    1.99 -   (comp hand-names #(apply str (drop-last (.getName %)))) (node-seq (hand))))
   1.100 +         (let [joint-type (:type constraints)]
   1.101 +           (println-repl "creating joint between"
   1.102 +                         (.getName obj-a) "and" (.getName obj-b))
   1.103 +           (cond (= :point joint-type)
   1.104 +                 (do
   1.105 +                   (println-repl "creating POINT joint")
   1.106 +                   (Point2PointJoint.
   1.107 +                    control-a
   1.108 +                    control-b
   1.109 +                    pivot-a
   1.110 +                    pivot-b))
   1.111 +                 (= :hinge joint-type)
   1.112 +                 (do
   1.113 +                   (println-repl "creating HINGE joint")
   1.114 +                   (let [axis (if-let
   1.115 +                                  [axis (:axis constraints)]
   1.116 +                                axis
   1.117 +                                Vector3f/UNIT_X)
   1.118 +                         [limit-1 limit-2] (:limit constraints)
   1.119 +                         hinge-axis
   1.120 +                         (.mult
   1.121 +                          (.getWorldRotation joint)
   1.122 +                          (blender-to-jme axis))]
   1.123 +                     (doto
   1.124 +                         (HingeJoint.
   1.125 +                          control-a
   1.126 +                          control-b
   1.127 +                          pivot-a
   1.128 +                          pivot-b
   1.129 +                          hinge-axis
   1.130 +                          hinge-axis)
   1.131 +                       (.setLimit limit-1 limit-2))))
   1.132 +                 (= :cone joint-type)
   1.133 +                 (do
   1.134 +                   (let [limit-xy (:limit-xz constraints)
   1.135 +                         limit-yz (:limit-yz constraints)
   1.136 +                         twist    (:twist constraints)]
   1.137 +                     
   1.138 +                     (println-repl "creating CONE joint")
   1.139 +                     (doto
   1.140 +                         (ConeJoint.
   1.141 +                          control-a
   1.142 +                          control-b
   1.143 +                          pivot-a
   1.144 +                          pivot-b
   1.145 +                          (doto (Matrix3f.)
   1.146 +                            (.fromStartEndVectors
   1.147 +                             Vector3f/UNIT_X
   1.148 +                             (.normalize
   1.149 +                              (.subtract (.getWorldTranslation joint)
   1.150 +                                         (.getWorldTranslation obj-a)))))
   1.151 +                          (doto (Matrix3f.)
   1.152 +                            (.fromStartEndVectors
   1.153 +                             Vector3f/UNIT_X
   1.154 +                             (.normalize
   1.155 +                              (.subtract
   1.156 +                               (.getWorldTranslation obj-b)
   1.157 +                               (.getWorldTranslation joint))))))
   1.158 +                       (.setLimit (float limit-xy)
   1.159 +                                  (float limit-yz)
   1.160 +                                  (float twist)))))
   1.161 +                 true
   1.162 +                 (println-repl
   1.163 +                  "joint-type" joint-type "not recognized")))
   1.164 +                 
   1.165 +           (println-repl "could not find joint meta-data!")))))
   1.166  
   1.167 -(defn hand-joints []
   1.168 -  (map #(.getWorldTranslation %)
   1.169 -       (filter #(re-matches #"joint\.\d\d\d" (.getName %))
   1.170 -               (node-seq (hand)))))
   1.171 -(defn worm []
   1.172 -  (load-blender-model "Models/creature1/try-again.blend"))
   1.173 +(defn assemble-creature [#^Node pieces joints]
   1.174 +  (dorun
   1.175 +   (map
   1.176 +    (fn [geom]
   1.177 +      (let [physics-control
   1.178 +            (RigidBodyControl.
   1.179 +             (HullCollisionShape.
   1.180 +              (.getMesh geom))
   1.181 +             (if-let [mass (meta-data geom "mass")]
   1.182 +               (do
   1.183 +                 (println-repl
   1.184 +                  "setting" (.getName geom) "mass to" (float mass))
   1.185 +                 (float mass))
   1.186 +               (float 1)))]
   1.187 +               
   1.188 +        (.addControl geom physics-control)))
   1.189 +    (filter #(isa? (class %) Geometry )
   1.190 +            (node-seq pieces))))
   1.191  
   1.192 +  (dorun
   1.193 +   (map
   1.194 +    (fn [joint]
   1.195 +      (let [[obj-a obj-b]
   1.196 +            (joint-targets pieces joint)]
   1.197 +        (connect obj-a obj-b joint)))
   1.198 +    joints))
   1.199 +  pieces)
   1.200  
   1.201 -(defn worm-pieces []
   1.202 -  (filter
   1.203 -   (comp #{"worm-2" "worm-1"}
   1.204 -         #(apply str (drop-last (.getName %))))
   1.205 -   (node-seq (worm))))
   1.206 +(defn blender-creature [blender-path]
   1.207 +  (let [model (load-blender-model blender-path)
   1.208 +        joints
   1.209 +        (if-let [joint-node (.getChild model "joints")]
   1.210 +          (seq (.getChildren joint-node))
   1.211 +          (do (println-repl "could not find joints node")
   1.212 +              []))]
   1.213 +  (assemble-creature model joints)))
   1.214  
   1.215 -(defn worm-joints []
   1.216 -  (filter #(re-matches #"joint\.\d\d\d" (.getName %))
   1.217 -          (node-seq (worm))))
   1.218 +(def hand "Models/creature1/one.blend")
   1.219  
   1.220 +(def worm "Models/creature1/try-again.blend")
   1.221 +
   1.222 +(defn test-creature [thing]
   1.223 +  (world
   1.224 +   (nodify [(blender-creature thing)
   1.225 +            (box 10 2 10 :position (Vector3f. 0 -5.5 0)
   1.226 +                 :color ColorRGBA/Gray :mass 0)])
   1.227 +   standard-debug-controls
   1.228 +   (comp light-up-everything enable-debug
   1.229 +         (fn [world]
   1.230 +           (.setTimer world (NanoTimer.))
   1.231 +           ;;(set-gravity world (Vector3f. 0 0 0))
   1.232 +           (speed-up world)
   1.233 +           world
   1.234 +           ))
   1.235 +   no-op))
   1.236 +
   1.237 +(defn world-setup [joint]
   1.238 +  (let [top (doto
   1.239 +                (sphere 0.1 :physical? false :color ColorRGBA/Yellow
   1.240 +                        :position (Vector3f. 0 7 0))
   1.241 +              (.addControl
   1.242 +               (RigidBodyControl.
   1.243 +                (CapsuleCollisionShape. 0.5 1.5 1) (float 15))))
   1.244 +        bottom (doto
   1.245 +                   (sphere 0.1 :physical? false :color ColorRGBA/DarkGray
   1.246 +                           :position (Vector3f. 0 -1 0))
   1.247 +              (.addControl
   1.248 +               (RigidBodyControl.
   1.249 +                (CapsuleCollisionShape. 0.5 1.5 1) (float 0))))
   1.250 +        table (box 10 2 10 :position (Vector3f. 0 -6 0)
   1.251 +                   :color ColorRGBA/Gray :mass 0)
   1.252 +        a (.getControl top RigidBodyControl)
   1.253 +        b (.getControl bottom RigidBodyControl)]
   1.254 +    (cond
   1.255 +     (= joint :point)
   1.256 +     (doto
   1.257 +         (Point2PointJoint. a b
   1.258 +                            (Vector3f. 0 -2 0)
   1.259 +                            (Vector3f. 0  2 0))
   1.260 +       (.setCollisionBetweenLinkedBodys false))
   1.261 +     (= joint :hinge)
   1.262 +     (doto
   1.263 +         (HingeJoint.
   1.264 +          a b
   1.265 +          (Vector3f. 0 -2 0)
   1.266 +          (Vector3f. 0 2 0)
   1.267 +          (Vector3f. 0 0 1)
   1.268 +          (Vector3f. 0 0 1)
   1.269 +
   1.270 +          )
   1.271 +       (.setCollisionBetweenLinkedBodys false)
   1.272 +       ;;(.setLimit (- Math/PI) Math/PI)
   1.273 +       )
   1.274 +     (= joint :cone)
   1.275 +     ;; note to self -- jbullet does NOT implement cone joints
   1.276 +     ;; correctly. You must use plain ol' bullet for this to work.
   1.277 +     ;; It's faster anyway, so whatever.
   1.278 +     
   1.279 +     (doto (ConeJoint.
   1.280 +            a b
   1.281 +            (Vector3f. 0 -5 0)
   1.282 +            (Vector3f. 0 2 0)
   1.283 +
   1.284 +            (doto (Matrix3f.)
   1.285 +              (.fromStartEndVectors Vector3f/UNIT_X
   1.286 +                                    Vector3f/UNIT_Y))
   1.287 +            (doto (Matrix3f.)
   1.288 +              (.fromStartEndVectors Vector3f/UNIT_X
   1.289 +                                    (.normalize
   1.290 +                                     (Vector3f. 5 5 0))))
   1.291 +            )
   1.292 +       ;;(.setAngularOnly true)
   1.293 +       
   1.294 +       (.setCollisionBetweenLinkedBodys false)
   1.295 +       (.setLimit (* 1 (/ Math/PI 4))
   1.296 +                  (* 1 (/ Math/PI 2))
   1.297 +                  (* 0 (/ Math/PI 4)))
   1.298 +        
   1.299 +       )
   1.300 +     (= joint :six)
   1.301 +     (doto
   1.302 +         (SixDofJoint.
   1.303 +          a b
   1.304 +          (Vector3f. 0 -2 0)
   1.305 +          (Vector3f. 0 2 0)
   1.306 +          ;;(doto (Matrix3f.)
   1.307 +          ;;    (.fromStartEndVectors Vector3f/UNIT_X
   1.308 +          ;;                          Vector3f/UNIT_Y))
   1.309 +          ;;(doto (Matrix3f.)
   1.310 +          ;;  (.fromStartEndVectors Vector3f/UNIT_X
   1.311 +          ;;                        Vector3f/UNIT_Y))
   1.312 +          true)
   1.313 +       (.setCollisionBetweenLinkedBodys false)
   1.314 +       (.setAngularLowerLimit (Vector3f. 0
   1.315 +                                         (- (/ Math/PI 2))
   1.316 +                                         0))
   1.317 +                                         
   1.318 +       (.setAngularUpperLimit (Vector3f. 0
   1.319 +                                         (/ Math/PI 2)
   1.320 +                                         0))
   1.321 +       (.setLinearLowerLimit  (Vector3f. 0 0 0))
   1.322 +       (.setLinearUpperLimit  (Vector3f. 0 0 0))
   1.323 +
   1.324 +       )
   1.325 +          
   1.326 +            
   1.327 +            
   1.328 +          
   1.329 +     
   1.330 +    )
   1.331 +      
   1.332 +    [top bottom table]))
   1.333 +
   1.334 +
   1.335 +(defn test-joint [joint]
   1.336 +  (let [[top bottom floor] (world-setup joint)
   1.337 +        control (.getControl top RigidBodyControl)
   1.338 +        move-up? (atom false)
   1.339 +        move-down? (atom false)
   1.340 +        move-left? (atom false)
   1.341 +        move-right? (atom false)
   1.342 +        roll-left? (atom false)
   1.343 +        roll-right? (atom false)
   1.344 +        timer (atom 0)]
   1.345 +
   1.346 +    (world
   1.347 +     (nodify [top bottom floor])
   1.348 +     (merge standard-debug-controls
   1.349 +            {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
   1.350 +             "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
   1.351 +             "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
   1.352 +             "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
   1.353 +             "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
   1.354 +             "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})     
   1.355 +     
   1.356 +     (fn [world]
   1.357 +       (light-up-everything world)
   1.358 +       (enable-debug world)
   1.359 +       (set-gravity world (Vector3f. 0 0 0))
   1.360 +       )
   1.361 +     
   1.362 +     (fn [world _]
   1.363 +       (if (zero? (rem (swap! timer inc) 100))
   1.364 +         (do
   1.365 +         ;;  (println-repl @timer)
   1.366 +           (.attachChild (.getRootNode world)
   1.367 +                       (sphere 0.05 :color ColorRGBA/Yellow
   1.368 +                               :position (.getWorldTranslation top)
   1.369 +                               :physical? false))))
   1.370 +       (if @move-up?
   1.371 +         (.applyTorque control
   1.372 +                       (.mult (.getPhysicsRotation control)
   1.373 +                              (Vector3f. 0 0 10))))
   1.374 +       (if @move-down?
   1.375 +         (.applyTorque control
   1.376 +                       (.mult (.getPhysicsRotation control)
   1.377 +                              (Vector3f. 0 0 -10))))
   1.378 +       (if @move-left?
   1.379 +         (.applyTorque control
   1.380 +                       (.mult (.getPhysicsRotation control)
   1.381 +                              (Vector3f. 0 10 0))))
   1.382 +       (if @move-right?
   1.383 +         (.applyTorque control
   1.384 +                       (.mult (.getPhysicsRotation control)
   1.385 +                              (Vector3f. 0 -10 0))))
   1.386 +       (if @roll-left?
   1.387 +         (.applyTorque control
   1.388 +                       (.mult (.getPhysicsRotation control)
   1.389 +                              (Vector3f. -1 0 0))))
   1.390 +       (if @roll-right?
   1.391 +         (.applyTorque control
   1.392 +                       (.mult (.getPhysicsRotation control)
   1.393 +                              (Vector3f. 1 0 0))))))))
   1.394 +#+end_src
   1.395 +
   1.396 +
   1.397 +* COMMENT purgatory
   1.398 +#+begin_src clojure
   1.399  (defn bullet-trans []
   1.400    (let [obj-a (sphere 0.5 :color ColorRGBA/Red
   1.401                        :position (Vector3f. -10 5 0))
   1.402 @@ -233,366 +529,10 @@
   1.403             )
   1.404      ))
   1.405  
   1.406 -        
   1.407 -                          
   1.408 -    
   1.409 -        
   1.410 -    
   1.411  
   1.412  
   1.413 -
   1.414 -
   1.415 -
   1.416 -(defn world-setup [joint]
   1.417 -  (let [top (doto
   1.418 -                (sphere 0.1 :physical? false :color ColorRGBA/Yellow
   1.419 -                        :position (Vector3f. 0 7 0))
   1.420 -              (.addControl
   1.421 -               (RigidBodyControl.
   1.422 -                (CapsuleCollisionShape. 0.5 1.5 1) (float 15))))
   1.423 -        bottom (doto
   1.424 -                   (sphere 0.1 :physical? false :color ColorRGBA/DarkGray
   1.425 -                           :position (Vector3f. 0 -1 0))
   1.426 -              (.addControl
   1.427 -               (RigidBodyControl.
   1.428 -                (CapsuleCollisionShape. 0.5 1.5 1) (float 0))))
   1.429 -        table (box 10 2 10 :position (Vector3f. 0 -6 0)
   1.430 -                   :color ColorRGBA/Gray :mass 0)
   1.431 -        a (.getControl top RigidBodyControl)
   1.432 -        b (.getControl bottom RigidBodyControl)]
   1.433 -    (cond
   1.434 -     (= joint :point)
   1.435 -     (doto
   1.436 -         (Point2PointJoint. a b
   1.437 -                            (Vector3f. 0 -2 0)
   1.438 -                            (Vector3f. 0  2 0))
   1.439 -       (.setCollisionBetweenLinkedBodys false))
   1.440 -     (= joint :hinge)
   1.441 -     (doto
   1.442 -         (HingeJoint.
   1.443 -          a b
   1.444 -          (Vector3f. 0 -2 0)
   1.445 -          (Vector3f. 0 2 0)
   1.446 -          (Vector3f. 0 0 1)
   1.447 -          (Vector3f. 0 0 1)
   1.448 -
   1.449 -          )
   1.450 -       (.setCollisionBetweenLinkedBodys false)
   1.451 -       ;;(.setLimit (- Math/PI) Math/PI)
   1.452 -       )
   1.453 -     (= joint :cone)
   1.454 -     ;; note to self -- jbullet does NOT implement cone joints
   1.455 -     ;; correctly. You must use plain ol' bullet for this to work.
   1.456 -     ;; It's faster anyway, so whatever.
   1.457 -     
   1.458 -     (doto (ConeJoint.
   1.459 -            a b
   1.460 -            (Vector3f. 0 -5 0)
   1.461 -            (Vector3f. 0 2 0)
   1.462 -
   1.463 -            (doto (Matrix3f.)
   1.464 -              (.fromStartEndVectors Vector3f/UNIT_X
   1.465 -                                    Vector3f/UNIT_Y))
   1.466 -            (doto (Matrix3f.)
   1.467 -              (.fromStartEndVectors Vector3f/UNIT_X
   1.468 -                                    Vector3f/UNIT_Y))
   1.469 -            )
   1.470 -       ;;(.setAngularOnly true)
   1.471 -       
   1.472 -       (.setCollisionBetweenLinkedBodys false)
   1.473 -       (.setLimit (* 1 (/ Math/PI 4))
   1.474 -                  (* 1 (/ Math/PI 4))
   1.475 -                  (* 0 (/ Math/PI 4)))
   1.476 -        
   1.477 -       )
   1.478 -     (= joint :six)
   1.479 -     (doto
   1.480 -         (SixDofJoint.
   1.481 -          a b
   1.482 -          (Vector3f. 0 -2 0)
   1.483 -          (Vector3f. 0 2 0)
   1.484 -          ;;(doto (Matrix3f.)
   1.485 -          ;;    (.fromStartEndVectors Vector3f/UNIT_X
   1.486 -          ;;                          Vector3f/UNIT_Y))
   1.487 -          ;;(doto (Matrix3f.)
   1.488 -          ;;  (.fromStartEndVectors Vector3f/UNIT_X
   1.489 -          ;;                        Vector3f/UNIT_Y))
   1.490 -          true)
   1.491 -       (.setCollisionBetweenLinkedBodys false)
   1.492 -       (.setAngularLowerLimit (Vector3f. 0
   1.493 -                                         (- (/ Math/PI 2))
   1.494 -                                         0))
   1.495 -                                         
   1.496 -       (.setAngularUpperLimit (Vector3f. 0
   1.497 -                                         (/ Math/PI 2)
   1.498 -                                         0))
   1.499 -       (.setLinearLowerLimit  (Vector3f. 0 0 0))
   1.500 -       (.setLinearUpperLimit  (Vector3f. 0 0 0))
   1.501 -
   1.502 -       )
   1.503 -          
   1.504 -            
   1.505 -            
   1.506 -          
   1.507 -     
   1.508 -    )
   1.509 -      
   1.510 -    [top bottom table]))
   1.511 -
   1.512 -(defn speed-up [world]
   1.513 -  (.setMoveSpeed (.getFlyByCamera world)
   1.514 -                 (float 100))
   1.515 -  (.setRotationSpeed (.getFlyByCamera world)
   1.516 -                     (float 20))
   1.517 -  world)
   1.518 -
   1.519 -
   1.520 -(defn test-joint [joint]
   1.521 -  (let [[top bottom floor] (world-setup joint)
   1.522 -        control (.getControl top RigidBodyControl)
   1.523 -        move-up? (atom false)
   1.524 -        move-down? (atom false)
   1.525 -        move-left? (atom false)
   1.526 -        move-right? (atom false)
   1.527 -        roll-left? (atom false)
   1.528 -        roll-right? (atom false)
   1.529 -        timer (atom 0)]
   1.530 -
   1.531 -    (world
   1.532 -     (nodify [top bottom floor])
   1.533 -     (merge standard-debug-controls
   1.534 -            {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
   1.535 -             "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
   1.536 -             "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
   1.537 -             "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
   1.538 -             "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
   1.539 -             "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})     
   1.540 -     
   1.541 -     (fn [world]
   1.542 -       (light-up-everything world)
   1.543 -       (enable-debug world)
   1.544 -       (set-gravity world (Vector3f. 0 0 0))
   1.545 -       )
   1.546 -     
   1.547 -     (fn [world _]
   1.548 -       (if (zero? (rem (swap! timer inc) 100))
   1.549 -         (do
   1.550 -         ;;  (println-repl @timer)
   1.551 -           (.attachChild (.getRootNode world)
   1.552 -                       (sphere 0.05 :color ColorRGBA/Yellow
   1.553 -                               :position (.getWorldTranslation top)
   1.554 -                               :physical? false))))
   1.555 -       (if @move-up?
   1.556 -         (.applyTorque control
   1.557 -                       (.mult (.getPhysicsRotation control)
   1.558 -                              (Vector3f. 0 0 10))))
   1.559 -       (if @move-down?
   1.560 -         (.applyTorque control
   1.561 -                       (.mult (.getPhysicsRotation control)
   1.562 -                              (Vector3f. 0 0 -10))))
   1.563 -       (if @move-left?
   1.564 -         (.applyTorque control
   1.565 -                       (.mult (.getPhysicsRotation control)
   1.566 -                              (Vector3f. 0 10 0))))
   1.567 -       (if @move-right?
   1.568 -         (.applyTorque control
   1.569 -                       (.mult (.getPhysicsRotation control)
   1.570 -                              (Vector3f. 0 -10 0))))
   1.571 -       (if @roll-left?
   1.572 -         (.applyTorque control
   1.573 -                       (.mult (.getPhysicsRotation control)
   1.574 -                              (Vector3f. -1 0 0))))
   1.575 -       (if @roll-right?
   1.576 -         (.applyTorque control
   1.577 -                       (.mult (.getPhysicsRotation control)
   1.578 -                              (Vector3f. 1 0 0))))))))
   1.579 -
   1.580 -                  
   1.581 -
   1.582 -(defn run [joint] (.start (test-joint joint)))
   1.583 -(defn look [joint] (view (nodify (world-setup joint))))
   1.584 -
   1.585 -(defn blender-to-jme
   1.586 -  "Convert from Blender coordinates to JME coordinates"
   1.587 -  [#^Vector3f in]
   1.588 -  (Vector3f. (.getX in)
   1.589 -             (.getZ in)
   1.590 -             (- (.getY in))))
   1.591 -
   1.592 -
   1.593 -(defn joint-targets
   1.594 -  "Return the two closest two objects to the joint object, ordered
   1.595 -  from bottom to top according to the joint's rotation."
   1.596 -  [#^Node parts #^Node joint]
   1.597 -  ;;(println (meta-data joint "joint"))
   1.598 -  (.getWorldRotation joint)
   1.599 -  (loop [radius (float 0.01)]
   1.600 -    (let [results (CollisionResults.)]
   1.601 -      (.collideWith
   1.602 -       parts
   1.603 -       (BoundingBox. (.getWorldTranslation joint)
   1.604 -                     radius radius radius)
   1.605 -       results)
   1.606 -      (let [targets
   1.607 -            (distinct
   1.608 -             (map  #(.getGeometry %) results))]
   1.609 -        (if (>= (count targets) 2)
   1.610 -          (sort-by
   1.611 -           #(.getY
   1.612 -             (.mult
   1.613 -              (.inverse (.getWorldRotation joint))
   1.614 -              (.subtract (.getWorldTranslation %)
   1.615 -                         (.getWorldTranslation joint))))
   1.616 -           (take 2 targets))
   1.617 -          (recur (float (* radius 2))))))))
   1.618 -
   1.619 -(defn connect
   1.620 -  "here are some examples:
   1.621 -   {:type :point}
   1.622 -   {:type :hinge  :limit [0 (/ Math/PI 2)] :axis (Vector3f. 0 1 0)}
   1.623 -   (:axis defaults to (Vector3f. 1 0 0) if not provided for hinge joints)
   1.624 -
   1.625 -   {:type :cone   :limit-xz 0]
   1.626 -                  :limit-yz 0]
   1.627 -                  :twist 0]}
   1.628 -"
   1.629 -  ([#^Node obj-a #^Node obj-b #^Node joint]
   1.630 -     (let [center-a (.getWorldTranslation obj-a)
   1.631 -           center-b (.getWorldTranslation obj-b)
   1.632 -           joint-center (.getWorldTranslation joint)
   1.633 -           pivot-a (.subtract joint-center center-a)
   1.634 -           pivot-b (.subtract joint-center center-b)
   1.635 -           control-a (.getControl obj-a RigidBodyControl)
   1.636 -           control-b (.getControl obj-b RigidBodyControl)]
   1.637 -           ;; A side-effect of creating a joint registers
   1.638 -           ;; it with both physics objects which in turn
   1.639 -           ;; will register the joint with the physics system
   1.640 -           ;; when the simulation is started.
   1.641 -       (if-let [constraints
   1.642 -                (map-vals
   1.643 -                 eval
   1.644 -                 (read-string
   1.645 -                  (meta-data (first (worm-joints)) "joint")))]
   1.646 -
   1.647 -         (let [joint-type (:type constraints)]
   1.648 -           (cond (= :point joint-type)
   1.649 -                 (do
   1.650 -                   (println-repl "creating POINT joint")
   1.651 -                   (Point2PointJoint.
   1.652 -                    control-a
   1.653 -                    control-b
   1.654 -                    pivot-a
   1.655 -                    pivot-b))
   1.656 -                 (= :hinge joint-type)
   1.657 -                 (do
   1.658 -                   (println-repl "creating HINGE joint")
   1.659 -                   (let [axis (if-let
   1.660 -                                  [axis (:axis constraints)]
   1.661 -                                axis
   1.662 -                                Vector3f/UNIT_X)
   1.663 -                         [limit-1 limit-2] (:limit constraints)
   1.664 -                         hinge-axis
   1.665 -                         (.mult
   1.666 -                          (.getWorldRotation joint)
   1.667 -                          (blender-to-jme axis))]
   1.668 -                     (doto
   1.669 -                         (HingeJoint.
   1.670 -                          control-a
   1.671 -                          control-b
   1.672 -                          pivot-a
   1.673 -                          pivot-b
   1.674 -                          hinge-axis
   1.675 -                          hinge-axis)
   1.676 -                       (.setLimit limit-1 limit-2))))
   1.677 -                 (= :cone joint-type)
   1.678 -                 (do
   1.679 -                   (let [limit-xy (:limit-xz constraints)
   1.680 -                         limit-yz (:limit-yz constraints)
   1.681 -                         twist    (:twist constraints)]
   1.682 -                     
   1.683 -                     (println-repl "creating CONE joint")
   1.684 -                     (doto
   1.685 -                         (ConeJoint.
   1.686 -                          control-a
   1.687 -                          control-b
   1.688 -                          pivot-a
   1.689 -                          pivot-b
   1.690 -                          (doto (Matrix3f.)
   1.691 -                            (.fromStartEndVectors
   1.692 -                             Vector3f/UNIT_X
   1.693 -                             (.normalize
   1.694 -                              (.subtract (.getWorldTranslation joint)
   1.695 -                                         (.getWorldTranslation obj-a)))))
   1.696 -                          (doto (Matrix3f.)
   1.697 -                            (.fromStartEndVectors
   1.698 -                             Vector3f/UNIT_X
   1.699 -                             (.normalize
   1.700 -                              (.subtract
   1.701 -                               (.getWorldTranslation obj-b)
   1.702 -                               (.getWorldTranslation joint))))))
   1.703 -                       (.setLimit (float limit-xy)
   1.704 -                                  (float limit-yz)
   1.705 -                                  (float twist)))))
   1.706 -                 true
   1.707 -                 (println-repl
   1.708 -                  "joint-type " joint-type " not recognized")))
   1.709 -                 
   1.710 -           (println-repl "could not find joint meta-data!")))))
   1.711 -           
   1.712 -
   1.713 -
   1.714 -(defn physical-worm [#^Node pieces joints]
   1.715 -  (dorun
   1.716 -   (map
   1.717 -    (fn [geom]
   1.718 -      (let [physics-control
   1.719 -            (RigidBodyControl.
   1.720 -             (HullCollisionShape.
   1.721 -              (.getMesh geom))
   1.722 -             (if-let [mass (meta-data geom "mass")]
   1.723 -               (do
   1.724 -                 (println-repl
   1.725 -                  "setting mass to " (float mass))
   1.726 -                 (float mass))
   1.727 -               (float 1)))]
   1.728 -               
   1.729 -        (.addControl geom physics-control)))
   1.730 -    (filter #(isa? (class %) Geometry )
   1.731 -            (node-seq pieces))))
   1.732 -
   1.733 -  (dorun
   1.734 -   (map
   1.735 -    (fn [joint]
   1.736 -      (let [[obj-a obj-b]
   1.737 -            (joint-targets pieces joint)]
   1.738 -        (connect obj-a obj-b joint)))
   1.739 -    joints))
   1.740 -  pieces)
   1.741 -
   1.742 -(defn the-worm []
   1.743 -  (physical-worm (worm) (worm-joints)))
   1.744 -
   1.745 -(defn test-worm []
   1.746 -  (world
   1.747 -   (nodify [(the-worm)
   1.748 -            (box 10 2 10 :position (Vector3f. 0 -5 0)
   1.749 -                 :color ColorRGBA/Gray :mass 0)])
   1.750 -   standard-debug-controls
   1.751 -   (comp light-up-everything enable-debug
   1.752 -         (fn [world]
   1.753 -           (.setTimer world (NanoTimer.))
   1.754 -           (speed-up world)
   1.755 -           ;;(set-gravity world (Vector3f. 0 0 0))
   1.756 -           world
   1.757 -           ))
   1.758 -   no-op))
   1.759 -
   1.760  #+end_src
   1.761  
   1.762 -#+results: body-1
   1.763 -: #'cortex.silly/test-try-again
   1.764 -
   1.765 -
   1.766  
   1.767  * COMMENT generate source
   1.768  #+begin_src clojure :tangle ../src/cortex/silly.clj