# HG changeset patch # User Robert McIntyre # Date 1328276825 25200 # Node ID 33278bf028e7c922ee388ffde1e06284776141de # Parent 75b6c2ebbf8e64fb7ec5ed9210e80d0082773f6b refactored joints diff -r 75b6c2ebbf8e -r 33278bf028e7 org/body.org --- a/org/body.org Fri Feb 03 06:41:16 2012 -0700 +++ b/org/body.org Fri Feb 03 06:47:05 2012 -0700 @@ -9,7 +9,7 @@ #+name: proprioception #+begin_src clojure (ns cortex.body - (:use (cortex world util)) + (:use (cortex world util sense)) (:import com.jme3.math.Vector3f com.jme3.math.Quaternion @@ -20,6 +20,8 @@ com.jme3.bounding.BoundingBox com.jme3.scene.Node)) +(cortex.import/mega-import-jme3) + (defn jme-to-blender "Convert from JME coordinates to Blender coordinates" [#^Vector3f in] @@ -27,6 +29,14 @@ (- (.getZ in)) (.getY in))) +(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." @@ -62,61 +72,160 @@ (seq (.getChildren joint-node)) (do (println-repl "could not find JOINTS node") []))) -(defn tap [obj direction force] - (let [control (.getControl obj RigidBodyControl)] - (.applyTorque - control - (.mult (.getPhysicsRotation control) - (.mult (.normalize direction) (float force)))))) +(defmulti joint-dispatch + "Translate blender pseudo-joints into real JME joints." + (fn [constraints & _] + (:type constraints))) +(defmethod joint-dispatch :point + [constraints control-a control-b pivot-a pivot-b rotation] + (println-repl "creating POINT2POINT joint") + ;; bullet's point2point joints are BROKEN, so we must use the + ;; generic 6DOF joint instead of an actual Point2Point joint! -(defn with-movement - [object - [up down left right roll-up roll-down :as keyboard] - forces - [root-node - keymap - intilization - world-loop]] - (let [add-keypress - (fn [state keymap key] - (merge keymap - {key - (fn [_ pressed?] - (reset! state pressed?))})) - move-up? (atom false) - move-down? (atom false) - move-left? (atom false) - move-right? (atom false) - roll-left? (atom false) - roll-right? (atom false) - - directions [(Vector3f. 0 1 0)(Vector3f. 0 -1 0) - (Vector3f. 0 0 1)(Vector3f. 0 0 -1) - (Vector3f. -1 0 0)(Vector3f. 1 0 0)] - atoms [move-left? move-right? move-up? move-down? - roll-left? roll-right?] + ;; should be able to do this: + (comment + (Point2PointJoint. + control-a + control-b + pivot-a + pivot-b)) - keymap* (reduce merge - (map #(add-keypress %1 keymap %2) - atoms - keyboard)) - - splice-loop (fn [] - (dorun - (map - (fn [sym direction force] - (if @sym - (tap object direction force))) - atoms directions forces))) + ;; but instead we must do this: + (println-repl "substuting 6DOF joint for POINT2POINT joint!") + (doto + (SixDofJoint. + control-a + control-b + pivot-a + pivot-b + false) + (.setLinearLowerLimit Vector3f/ZERO) + (.setLinearUpperLimit Vector3f/ZERO) + ;;(.setAngularLowerLimit (Vector3f. 1 1 1)) + ;;(.setAngularUpperLimit (Vector3f. 0 0 0)) - world-loop* (fn [world tpf] - (world-loop world tpf) - (splice-loop))] - [root-node - keymap* - intilization - world-loop*])) +)) + + +(defmethod joint-dispatch :hinge + [constraints control-a control-b pivot-a pivot-b rotation] + (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 + rotation + (blender-to-jme axis))] + (doto + (HingeJoint. + control-a + control-b + pivot-a + pivot-b + hinge-axis + hinge-axis) + (.setLimit limit-1 limit-2)))) + +(defmethod joint-dispatch :cone + [constraints control-a control-b pivot-a pivot-b rotation] + (let [limit-xz (:limit-xz constraints) + limit-xy (:limit-xy constraints) + twist (:twist constraints)] + + (println-repl "creating CONE joint") + (println-repl rotation) + (println-repl + "UNIT_X --> " (.mult rotation (Vector3f. 1 0 0))) + (println-repl + "UNIT_Y --> " (.mult rotation (Vector3f. 0 1 0))) + (println-repl + "UNIT_Z --> " (.mult rotation (Vector3f. 0 0 1))) + (doto + (ConeJoint. + control-a + control-b + pivot-a + pivot-b + rotation + rotation) + (.setLimit (float limit-xz) + (float limit-xy) + (float twist))))) + +(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-xy 0] + :twist 0]} (use XZY rotation mode in blender!)" + [#^Node obj-a #^Node obj-b #^Node joint] + (let [control-a (.getControl obj-a RigidBodyControl) + control-b (.getControl obj-b RigidBodyControl) + joint-center (.getWorldTranslation joint) + joint-rotation (.toRotationMatrix (.getWorldRotation joint)) + pivot-a (world-to-local obj-a joint-center) + pivot-b (world-to-local obj-b joint-center)] + + (if-let [constraints + (map-vals + eval + (read-string + (meta-data joint "joint")))] + ;; 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. + (do + (println-repl "creating joint between" + (.getName obj-a) "and" (.getName obj-b)) + (joint-dispatch constraints + control-a control-b + pivot-a pivot-b + joint-rotation)) + (println-repl "could not find joint meta-data!")))) + + + + +(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) + + +;; TODO implement a function that adds joints in the style of the +;; other sense functions + + (import java.awt.image.BufferedImage) diff -r 75b6c2ebbf8e -r 33278bf028e7 org/test-creature.org --- a/org/test-creature.org Fri Feb 03 06:41:16 2012 -0700 +++ b/org/test-creature.org Fri Feb 03 06:47:05 2012 -0700 @@ -71,164 +71,14 @@ (.registerLoader BlenderModelLoader (into-array String ["blend"]))) model)) -(defn blender-to-jme - "Convert from Blender coordinates to JME coordinates" - [#^Vector3f in] - (Vector3f. (.getX in) - (.getZ in) - (- (.getY in)))) +(declare blender-creature) - -(defmulti joint-dispatch - "Translate blender pseudo-joints into real JME joints." - (fn [constraints & _] - (:type constraints))) - -(defmethod joint-dispatch :point - [constraints control-a control-b pivot-a pivot-b rotation] - (println-repl "creating POINT2POINT joint") - ;; bullet's point2point joints are BROKEN, so we must use the - ;; generic 6DOF joint instead of an actual Point2Point joint! - - ;; should be able to do this: - (comment - (Point2PointJoint. - control-a - control-b - pivot-a - pivot-b)) - - ;; but instead we must do this: - (println-repl "substuting 6DOF joint for POINT2POINT joint!") - (doto - (SixDofJoint. - control-a - control-b - pivot-a - pivot-b - false) - (.setLinearLowerLimit Vector3f/ZERO) - (.setLinearUpperLimit Vector3f/ZERO) - ;;(.setAngularLowerLimit (Vector3f. 1 1 1)) - ;;(.setAngularUpperLimit (Vector3f. 0 0 0)) - -)) - - -(defmethod joint-dispatch :hinge - [constraints control-a control-b pivot-a pivot-b rotation] - (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 - rotation - (blender-to-jme axis))] - (doto - (HingeJoint. - control-a - control-b - pivot-a - pivot-b - hinge-axis - hinge-axis) - (.setLimit limit-1 limit-2)))) - -(defmethod joint-dispatch :cone - [constraints control-a control-b pivot-a pivot-b rotation] - (let [limit-xz (:limit-xz constraints) - limit-xy (:limit-xy constraints) - twist (:twist constraints)] - - (println-repl "creating CONE joint") - (println-repl rotation) - (println-repl - "UNIT_X --> " (.mult rotation (Vector3f. 1 0 0))) - (println-repl - "UNIT_Y --> " (.mult rotation (Vector3f. 0 1 0))) - (println-repl - "UNIT_Z --> " (.mult rotation (Vector3f. 0 0 1))) - (doto - (ConeJoint. - control-a - control-b - pivot-a - pivot-b - rotation - rotation) - (.setLimit (float limit-xz) - (float limit-xy) - (float twist))))) - -(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-xy 0] - :twist 0]} (use XZY rotation mode in blender!)" - [#^Node obj-a #^Node obj-b #^Node joint] - (let [control-a (.getControl obj-a RigidBodyControl) - control-b (.getControl obj-b RigidBodyControl) - joint-center (.getWorldTranslation joint) - joint-rotation (.toRotationMatrix (.getWorldRotation joint)) - pivot-a (world-to-local obj-a joint-center) - pivot-b (world-to-local obj-b joint-center)] - - (if-let [constraints - (map-vals - eval - (read-string - (meta-data joint "joint")))] - ;; 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. - (do - (println-repl "creating joint between" - (.getName obj-a) "and" (.getName obj-b)) - (joint-dispatch constraints - control-a control-b - pivot-a pivot-b - joint-rotation)) - (println-repl "could not find joint meta-data!")))) - - - - -(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) - -(declare blender-creature) +(defn blender-creature + "Return a creature with all joints in place." + [blender-path] + (let [model (load-blender-model blender-path) + joints (creature-joints model)] + (assemble-creature model joints))) (def hand "Models/creature1/one.blend") @@ -271,12 +121,6 @@ -(defn blender-creature - "Return a creature with all joints in place." - [blender-path] - (let [model (load-blender-model blender-path) - joints (creature-joints model)] - (assemble-creature model joints))) (defn gray-scale [num] (+ num diff -r 75b6c2ebbf8e -r 33278bf028e7 org/util.org --- a/org/util.org Fri Feb 03 06:41:16 2012 -0700 +++ b/org/util.org Fri Feb 03 06:47:05 2012 -0700 @@ -398,6 +398,62 @@ {"key-space" (fire-cannon-ball)}) +(defn tap [obj direction force] + (let [control (.getControl obj RigidBodyControl)] + (.applyTorque + control + (.mult (.getPhysicsRotation control) + (.mult (.normalize direction) (float force)))))) + + +(defn with-movement + [object + [up down left right roll-up roll-down :as keyboard] + forces + [root-node + keymap + intilization + world-loop]] + (let [add-keypress + (fn [state keymap key] + (merge keymap + {key + (fn [_ pressed?] + (reset! state pressed?))})) + move-up? (atom false) + move-down? (atom false) + move-left? (atom false) + move-right? (atom false) + roll-left? (atom false) + roll-right? (atom false) + + directions [(Vector3f. 0 1 0)(Vector3f. 0 -1 0) + (Vector3f. 0 0 1)(Vector3f. 0 0 -1) + (Vector3f. -1 0 0)(Vector3f. 1 0 0)] + atoms [move-left? move-right? move-up? move-down? + roll-left? roll-right?] + + keymap* (reduce merge + (map #(add-keypress %1 keymap %2) + atoms + keyboard)) + + splice-loop (fn [] + (dorun + (map + (fn [sym direction force] + (if @sym + (tap object direction force))) + atoms directions forces))) + + world-loop* (fn [world tpf] + (world-loop world tpf) + (splice-loop))] + [root-node + keymap* + intilization + world-loop*])) + #+end_src