comparison org/body.org @ 209:e49c690d2bcf

minor edits.
author Robert McIntyre <rlm@mit.edu>
date Thu, 09 Feb 2012 05:02:21 -0700
parents bb3b75bf1664
children 384ed3437948
comparison
equal deleted inserted replaced
208:30bd811c5dcb 209:e49c690d2bcf
45 invisible joints that are well supported in jMonkyeEngine. Bullet, the 45 invisible joints that are well supported in jMonkyeEngine. Bullet, the
46 physics backend for jMonkeyEngine, can efficiently simulate hundreds 46 physics backend for jMonkeyEngine, can efficiently simulate hundreds
47 of rigid bodies connected by joints. Sections do not have to stay as 47 of rigid bodies connected by joints. Sections do not have to stay as
48 one piece forever; they can be dynamically replaced with multiple 48 one piece forever; they can be dynamically replaced with multiple
49 sections to simulate splitting in two. This could be used to simulate 49 sections to simulate splitting in two. This could be used to simulate
50 retractable claws or EVE's hands, which could coalece into one object 50 retractable claws or EVE's hands, which are able to coalece into one
51 in the movie. 51 object in the movie.
52 52
53 * Solidifying the Body 53 * Solidifying the Body
54 54
55 Here is a hand designed eve-style in blender. 55 Here is a hand designed eve-style in blender.
56 56
110 You will notice that the hand has no physical presence -- it's a 110 You will notice that the hand has no physical presence -- it's a
111 hologram through which everything passes. Therefore, the first thing 111 hologram through which everything passes. Therefore, the first thing
112 to do is to make it solid. Blender has physics simulation on par with 112 to do is to make it solid. Blender has physics simulation on par with
113 jMonkeyEngine (they both use bullet as their physics backend), but it 113 jMonkeyEngine (they both use bullet as their physics backend), but it
114 can be difficult to translate between the two systems, so for now I 114 can be difficult to translate between the two systems, so for now I
115 specify the mass of each object in blender and construct the physics 115 specify the mass of each object as meta-data in blender and construct
116 shape based on the mesh in jMonkeyEngine. 116 the physics shape based on the mesh in jMonkeyEngine.
117 117
118 #+name: body-1 118 #+name: body-1
119 #+begin_src clojure 119 #+begin_src clojure
120 (defn physical! 120 (defn physical!
121 "Iterate through the nodes in creature and make them real physical 121 "Iterate through the nodes in creature and make them real physical
145 145
146 #+name: test-2 146 #+name: test-2
147 #+begin_src clojure 147 #+begin_src clojure
148 (in-ns 'cortex.test.body) 148 (in-ns 'cortex.test.body)
149 149
150 (def normal-gravity 150 (def gravity-control
151 {"key-g" (fn [world _] 151 {"key-g" (fn [world _]
152 (set-gravity world (Vector3f. 0 -9.81 0)))}) 152 (set-gravity world (Vector3f. 0 -9.81 0)))
153 "key-u" (fn [world _] (set-gravity world Vector3f/ZERO))})
154
153 155
154 (defn floor [] 156 (defn floor []
155 (box 10 3 10 :position (Vector3f. 0 -10 0) 157 (box 10 3 10 :position (Vector3f. 0 -10 0)
156 :color ColorRGBA/Gray :mass 0)) 158 :color ColorRGBA/Gray :mass 0))
157 159
158 (defn test-two [] 160 (defn test-two []
159 (world (nodify 161 (world (nodify
160 [(doto (hand) 162 [(doto (hand)
161 (physical!)) 163 (physical!))
162 (floor)]) 164 (floor)])
163 (merge standard-debug-controls normal-gravity) 165 (merge standard-debug-controls gravity-control)
164 (comp 166 (comp
165 #(Capture/captureVideo 167 #(Capture/captureVideo
166 % (File. "/home/r/proj/cortex/render/body/2")) 168 % (File. "/home/r/proj/cortex/render/body/2"))
167 #(do (set-gravity % Vector3f/ZERO) %) 169 #(do (set-gravity % Vector3f/ZERO) %)
168 setup) 170 setup)
184 186
185 Now that's some progress. 187 Now that's some progress.
186 188
187 * Joints 189 * Joints
188 190
189 Obviously, an AI is not going to be doing much just lying in pieces on 191 Obviously, an AI is not going to be doing much while lying in pieces
190 the floor. So, the next step to making a proper body is to connect 192 on the floor. So, the next step to making a proper body is to connect
191 those pieces together with joints. jMonkeyEngine has a large array of 193 those pieces together with joints. jMonkeyEngine has a large array of
192 joints available via bullet, such as Point2Point, Cone, Hinge, and a 194 joints available via bullet, such as Point2Point, Cone, Hinge, and a
193 generic Six Degree of Freedom joint, with or without spring 195 generic Six Degree of Freedom joint, with or without spring
194 restitution. 196 restitution.
195 197
202 some senses. Each joint is specified by an empty node whose parent 204 some senses. Each joint is specified by an empty node whose parent
203 has the name "joints". Their orientation and meta-data determine what 205 has the name "joints". Their orientation and meta-data determine what
204 joint is created. 206 joint is created.
205 207
206 #+attr_html: width="755" 208 #+attr_html: width="755"
207 #+caption: joints hack in blender. Each empty node here will be transformed into a joint in jMonkeyEngine 209 #+caption: Joints hack in blender. Each empty node here will be transformed into a joint in jMonkeyEngine
208 [[../images/hand-screenshot1.png]] 210 [[../images/hand-screenshot1.png]]
209 211
210 The empty node in the upper right, highlighted in yellow, is the 212 The empty node in the upper right, highlighted in yellow, is the
211 parent node of all the emptys which represent joints. The following 213 parent node of all the emptys which represent joints. The following
212 functions must do three things to translate these into real joints: 214 functions must do three things to translate these into real joints:
214 - Find the children of the "joints" node. 216 - Find the children of the "joints" node.
215 - Determine the two spatials the joint it meant to connect. 217 - Determine the two spatials the joint it meant to connect.
216 - Create the joint based on the meta-data of the empty node. 218 - Create the joint based on the meta-data of the empty node.
217 219
218 ** Finding the Joints 220 ** Finding the Joints
221
222 The higher order function =(sense-nodes)= from =cortex.sense= simplifies
223 the first task.
224
219 #+name: joints-2 225 #+name: joints-2
220 #+begin_src clojure 226 #+begin_src clojure
221 (defvar 227 (defvar
222 ^{:arglists '([creature])} 228 ^{:arglists '([creature])}
223 joints 229 joints
224 (sense-nodes "joints") 230 (sense-nodes "joints")
225 "Return the children of the creature's \"joints\" node.") 231 "Return the children of the creature's \"joints\" node.")
226 #+end_src 232 #+end_src
227 233
228 The higher order function =(sense-nodes)= from cortex.sense makes our
229 first task very easy.
230 234
231 ** Joint Targets and Orientation 235 ** Joint Targets and Orientation
232 236
233 This technique for finding a joint's targets is very similiar to 237 This technique for finding a joint's targets is very similiar to
234 =(cortex.sense/closest-node)=. A small cube, centered around the 238 =(cortex.sense/closest-node)=. A small cube, centered around the
249 (loop [radius (float 0.01)] 253 (loop [radius (float 0.01)]
250 (let [results (CollisionResults.)] 254 (let [results (CollisionResults.)]
251 (.collideWith 255 (.collideWith
252 parts 256 parts
253 (BoundingBox. (.getWorldTranslation joint) 257 (BoundingBox. (.getWorldTranslation joint)
254 radius radius radius) 258 radius radius radius) results)
255 results)
256 (let [targets 259 (let [targets
257 (distinct 260 (distinct
258 (map #(.getGeometry %) results))] 261 (map #(.getGeometry %) results))]
259 (if (>= (count targets) 2) 262 (if (>= (count targets) 2)
260 (sort-by 263 (sort-by
261 #(let [v 264 #(let [joint-ref-frame-position
262 (jme-to-blender 265 (jme-to-blender
263 (.mult 266 (.mult
264 (.inverse (.getWorldRotation joint)) 267 (.inverse (.getWorldRotation joint))
265 (.subtract (.getWorldTranslation %) 268 (.subtract (.getWorldTranslation %)
266 (.getWorldTranslation joint))))] 269 (.getWorldTranslation joint))))]
267 (println-repl (.getName %) ":" v) 270 (.dot (Vector3f. 1 1 1) joint-ref-frame-position))
268 (.dot (Vector3f. 1 1 1)
269 v))
270 (take 2 targets)) 271 (take 2 targets))
271 (recur (float (* radius 2)))))))) 272 (recur (float (* radius 2))))))))
272 #+end_src 273 #+end_src
273 274
274 ** Generating Joints 275 ** Generating Joints
275 276
276 This long chunk of code iterates through all the different ways of 277 This section of code iterates through all the different ways of
277 specifying joints using blender meta-data and converts each one to the 278 specifying joints using blender meta-data and converts each one to the
278 appropriate jMonkyeEngine joint. 279 appropriate jMonkyeEngine joint.
279 280
280 #+name: joints-4 281 #+name: joints-4
281 #+begin_src clojure 282 #+begin_src clojure
396 pivot-a pivot-b 397 pivot-a pivot-b
397 joint-rotation)) 398 joint-rotation))
398 (println-repl "could not find joint meta-data!")))) 399 (println-repl "could not find joint meta-data!"))))
399 #+end_src 400 #+end_src
400 401
401 Creating joints is now a matter applying =(connect)= to each joint 402 Creating joints is now a matter of applying =(connect)= to each joint
402 node. 403 node.
403 404
404 #+name: joints-5 405 #+name: joints-5
405 #+begin_src clojure 406 #+begin_src clojure
406 (defn joints! 407 (defn joints!
424 #+begin_src clojure 425 #+begin_src clojure
425 (in-ns 'cortex.test.body) 426 (in-ns 'cortex.test.body)
426 427
427 (def debug-control 428 (def debug-control
428 {"key-h" (fn [world val] 429 {"key-h" (fn [world val]
429 (if val (enable-debug world))) 430 (if val (enable-debug world)))})
430 "key-u" (fn [world _] (set-gravity world Vector3f/ZERO))})
431 431
432 (defn test-three [] 432 (defn test-three []
433 (world (nodify 433 (world (nodify
434 [(doto (hand) 434 [(doto (hand)
435 (physical!) 435 (physical!)
436 (joints!)) 436 (joints!))
437 (floor)]) 437 (floor)])
438 (merge standard-debug-controls debug-control 438 (merge standard-debug-controls debug-control
439 normal-gravity) 439 gravity-control)
440 (comp 440 (comp
441 #(Capture/captureVideo 441 #(Capture/captureVideo
442 % (File. "/home/r/proj/cortex/render/body/3")) 442 % (File. "/home/r/proj/cortex/render/body/3"))
443 #(do (set-gravity % Vector3f/ZERO) %) 443 #(do (set-gravity % Vector3f/ZERO) %)
444 setup) 444 setup)
522 <p>This worm model will be the platform onto which future senses will 522 <p>This worm model will be the platform onto which future senses will
523 be grafted.</p> 523 be grafted.</p>
524 </div> 524 </div>
525 #+end_html 525 #+end_html
526 526
527 * Bookkeeping 527 * Headers
528
529 Headers; here for completeness.
530
531 #+name: body-header 528 #+name: body-header
532 #+begin_src clojure 529 #+begin_src clojure
533 (ns cortex.body 530 (ns cortex.body
534 "Assemble a physical creature using the definitions found in a 531 "Assemble a physical creature using the definitions found in a
535 specially prepared blender file. Creates rigid bodies and joints so 532 specially prepared blender file. Creates rigid bodies and joints so
561 558
562 * Source 559 * Source
563 - [[../src/cortex/body.clj][cortex.body]] 560 - [[../src/cortex/body.clj][cortex.body]]
564 - [[../src/cortex/test/body.clj][cortex.test.body]] 561 - [[../src/cortex/test/body.clj][cortex.test.body]]
565 - [[../assets/Models/test-creature/hand.blend][hand.blend]] 562 - [[../assets/Models/test-creature/hand.blend][hand.blend]]
563 - [[../assets/Models/test-creature/palm.png][UV-map-1]]
566 - [[../assets/Models/test-creature/worm.blend][worm.blend]] 564 - [[../assets/Models/test-creature/worm.blend][worm.blend]]
567 - [[../assets/Models/test-creature/retina-small.png][UV-map-1]] 565 - [[../assets/Models/test-creature/retina-small.png][UV-map-1]]
568 - [[../assets/Models/test-creature/tip.png][UV-map-2]] 566 - [[../assets/Models/test-creature/tip.png][UV-map-2]]
569 567
570 * COMMENT Generate Source 568 * COMMENT Generate Source