Mercurial > cortex
diff org/body.org @ 203:0e5d5ee5a914
first draft of body.org complete
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Wed, 08 Feb 2012 08:53:12 -0700 |
parents | d5c597a7aed4 |
children | 162b24a82712 |
line wrap: on
line diff
1.1 --- a/org/body.org Wed Feb 08 05:50:15 2012 -0700 1.2 +++ b/org/body.org Wed Feb 08 08:53:12 2012 -0700 1.3 @@ -38,14 +38,22 @@ 1.4 1.5 The main reason that I use eve-style bodies is so that there will be 1.6 correspondence between the AI's vision and the physical presence of 1.7 -its body. 1.8 +its body. Each individual section is simulated by a separate rigid 1.9 +body that corresponds exactly with its visual representation and does 1.10 +not change. Sections are connected by invisible joints that are well 1.11 +supported in jMonkyeEngine. Bullet, the physics backend for 1.12 +jMonkeyEngine, can efficiently simulate hundreds of rigid bodies 1.13 +connected by joints. Sections do not have to stay as one piece 1.14 +forever; they can be dynamically replaced with multiple sections to 1.15 +simulate splitting in two. This could be used to simulate retractable 1.16 +claws or EVE's hands, which could coalece into one object in the 1.17 +movie. 1.18 1.19 * Solidifying the Body 1.20 1.21 Here is a hand designed eve-style in blender. 1.22 1.23 - 1.24 -#+attr_html: width="500" 1.25 +#+attr_html: width="755" 1.26 [[../images/hand-screenshot0.png]] 1.27 1.28 If we load it directly into jMonkeyEngine, we get this: 1.29 @@ -92,10 +100,16 @@ 1.30 #+end_src 1.31 1.32 #+begin_html 1.33 -<video controls="controls" width="755"> 1.34 +<div class="figure"> 1.35 +<center> 1.36 +<video controls="controls" width="640"> 1.37 <source src="../video/ghost-hand.ogg" type="video/ogg" 1.38 preload="none" poster="../images/aurellem-1280x480.png" /> 1.39 </video> 1.40 +</center> 1.41 +<p>The hand model directly loaded from blender. It has no physical 1.42 + presense in the simulation. </p> 1.43 +</div> 1.44 #+end_html 1.45 1.46 You will notice that the hand has no physical presence -- it's a 1.47 @@ -106,7 +120,7 @@ 1.48 specify the mass of each object in blender and construct the physics 1.49 shape based on the mesh in jMonkeyEngine. 1.50 1.51 -#+name: joints-1 1.52 +#+name: body-1 1.53 #+begin_src clojure 1.54 (defn physical! 1.55 "Iterate through the nodes in creature and make them real physical 1.56 @@ -134,6 +148,7 @@ 1.57 CollisionShapes for each geometry with the mass specified in that 1.58 geometry's meta-data. 1.59 1.60 +#+name: test-1 1.61 #+begin_src clojure 1.62 (in-ns 'cortex.test.body) 1.63 1.64 @@ -160,10 +175,16 @@ 1.65 #+end_src 1.66 1.67 #+begin_html 1.68 -<video controls="controls" width="755"> 1.69 +<div class="figure"> 1.70 +<center> 1.71 +<video controls="controls" width="640"> 1.72 <source src="../video/crumbly-hand.ogg" type="video/ogg" 1.73 preload="none" poster="../images/aurellem-1280x480.png" /> 1.74 </video> 1.75 +</center> 1.76 +<p>The hand now has a physical presence, but there is nothing to hold 1.77 +it together.</p> 1.78 +</div> 1.79 #+end_html 1.80 1.81 Now that's some progress. 1.82 @@ -188,12 +209,44 @@ 1.83 has the name "joints". Their orientation and meta-data determine what 1.84 joint is created. 1.85 1.86 +#+attr_html: width="755" 1.87 +#+caption: joints hack in blender. Each empty node here will be transformed into a joint in jMonkeyEngine 1.88 [[../images/hand-screenshot1.png]] 1.89 1.90 +The empty node in the upper right, highlighted in yellow, is the 1.91 +parent node of all the emptys which represent joints. The following 1.92 +functions must do three things to translate these into real joints: 1.93 1.94 + - Find the children of the "joints" node. 1.95 + - Determine the two spatials the joint it meant to connect. 1.96 + - Create the joint based on the meta-data of the empty node. 1.97 1.98 +** Finding the Joints 1.99 +#+name: joints-2 1.100 +#+begin_src clojure 1.101 +(defvar 1.102 + ^{:arglists '([creature])} 1.103 + joints 1.104 + (sense-nodes "joints") 1.105 + "Return the children of the creature's \"joints\" node.") 1.106 +#+end_src 1.107 1.108 -#+name: joints-2 1.109 +The higher order function =(sense-nodes)= from cortex.sense makes our 1.110 +first task very easy. 1.111 + 1.112 +** Joint Targets and Orientation 1.113 + 1.114 +This technique for finding a joint's targets is very similiar to 1.115 +=(cortex.sense/closest-node)=. A small cube, centered around the 1.116 +empty-node, grows exponentially until it intersects two /physical/ 1.117 +objects. The objects are ordered according to the joint's rotation, 1.118 +with the first one being the object that has more negative coordinates 1.119 +in the joint's reference frame. Since the objects must be physical, 1.120 +the empty-node itself escapes detection. Because the objects must be 1.121 +physical, =(joint-targets)= must be called /after/ =(physical!)= is 1.122 +called. 1.123 + 1.124 +#+name: joints-3 1.125 #+begin_src clojure 1.126 (defn joint-targets 1.127 "Return the two closest two objects to the joint object, ordered 1.128 @@ -222,7 +275,16 @@ 1.129 v)) 1.130 (take 2 targets)) 1.131 (recur (float (* radius 2)))))))) 1.132 +#+end_src 1.133 1.134 +** Generating Joints 1.135 + 1.136 +This long chunk of code iterates through all the different ways of 1.137 +specifying joints using blender meta-data and converts each one to the 1.138 +appropriate jMonkyeEngine joint. 1.139 + 1.140 +#+name: joints-4 1.141 +#+begin_src clojure 1.142 (defmulti joint-dispatch 1.143 "Translate blender pseudo-joints into real JME joints." 1.144 (fn [constraints & _] 1.145 @@ -252,12 +314,7 @@ 1.146 pivot-b 1.147 false) 1.148 (.setLinearLowerLimit Vector3f/ZERO) 1.149 - (.setLinearUpperLimit Vector3f/ZERO) 1.150 - ;;(.setAngularLowerLimit (Vector3f. 1 1 1)) 1.151 - ;;(.setAngularUpperLimit (Vector3f. 0 0 0)) 1.152 - 1.153 -)) 1.154 - 1.155 + (.setLinearUpperLimit Vector3f/ZERO))) 1.156 1.157 (defmethod joint-dispatch :hinge 1.158 [constraints control-a control-b pivot-a pivot-b rotation] 1.159 @@ -345,13 +402,12 @@ 1.160 pivot-a pivot-b 1.161 joint-rotation)) 1.162 (println-repl "could not find joint meta-data!")))) 1.163 +#+end_src 1.164 1.165 -(defvar 1.166 - ^{:arglists '([creature])} 1.167 - joints 1.168 - (sense-nodes "joints") 1.169 - "Return the children of the creature's \"joints\" node.") 1.170 +Creating joints is now a matter applying =(connect)= to each joint 1.171 +node. 1.172 1.173 +#+begin_src clojure 1.174 (defn joints! 1.175 "Connect the solid parts of the creature with physical joints. The 1.176 joints are taken from the \"joints\" node in the creature." 1.177 @@ -362,7 +418,66 @@ 1.178 (let [[obj-a obj-b] (joint-targets creature joint)] 1.179 (connect obj-a obj-b joint))) 1.180 (joints creature)))) 1.181 +#+end_src 1.182 1.183 + 1.184 +** Round 3 1.185 + 1.186 +Now we can test the hand in all its glory. 1.187 + 1.188 +#+begin_src clojure 1.189 +(in-ns 'cortex.test.body) 1.190 + 1.191 +(def debug-control 1.192 + {"key-h" (fn [world val] 1.193 + (if val (enable-debug world))) 1.194 + 1.195 + "key-u" (fn [world _] (set-gravity world Vector3f/ZERO)) 1.196 + }) 1.197 + 1.198 +(defn test-three [] 1.199 + (world (nodify 1.200 + [(doto (hand) 1.201 + (physical!) 1.202 + (joints!) ) 1.203 + (floor)]) 1.204 + (merge standard-debug-controls debug-control 1.205 + normal-gravity) 1.206 + (comp 1.207 + #(Capture/captureVideo 1.208 + % (File. "/home/r/proj/cortex/render/body/3")) 1.209 + #(do (set-gravity % Vector3f/ZERO) %) 1.210 + setup) 1.211 + no-op)) 1.212 +#+end_src 1.213 + 1.214 +=(physical!)= makes the hand solid, then =(joints!)= connects each 1.215 +piece together. 1.216 + 1.217 + 1.218 +#+begin_html 1.219 +<div class="figure"> 1.220 +<center> 1.221 +<video controls="controls" width="640"> 1.222 + <source src="../video/full-hand.ogg" type="video/ogg" 1.223 + preload="none" poster="../images/aurellem-1280x480.png" /> 1.224 +</video> 1.225 +</center> 1.226 +<p>Now the hand is physical and has joints.</p> 1.227 +</div> 1.228 +#+end_html 1.229 + 1.230 +The joints are visualized as green connections between each segment 1.231 +for debug purposes. You can see that they correspond to the empty 1.232 +nodes in the blender file. 1.233 + 1.234 +* Wrap-Up! 1.235 + 1.236 +It is convienent to combine =(physical!)= and =(joints!)= into one 1.237 +function that completely creates the creature's physical body. 1.238 + 1.239 +#+name: joints-4 1.240 +#+begin_src clojure 1.241 (defn body! 1.242 "Endow the creature with a physical body connected with joints. The 1.243 particulars of the joints and the masses of each pody part are 1.244 @@ -374,6 +489,8 @@ 1.245 1.246 * Bookkeeping 1.247 1.248 +Header; here for completeness. 1.249 + 1.250 #+name: body-0 1.251 #+begin_src clojure 1.252 (ns cortex.body 1.253 @@ -397,6 +514,11 @@ 1.254 1.255 * Source 1.256 1.257 +Dylan -- I'll fill these in later 1.258 +- cortex.body 1.259 +- cortex.test.body 1.260 +- blender files 1.261 + 1.262 * COMMENT Examples 1.263 1.264 #+name: test-body