Mercurial > cortex
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 |