# HG changeset patch # User Robert McIntyre # Date 1325734440 25200 # Node ID 77b506ac64f33872dc8c769f3351f634fc8a4f9b # Parent 1f84f425e05d3a6481d0d6198a8626c7bed338dc trying to make offset cone joints diff -r 1f84f425e05d -r 77b506ac64f3 assets/Models/creature1/one.blend Binary file assets/Models/creature1/one.blend has changed diff -r 1f84f425e05d -r 77b506ac64f3 assets/Models/creature1/try-again.blend Binary file assets/Models/creature1/try-again.blend has changed diff -r 1f84f425e05d -r 77b506ac64f3 org/test-creature.org --- a/org/test-creature.org Wed Jan 04 08:36:42 2012 -0700 +++ b/org/test-creature.org Wed Jan 04 20:34:00 2012 -0700 @@ -48,9 +48,6 @@ (cortex.import/mega-import-jme3) (use '(cortex world util body hearing touch vision)) -(use '[clojure.contrib [seq :only [find-first]]]) - - (rlm.rlm-commands/help) (defn load-blender-model @@ -66,52 +63,351 @@ (.findValue data key) nil)) +(defn blender-to-jme + "Convert from Blender coordinates to JME coordinates" + [#^Vector3f in] + (Vector3f. (.getX in) + (.getZ in) + (- (.getY in)))) -(defn hand [] - (load-blender-model "Models/creature1/one.blend")) +(defn joint-targets + "Return the two closest two objects to the joint object, ordered + from bottom to top according to the joint's rotation." + [#^Node parts #^Node joint] + ;;(println (meta-data joint "joint")) + (.getWorldRotation joint) + (loop [radius (float 0.01)] + (let [results (CollisionResults.)] + (.collideWith + parts + (BoundingBox. (.getWorldTranslation joint) + radius radius radius) + results) + (let [targets + (distinct + (map #(.getGeometry %) results))] + (if (>= (count targets) 2) + (sort-by + #(.getY + (.mult + (.inverse (.getWorldRotation joint)) + (.subtract (.getWorldTranslation %) + (.getWorldTranslation joint)))) + (take 2 targets)) + (recur (float (* radius 2)))))))) +(defn connect + "here are some examples: + {:type :point} + {:type :hinge :limit [0 (/ Math/PI 2)] :axis (Vector3f. 0 1 0)} + (:axis defaults to (Vector3f. 1 0 0) if not provided for hinge joints) - -(def hand-names - #{ - "middle-1" - "middle-2" - "middle-3" - "palm" - "pinky-1" - "pinky-2" - "pinky-3" - "pointer-1" - "pointer-2" - "pointer-3" - "ring-1" - "ring-2" - "ring-3" - "thumb-1" - "thumb-2"}) + {:type :cone :limit-xz 0] + :limit-yz 0] + :twist 0]}" + ([#^Node obj-a #^Node obj-b #^Node joint] + (let [center-a (.getWorldTranslation obj-a) + center-b (.getWorldTranslation obj-b) + joint-center (.getWorldTranslation joint) + pivot-a (.subtract joint-center center-a) + pivot-b (.subtract joint-center center-b) + control-a (.getControl obj-a RigidBodyControl) + control-b (.getControl obj-b RigidBodyControl)] + ;; A side-effect of creating a joint registers + ;; it with both physics objects which in turn + ;; will register the joint with the physics system + ;; when the simulation is started. + (if-let [constraints + (map-vals + eval + (read-string + (meta-data joint "joint")))] -(defn hand-pieces [] - (filter - (comp hand-names #(apply str (drop-last (.getName %)))) (node-seq (hand)))) + (let [joint-type (:type constraints)] + (println-repl "creating joint between" + (.getName obj-a) "and" (.getName obj-b)) + (cond (= :point joint-type) + (do + (println-repl "creating POINT joint") + (Point2PointJoint. + control-a + control-b + pivot-a + pivot-b)) + (= :hinge joint-type) + (do + (println-repl "creating HINGE joint") + (let [axis (if-let + [axis (:axis constraints)] + axis + Vector3f/UNIT_X) + [limit-1 limit-2] (:limit constraints) + hinge-axis + (.mult + (.getWorldRotation joint) + (blender-to-jme axis))] + (doto + (HingeJoint. + control-a + control-b + pivot-a + pivot-b + hinge-axis + hinge-axis) + (.setLimit limit-1 limit-2)))) + (= :cone joint-type) + (do + (let [limit-xy (:limit-xz constraints) + limit-yz (:limit-yz constraints) + twist (:twist constraints)] + + (println-repl "creating CONE joint") + (doto + (ConeJoint. + control-a + control-b + pivot-a + pivot-b + (doto (Matrix3f.) + (.fromStartEndVectors + Vector3f/UNIT_X + (.normalize + (.subtract (.getWorldTranslation joint) + (.getWorldTranslation obj-a))))) + (doto (Matrix3f.) + (.fromStartEndVectors + Vector3f/UNIT_X + (.normalize + (.subtract + (.getWorldTranslation obj-b) + (.getWorldTranslation joint)))))) + (.setLimit (float limit-xy) + (float limit-yz) + (float twist))))) + true + (println-repl + "joint-type" joint-type "not recognized"))) + + (println-repl "could not find joint meta-data!"))))) -(defn hand-joints [] - (map #(.getWorldTranslation %) - (filter #(re-matches #"joint\.\d\d\d" (.getName %)) - (node-seq (hand))))) -(defn worm [] - (load-blender-model "Models/creature1/try-again.blend")) +(defn assemble-creature [#^Node pieces joints] + (dorun + (map + (fn [geom] + (let [physics-control + (RigidBodyControl. + (HullCollisionShape. + (.getMesh geom)) + (if-let [mass (meta-data geom "mass")] + (do + (println-repl + "setting" (.getName geom) "mass to" (float mass)) + (float mass)) + (float 1)))] + + (.addControl geom physics-control))) + (filter #(isa? (class %) Geometry ) + (node-seq pieces)))) + (dorun + (map + (fn [joint] + (let [[obj-a obj-b] + (joint-targets pieces joint)] + (connect obj-a obj-b joint))) + joints)) + pieces) -(defn worm-pieces [] - (filter - (comp #{"worm-2" "worm-1"} - #(apply str (drop-last (.getName %)))) - (node-seq (worm)))) +(defn blender-creature [blender-path] + (let [model (load-blender-model blender-path) + joints + (if-let [joint-node (.getChild model "joints")] + (seq (.getChildren joint-node)) + (do (println-repl "could not find joints node") + []))] + (assemble-creature model joints))) -(defn worm-joints [] - (filter #(re-matches #"joint\.\d\d\d" (.getName %)) - (node-seq (worm)))) +(def hand "Models/creature1/one.blend") +(def worm "Models/creature1/try-again.blend") + +(defn test-creature [thing] + (world + (nodify [(blender-creature thing) + (box 10 2 10 :position (Vector3f. 0 -5.5 0) + :color ColorRGBA/Gray :mass 0)]) + standard-debug-controls + (comp light-up-everything enable-debug + (fn [world] + (.setTimer world (NanoTimer.)) + ;;(set-gravity world (Vector3f. 0 0 0)) + (speed-up world) + world + )) + no-op)) + +(defn world-setup [joint] + (let [top (doto + (sphere 0.1 :physical? false :color ColorRGBA/Yellow + :position (Vector3f. 0 7 0)) + (.addControl + (RigidBodyControl. + (CapsuleCollisionShape. 0.5 1.5 1) (float 15)))) + bottom (doto + (sphere 0.1 :physical? false :color ColorRGBA/DarkGray + :position (Vector3f. 0 -1 0)) + (.addControl + (RigidBodyControl. + (CapsuleCollisionShape. 0.5 1.5 1) (float 0)))) + table (box 10 2 10 :position (Vector3f. 0 -6 0) + :color ColorRGBA/Gray :mass 0) + a (.getControl top RigidBodyControl) + b (.getControl bottom RigidBodyControl)] + (cond + (= joint :point) + (doto + (Point2PointJoint. a b + (Vector3f. 0 -2 0) + (Vector3f. 0 2 0)) + (.setCollisionBetweenLinkedBodys false)) + (= joint :hinge) + (doto + (HingeJoint. + a b + (Vector3f. 0 -2 0) + (Vector3f. 0 2 0) + (Vector3f. 0 0 1) + (Vector3f. 0 0 1) + + ) + (.setCollisionBetweenLinkedBodys false) + ;;(.setLimit (- Math/PI) Math/PI) + ) + (= joint :cone) + ;; note to self -- jbullet does NOT implement cone joints + ;; correctly. You must use plain ol' bullet for this to work. + ;; It's faster anyway, so whatever. + + (doto (ConeJoint. + a b + (Vector3f. 0 -5 0) + (Vector3f. 0 2 0) + + (doto (Matrix3f.) + (.fromStartEndVectors Vector3f/UNIT_X + Vector3f/UNIT_Y)) + (doto (Matrix3f.) + (.fromStartEndVectors Vector3f/UNIT_X + (.normalize + (Vector3f. 5 5 0)))) + ) + ;;(.setAngularOnly true) + + (.setCollisionBetweenLinkedBodys false) + (.setLimit (* 1 (/ Math/PI 4)) + (* 1 (/ Math/PI 2)) + (* 0 (/ Math/PI 4))) + + ) + (= joint :six) + (doto + (SixDofJoint. + a b + (Vector3f. 0 -2 0) + (Vector3f. 0 2 0) + ;;(doto (Matrix3f.) + ;; (.fromStartEndVectors Vector3f/UNIT_X + ;; Vector3f/UNIT_Y)) + ;;(doto (Matrix3f.) + ;; (.fromStartEndVectors Vector3f/UNIT_X + ;; Vector3f/UNIT_Y)) + true) + (.setCollisionBetweenLinkedBodys false) + (.setAngularLowerLimit (Vector3f. 0 + (- (/ Math/PI 2)) + 0)) + + (.setAngularUpperLimit (Vector3f. 0 + (/ Math/PI 2) + 0)) + (.setLinearLowerLimit (Vector3f. 0 0 0)) + (.setLinearUpperLimit (Vector3f. 0 0 0)) + + ) + + + + + + ) + + [top bottom table])) + + +(defn test-joint [joint] + (let [[top bottom floor] (world-setup joint) + control (.getControl top RigidBodyControl) + move-up? (atom false) + move-down? (atom false) + move-left? (atom false) + move-right? (atom false) + roll-left? (atom false) + roll-right? (atom false) + timer (atom 0)] + + (world + (nodify [top bottom floor]) + (merge standard-debug-controls + {"key-r" (fn [_ pressed?] (reset! move-up? pressed?)) + "key-t" (fn [_ pressed?] (reset! move-down? pressed?)) + "key-f" (fn [_ pressed?] (reset! move-left? pressed?)) + "key-g" (fn [_ pressed?] (reset! move-right? pressed?)) + "key-v" (fn [_ pressed?] (reset! roll-left? pressed?)) + "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))}) + + (fn [world] + (light-up-everything world) + (enable-debug world) + (set-gravity world (Vector3f. 0 0 0)) + ) + + (fn [world _] + (if (zero? (rem (swap! timer inc) 100)) + (do + ;; (println-repl @timer) + (.attachChild (.getRootNode world) + (sphere 0.05 :color ColorRGBA/Yellow + :position (.getWorldTranslation top) + :physical? false)))) + (if @move-up? + (.applyTorque control + (.mult (.getPhysicsRotation control) + (Vector3f. 0 0 10)))) + (if @move-down? + (.applyTorque control + (.mult (.getPhysicsRotation control) + (Vector3f. 0 0 -10)))) + (if @move-left? + (.applyTorque control + (.mult (.getPhysicsRotation control) + (Vector3f. 0 10 0)))) + (if @move-right? + (.applyTorque control + (.mult (.getPhysicsRotation control) + (Vector3f. 0 -10 0)))) + (if @roll-left? + (.applyTorque control + (.mult (.getPhysicsRotation control) + (Vector3f. -1 0 0)))) + (if @roll-right? + (.applyTorque control + (.mult (.getPhysicsRotation control) + (Vector3f. 1 0 0)))))))) +#+end_src + + +* COMMENT purgatory +#+begin_src clojure (defn bullet-trans [] (let [obj-a (sphere 0.5 :color ColorRGBA/Red :position (Vector3f. -10 5 0)) @@ -233,366 +529,10 @@ ) )) - - - - - - - - -(defn world-setup [joint] - (let [top (doto - (sphere 0.1 :physical? false :color ColorRGBA/Yellow - :position (Vector3f. 0 7 0)) - (.addControl - (RigidBodyControl. - (CapsuleCollisionShape. 0.5 1.5 1) (float 15)))) - bottom (doto - (sphere 0.1 :physical? false :color ColorRGBA/DarkGray - :position (Vector3f. 0 -1 0)) - (.addControl - (RigidBodyControl. - (CapsuleCollisionShape. 0.5 1.5 1) (float 0)))) - table (box 10 2 10 :position (Vector3f. 0 -6 0) - :color ColorRGBA/Gray :mass 0) - a (.getControl top RigidBodyControl) - b (.getControl bottom RigidBodyControl)] - (cond - (= joint :point) - (doto - (Point2PointJoint. a b - (Vector3f. 0 -2 0) - (Vector3f. 0 2 0)) - (.setCollisionBetweenLinkedBodys false)) - (= joint :hinge) - (doto - (HingeJoint. - a b - (Vector3f. 0 -2 0) - (Vector3f. 0 2 0) - (Vector3f. 0 0 1) - (Vector3f. 0 0 1) - - ) - (.setCollisionBetweenLinkedBodys false) - ;;(.setLimit (- Math/PI) Math/PI) - ) - (= joint :cone) - ;; note to self -- jbullet does NOT implement cone joints - ;; correctly. You must use plain ol' bullet for this to work. - ;; It's faster anyway, so whatever. - - (doto (ConeJoint. - a b - (Vector3f. 0 -5 0) - (Vector3f. 0 2 0) - - (doto (Matrix3f.) - (.fromStartEndVectors Vector3f/UNIT_X - Vector3f/UNIT_Y)) - (doto (Matrix3f.) - (.fromStartEndVectors Vector3f/UNIT_X - Vector3f/UNIT_Y)) - ) - ;;(.setAngularOnly true) - - (.setCollisionBetweenLinkedBodys false) - (.setLimit (* 1 (/ Math/PI 4)) - (* 1 (/ Math/PI 4)) - (* 0 (/ Math/PI 4))) - - ) - (= joint :six) - (doto - (SixDofJoint. - a b - (Vector3f. 0 -2 0) - (Vector3f. 0 2 0) - ;;(doto (Matrix3f.) - ;; (.fromStartEndVectors Vector3f/UNIT_X - ;; Vector3f/UNIT_Y)) - ;;(doto (Matrix3f.) - ;; (.fromStartEndVectors Vector3f/UNIT_X - ;; Vector3f/UNIT_Y)) - true) - (.setCollisionBetweenLinkedBodys false) - (.setAngularLowerLimit (Vector3f. 0 - (- (/ Math/PI 2)) - 0)) - - (.setAngularUpperLimit (Vector3f. 0 - (/ Math/PI 2) - 0)) - (.setLinearLowerLimit (Vector3f. 0 0 0)) - (.setLinearUpperLimit (Vector3f. 0 0 0)) - - ) - - - - - - ) - - [top bottom table])) - -(defn speed-up [world] - (.setMoveSpeed (.getFlyByCamera world) - (float 100)) - (.setRotationSpeed (.getFlyByCamera world) - (float 20)) - world) - - -(defn test-joint [joint] - (let [[top bottom floor] (world-setup joint) - control (.getControl top RigidBodyControl) - move-up? (atom false) - move-down? (atom false) - move-left? (atom false) - move-right? (atom false) - roll-left? (atom false) - roll-right? (atom false) - timer (atom 0)] - - (world - (nodify [top bottom floor]) - (merge standard-debug-controls - {"key-r" (fn [_ pressed?] (reset! move-up? pressed?)) - "key-t" (fn [_ pressed?] (reset! move-down? pressed?)) - "key-f" (fn [_ pressed?] (reset! move-left? pressed?)) - "key-g" (fn [_ pressed?] (reset! move-right? pressed?)) - "key-v" (fn [_ pressed?] (reset! roll-left? pressed?)) - "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))}) - - (fn [world] - (light-up-everything world) - (enable-debug world) - (set-gravity world (Vector3f. 0 0 0)) - ) - - (fn [world _] - (if (zero? (rem (swap! timer inc) 100)) - (do - ;; (println-repl @timer) - (.attachChild (.getRootNode world) - (sphere 0.05 :color ColorRGBA/Yellow - :position (.getWorldTranslation top) - :physical? false)))) - (if @move-up? - (.applyTorque control - (.mult (.getPhysicsRotation control) - (Vector3f. 0 0 10)))) - (if @move-down? - (.applyTorque control - (.mult (.getPhysicsRotation control) - (Vector3f. 0 0 -10)))) - (if @move-left? - (.applyTorque control - (.mult (.getPhysicsRotation control) - (Vector3f. 0 10 0)))) - (if @move-right? - (.applyTorque control - (.mult (.getPhysicsRotation control) - (Vector3f. 0 -10 0)))) - (if @roll-left? - (.applyTorque control - (.mult (.getPhysicsRotation control) - (Vector3f. -1 0 0)))) - (if @roll-right? - (.applyTorque control - (.mult (.getPhysicsRotation control) - (Vector3f. 1 0 0)))))))) - - - -(defn run [joint] (.start (test-joint joint))) -(defn look [joint] (view (nodify (world-setup joint)))) - -(defn blender-to-jme - "Convert from Blender coordinates to JME coordinates" - [#^Vector3f in] - (Vector3f. (.getX in) - (.getZ in) - (- (.getY in)))) - - -(defn joint-targets - "Return the two closest two objects to the joint object, ordered - from bottom to top according to the joint's rotation." - [#^Node parts #^Node joint] - ;;(println (meta-data joint "joint")) - (.getWorldRotation joint) - (loop [radius (float 0.01)] - (let [results (CollisionResults.)] - (.collideWith - parts - (BoundingBox. (.getWorldTranslation joint) - radius radius radius) - results) - (let [targets - (distinct - (map #(.getGeometry %) results))] - (if (>= (count targets) 2) - (sort-by - #(.getY - (.mult - (.inverse (.getWorldRotation joint)) - (.subtract (.getWorldTranslation %) - (.getWorldTranslation joint)))) - (take 2 targets)) - (recur (float (* radius 2)))))))) - -(defn connect - "here are some examples: - {:type :point} - {:type :hinge :limit [0 (/ Math/PI 2)] :axis (Vector3f. 0 1 0)} - (:axis defaults to (Vector3f. 1 0 0) if not provided for hinge joints) - - {:type :cone :limit-xz 0] - :limit-yz 0] - :twist 0]} -" - ([#^Node obj-a #^Node obj-b #^Node joint] - (let [center-a (.getWorldTranslation obj-a) - center-b (.getWorldTranslation obj-b) - joint-center (.getWorldTranslation joint) - pivot-a (.subtract joint-center center-a) - pivot-b (.subtract joint-center center-b) - control-a (.getControl obj-a RigidBodyControl) - control-b (.getControl obj-b RigidBodyControl)] - ;; A side-effect of creating a joint registers - ;; it with both physics objects which in turn - ;; will register the joint with the physics system - ;; when the simulation is started. - (if-let [constraints - (map-vals - eval - (read-string - (meta-data (first (worm-joints)) "joint")))] - - (let [joint-type (:type constraints)] - (cond (= :point joint-type) - (do - (println-repl "creating POINT joint") - (Point2PointJoint. - control-a - control-b - pivot-a - pivot-b)) - (= :hinge joint-type) - (do - (println-repl "creating HINGE joint") - (let [axis (if-let - [axis (:axis constraints)] - axis - Vector3f/UNIT_X) - [limit-1 limit-2] (:limit constraints) - hinge-axis - (.mult - (.getWorldRotation joint) - (blender-to-jme axis))] - (doto - (HingeJoint. - control-a - control-b - pivot-a - pivot-b - hinge-axis - hinge-axis) - (.setLimit limit-1 limit-2)))) - (= :cone joint-type) - (do - (let [limit-xy (:limit-xz constraints) - limit-yz (:limit-yz constraints) - twist (:twist constraints)] - - (println-repl "creating CONE joint") - (doto - (ConeJoint. - control-a - control-b - pivot-a - pivot-b - (doto (Matrix3f.) - (.fromStartEndVectors - Vector3f/UNIT_X - (.normalize - (.subtract (.getWorldTranslation joint) - (.getWorldTranslation obj-a))))) - (doto (Matrix3f.) - (.fromStartEndVectors - Vector3f/UNIT_X - (.normalize - (.subtract - (.getWorldTranslation obj-b) - (.getWorldTranslation joint)))))) - (.setLimit (float limit-xy) - (float limit-yz) - (float twist))))) - true - (println-repl - "joint-type " joint-type " not recognized"))) - - (println-repl "could not find joint meta-data!"))))) - - - -(defn physical-worm [#^Node pieces joints] - (dorun - (map - (fn [geom] - (let [physics-control - (RigidBodyControl. - (HullCollisionShape. - (.getMesh geom)) - (if-let [mass (meta-data geom "mass")] - (do - (println-repl - "setting mass to " (float mass)) - (float mass)) - (float 1)))] - - (.addControl geom physics-control))) - (filter #(isa? (class %) Geometry ) - (node-seq pieces)))) - - (dorun - (map - (fn [joint] - (let [[obj-a obj-b] - (joint-targets pieces joint)] - (connect obj-a obj-b joint))) - joints)) - pieces) - -(defn the-worm [] - (physical-worm (worm) (worm-joints))) - -(defn test-worm [] - (world - (nodify [(the-worm) - (box 10 2 10 :position (Vector3f. 0 -5 0) - :color ColorRGBA/Gray :mass 0)]) - standard-debug-controls - (comp light-up-everything enable-debug - (fn [world] - (.setTimer world (NanoTimer.)) - (speed-up world) - ;;(set-gravity world (Vector3f. 0 0 0)) - world - )) - no-op)) - #+end_src -#+results: body-1 -: #'cortex.silly/test-try-again - - * COMMENT generate source #+begin_src clojure :tangle ../src/cortex/silly.clj diff -r 1f84f425e05d -r 77b506ac64f3 org/util.org --- a/org/util.org Wed Jan 04 08:36:42 2012 -0700 +++ b/org/util.org Wed Jan 04 20:34:00 2012 -0700 @@ -128,6 +128,16 @@ BulletAppState)) (asset-manager))) +(defn speed-up + "Increase the dismally slow speed of the world's camera." + [world] + (.setMoveSpeed (.getFlyByCamera world) + (float 100)) + (.setRotationSpeed (.getFlyByCamera world) + (float 20)) + world) + + (defn no-logging "Disable all of jMonkeyEngine's logging." []