Mercurial > cortex
comparison org/test-creature.org @ 77:1f84f425e05d
first draft of automatic constraints from blender
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Wed, 04 Jan 2012 08:36:42 -0700 |
parents | f4c77512808e |
children | 77b506ac64f3 |
comparison
equal
deleted
inserted
replaced
76:5e75b616ca60 | 77:1f84f425e05d |
---|---|
64 (defn meta-data [blender-node key] | 64 (defn meta-data [blender-node key] |
65 (if-let [data (.getUserData blender-node "properties")] | 65 (if-let [data (.getUserData blender-node "properties")] |
66 (.findValue data key) | 66 (.findValue data key) |
67 nil)) | 67 nil)) |
68 | 68 |
69 (defn hand2 [] | |
70 (load-blender-model "Models/creature1/try-again.blend")) | |
71 | 69 |
72 (defn hand [] | 70 (defn hand [] |
73 (load-blender-model "Models/creature1/one.blend")) | 71 (load-blender-model "Models/creature1/one.blend")) |
74 | 72 |
75 | 73 |
98 | 96 |
99 (defn hand-joints [] | 97 (defn hand-joints [] |
100 (map #(.getWorldTranslation %) | 98 (map #(.getWorldTranslation %) |
101 (filter #(re-matches #"joint\.\d\d\d" (.getName %)) | 99 (filter #(re-matches #"joint\.\d\d\d" (.getName %)) |
102 (node-seq (hand))))) | 100 (node-seq (hand))))) |
101 (defn worm [] | |
102 (load-blender-model "Models/creature1/try-again.blend")) | |
103 | |
103 | 104 |
104 (defn worm-pieces [] | 105 (defn worm-pieces [] |
105 (filter | 106 (filter |
106 (comp #{"worm-2" "worm-1"} | 107 (comp #{"worm-2" "worm-1"} |
107 #(apply str (drop-last (.getName %)))) | 108 #(apply str (drop-last (.getName %)))) |
108 (node-seq (hand2)))) | 109 (node-seq (worm)))) |
109 | 110 |
110 (defn worm-joints [] | 111 (defn worm-joints [] |
111 [Vector3f/ZERO]) | 112 (filter #(re-matches #"joint\.\d\d\d" (.getName %)) |
112 | 113 (node-seq (worm)))) |
113 | 114 |
114 | 115 (defn bullet-trans [] |
115 (defn find-joint | 116 (let [obj-a (sphere 0.5 :color ColorRGBA/Red |
116 [#^Node parts #^Vector3f joint-position] | 117 :position (Vector3f. -10 5 0)) |
118 obj-b (sphere 0.5 :color ColorRGBA/Blue | |
119 :position (Vector3f. -10 -5 0) | |
120 :mass 0) | |
121 control-a (.getControl obj-a RigidBodyControl) | |
122 control-b (.getControl obj-b RigidBodyControl) | |
123 swivel | |
124 (.toRotationMatrix | |
125 (doto (Quaternion.) | |
126 (.fromAngleAxis (/ Math/PI 2) | |
127 Vector3f/UNIT_X)))] | |
128 (doto | |
129 (ConeJoint. | |
130 control-a control-b | |
131 (Vector3f. 0 5 0) | |
132 (Vector3f. 0 -5 0) | |
133 swivel swivel) | |
134 (.setLimit (* 0.6 (/ Math/PI 4)) | |
135 (/ Math/PI 4) | |
136 (* Math/PI 0.8))) | |
137 (world (nodify | |
138 [obj-a obj-b]) | |
139 standard-debug-controls | |
140 enable-debug | |
141 no-op))) | |
142 | |
143 | |
144 (defn bullet-trans* [] | |
145 (let [obj-a (box 1.5 0.5 0.5 :color ColorRGBA/Red | |
146 :position (Vector3f. 5 0 0) | |
147 :mass 90) | |
148 obj-b (sphere 0.5 :color ColorRGBA/Blue | |
149 :position (Vector3f. -5 0 0) | |
150 :mass 0) | |
151 control-a (.getControl obj-a RigidBodyControl) | |
152 control-b (.getControl obj-b RigidBodyControl) | |
153 move-up? (atom nil) | |
154 move-down? (atom nil) | |
155 move-left? (atom nil) | |
156 move-right? (atom nil) | |
157 roll-left? (atom nil) | |
158 roll-right? (atom nil) | |
159 force 100 | |
160 swivel | |
161 (.toRotationMatrix | |
162 (doto (Quaternion.) | |
163 (.fromAngleAxis (/ Math/PI 2) | |
164 Vector3f/UNIT_X))) | |
165 x-move | |
166 (doto (Matrix3f.) | |
167 (.fromStartEndVectors Vector3f/UNIT_X | |
168 (.normalize (Vector3f. 1 1 0)))) | |
169 | |
170 timer (atom 0)] | |
171 (doto | |
172 (ConeJoint. | |
173 control-a control-b | |
174 (Vector3f. -8 0 0) | |
175 (Vector3f. 2 0 0) | |
176 ;;swivel swivel | |
177 ;;Matrix3f/IDENTITY Matrix3f/IDENTITY | |
178 x-move Matrix3f/IDENTITY | |
179 ) | |
180 (.setCollisionBetweenLinkedBodys false) | |
181 (.setLimit (* 1 (/ Math/PI 4)) ;; twist | |
182 (* 1 (/ Math/PI 4)) ;; swing span in X-Y plane | |
183 (* 0 (/ Math/PI 4)))) ;; swing span in Y-Z plane | |
184 (world (nodify | |
185 [obj-a obj-b]) | |
186 (merge standard-debug-controls | |
187 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?)) | |
188 "key-t" (fn [_ pressed?] (reset! move-down? pressed?)) | |
189 "key-f" (fn [_ pressed?] (reset! move-left? pressed?)) | |
190 "key-g" (fn [_ pressed?] (reset! move-right? pressed?)) | |
191 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?)) | |
192 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))}) | |
193 | |
194 (fn [world] | |
195 (enable-debug world) | |
196 (set-gravity world Vector3f/ZERO) | |
197 ) | |
198 | |
199 (fn [world _] | |
200 | |
201 (if @move-up? | |
202 (.applyForce control-a | |
203 (Vector3f. force 0 0) | |
204 (Vector3f. 0 0 0))) | |
205 (if @move-down? | |
206 (.applyForce control-a | |
207 (Vector3f. (- force) 0 0) | |
208 (Vector3f. 0 0 0))) | |
209 (if @move-left? | |
210 (.applyForce control-a | |
211 (Vector3f. 0 force 0) | |
212 (Vector3f. 0 0 0))) | |
213 (if @move-right? | |
214 (.applyForce control-a | |
215 (Vector3f. 0 (- force) 0) | |
216 (Vector3f. 0 0 0))) | |
217 | |
218 (if @roll-left? | |
219 (.applyForce control-a | |
220 (Vector3f. 0 0 force) | |
221 (Vector3f. 0 0 0))) | |
222 (if @roll-right? | |
223 (.applyForce control-a | |
224 (Vector3f. 0 0 (- force)) | |
225 (Vector3f. 0 0 0))) | |
226 | |
227 (if (zero? (rem (swap! timer inc) 100)) | |
228 (.attachChild | |
229 (.getRootNode world) | |
230 (sphere 0.05 :color ColorRGBA/Yellow | |
231 :physical? false :position | |
232 (.getWorldTranslation obj-a))))) | |
233 ) | |
234 )) | |
235 | |
236 | |
237 | |
238 | |
239 | |
240 | |
241 | |
242 | |
243 | |
244 | |
245 | |
246 (defn world-setup [joint] | |
247 (let [top (doto | |
248 (sphere 0.1 :physical? false :color ColorRGBA/Yellow | |
249 :position (Vector3f. 0 7 0)) | |
250 (.addControl | |
251 (RigidBodyControl. | |
252 (CapsuleCollisionShape. 0.5 1.5 1) (float 15)))) | |
253 bottom (doto | |
254 (sphere 0.1 :physical? false :color ColorRGBA/DarkGray | |
255 :position (Vector3f. 0 -1 0)) | |
256 (.addControl | |
257 (RigidBodyControl. | |
258 (CapsuleCollisionShape. 0.5 1.5 1) (float 0)))) | |
259 table (box 10 2 10 :position (Vector3f. 0 -6 0) | |
260 :color ColorRGBA/Gray :mass 0) | |
261 a (.getControl top RigidBodyControl) | |
262 b (.getControl bottom RigidBodyControl)] | |
263 (cond | |
264 (= joint :point) | |
265 (doto | |
266 (Point2PointJoint. a b | |
267 (Vector3f. 0 -2 0) | |
268 (Vector3f. 0 2 0)) | |
269 (.setCollisionBetweenLinkedBodys false)) | |
270 (= joint :hinge) | |
271 (doto | |
272 (HingeJoint. | |
273 a b | |
274 (Vector3f. 0 -2 0) | |
275 (Vector3f. 0 2 0) | |
276 (Vector3f. 0 0 1) | |
277 (Vector3f. 0 0 1) | |
278 | |
279 ) | |
280 (.setCollisionBetweenLinkedBodys false) | |
281 ;;(.setLimit (- Math/PI) Math/PI) | |
282 ) | |
283 (= joint :cone) | |
284 ;; note to self -- jbullet does NOT implement cone joints | |
285 ;; correctly. You must use plain ol' bullet for this to work. | |
286 ;; It's faster anyway, so whatever. | |
287 | |
288 (doto (ConeJoint. | |
289 a b | |
290 (Vector3f. 0 -5 0) | |
291 (Vector3f. 0 2 0) | |
292 | |
293 (doto (Matrix3f.) | |
294 (.fromStartEndVectors Vector3f/UNIT_X | |
295 Vector3f/UNIT_Y)) | |
296 (doto (Matrix3f.) | |
297 (.fromStartEndVectors Vector3f/UNIT_X | |
298 Vector3f/UNIT_Y)) | |
299 ) | |
300 ;;(.setAngularOnly true) | |
301 | |
302 (.setCollisionBetweenLinkedBodys false) | |
303 (.setLimit (* 1 (/ Math/PI 4)) | |
304 (* 1 (/ Math/PI 4)) | |
305 (* 0 (/ Math/PI 4))) | |
306 | |
307 ) | |
308 (= joint :six) | |
309 (doto | |
310 (SixDofJoint. | |
311 a b | |
312 (Vector3f. 0 -2 0) | |
313 (Vector3f. 0 2 0) | |
314 ;;(doto (Matrix3f.) | |
315 ;; (.fromStartEndVectors Vector3f/UNIT_X | |
316 ;; Vector3f/UNIT_Y)) | |
317 ;;(doto (Matrix3f.) | |
318 ;; (.fromStartEndVectors Vector3f/UNIT_X | |
319 ;; Vector3f/UNIT_Y)) | |
320 true) | |
321 (.setCollisionBetweenLinkedBodys false) | |
322 (.setAngularLowerLimit (Vector3f. 0 | |
323 (- (/ Math/PI 2)) | |
324 0)) | |
325 | |
326 (.setAngularUpperLimit (Vector3f. 0 | |
327 (/ Math/PI 2) | |
328 0)) | |
329 (.setLinearLowerLimit (Vector3f. 0 0 0)) | |
330 (.setLinearUpperLimit (Vector3f. 0 0 0)) | |
331 | |
332 ) | |
333 | |
334 | |
335 | |
336 | |
337 | |
338 ) | |
339 | |
340 [top bottom table])) | |
341 | |
342 (defn speed-up [world] | |
343 (.setMoveSpeed (.getFlyByCamera world) | |
344 (float 100)) | |
345 (.setRotationSpeed (.getFlyByCamera world) | |
346 (float 20)) | |
347 world) | |
348 | |
349 | |
350 (defn test-joint [joint] | |
351 (let [[top bottom floor] (world-setup joint) | |
352 control (.getControl top RigidBodyControl) | |
353 move-up? (atom false) | |
354 move-down? (atom false) | |
355 move-left? (atom false) | |
356 move-right? (atom false) | |
357 roll-left? (atom false) | |
358 roll-right? (atom false) | |
359 timer (atom 0)] | |
360 | |
361 (world | |
362 (nodify [top bottom floor]) | |
363 (merge standard-debug-controls | |
364 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?)) | |
365 "key-t" (fn [_ pressed?] (reset! move-down? pressed?)) | |
366 "key-f" (fn [_ pressed?] (reset! move-left? pressed?)) | |
367 "key-g" (fn [_ pressed?] (reset! move-right? pressed?)) | |
368 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?)) | |
369 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))}) | |
370 | |
371 (fn [world] | |
372 (light-up-everything world) | |
373 (enable-debug world) | |
374 (set-gravity world (Vector3f. 0 0 0)) | |
375 ) | |
376 | |
377 (fn [world _] | |
378 (if (zero? (rem (swap! timer inc) 100)) | |
379 (do | |
380 ;; (println-repl @timer) | |
381 (.attachChild (.getRootNode world) | |
382 (sphere 0.05 :color ColorRGBA/Yellow | |
383 :position (.getWorldTranslation top) | |
384 :physical? false)))) | |
385 (if @move-up? | |
386 (.applyTorque control | |
387 (.mult (.getPhysicsRotation control) | |
388 (Vector3f. 0 0 10)))) | |
389 (if @move-down? | |
390 (.applyTorque control | |
391 (.mult (.getPhysicsRotation control) | |
392 (Vector3f. 0 0 -10)))) | |
393 (if @move-left? | |
394 (.applyTorque control | |
395 (.mult (.getPhysicsRotation control) | |
396 (Vector3f. 0 10 0)))) | |
397 (if @move-right? | |
398 (.applyTorque control | |
399 (.mult (.getPhysicsRotation control) | |
400 (Vector3f. 0 -10 0)))) | |
401 (if @roll-left? | |
402 (.applyTorque control | |
403 (.mult (.getPhysicsRotation control) | |
404 (Vector3f. -1 0 0)))) | |
405 (if @roll-right? | |
406 (.applyTorque control | |
407 (.mult (.getPhysicsRotation control) | |
408 (Vector3f. 1 0 0)))))))) | |
409 | |
410 | |
411 | |
412 (defn run [joint] (.start (test-joint joint))) | |
413 (defn look [joint] (view (nodify (world-setup joint)))) | |
414 | |
415 (defn blender-to-jme | |
416 "Convert from Blender coordinates to JME coordinates" | |
417 [#^Vector3f in] | |
418 (Vector3f. (.getX in) | |
419 (.getZ in) | |
420 (- (.getY in)))) | |
421 | |
422 | |
423 (defn joint-targets | |
424 "Return the two closest two objects to the joint object, ordered | |
425 from bottom to top according to the joint's rotation." | |
426 [#^Node parts #^Node joint] | |
427 ;;(println (meta-data joint "joint")) | |
428 (.getWorldRotation joint) | |
117 (loop [radius (float 0.01)] | 429 (loop [radius (float 0.01)] |
118 (let [results (CollisionResults.)] | 430 (let [results (CollisionResults.)] |
119 (.collideWith | 431 (.collideWith |
120 parts | 432 parts |
121 (BoundingBox. joint-position radius radius radius) | 433 (BoundingBox. (.getWorldTranslation joint) |
434 radius radius radius) | |
122 results) | 435 results) |
123 (let [targets | 436 (let [targets |
124 (distinct | 437 (distinct |
125 (map #(.getGeometry %) results))] | 438 (map #(.getGeometry %) results))] |
126 (if (>= (count targets) 2) | 439 (if (>= (count targets) 2) |
127 (take 2 targets) | 440 (sort-by |
441 #(.getY | |
442 (.mult | |
443 (.inverse (.getWorldRotation joint)) | |
444 (.subtract (.getWorldTranslation %) | |
445 (.getWorldTranslation joint)))) | |
446 (take 2 targets)) | |
128 (recur (float (* radius 2)))))))) | 447 (recur (float (* radius 2)))))))) |
129 | 448 |
130 | 449 (defn connect |
131 | 450 "here are some examples: |
132 (defn connect-at-point | 451 {:type :point} |
133 [obj-a obj-b point] | 452 {:type :hinge :limit [0 (/ Math/PI 2)] :axis (Vector3f. 0 1 0)} |
134 (let [center-a (.getWorldTranslation obj-a) | 453 (:axis defaults to (Vector3f. 1 0 0) if not provided for hinge joints) |
135 center-b (.getWorldTranslation obj-b) | 454 |
136 pivot-a (.subtract point center-a) | 455 {:type :cone :limit-xz 0] |
137 pivot-b (.subtract point center-b) | 456 :limit-yz 0] |
138 ;; A side-effect of creating a joint registers | 457 :twist 0]} |
139 ;; it with both physics objects which in turn | 458 " |
140 ;; will register the joint with the physics system | 459 ([#^Node obj-a #^Node obj-b #^Node joint] |
141 ;; when the simulation is started. | 460 (let [center-a (.getWorldTranslation obj-a) |
142 joint (Point2PointJoint. | 461 center-b (.getWorldTranslation obj-b) |
143 (.getControl obj-a RigidBodyControl) | 462 joint-center (.getWorldTranslation joint) |
144 (.getControl obj-b RigidBodyControl) | 463 pivot-a (.subtract joint-center center-a) |
145 pivot-a | 464 pivot-b (.subtract joint-center center-b) |
146 pivot-b)] | 465 control-a (.getControl obj-a RigidBodyControl) |
147 obj-a)) | 466 control-b (.getControl obj-b RigidBodyControl)] |
148 | 467 ;; A side-effect of creating a joint registers |
149 | 468 ;; it with both physics objects which in turn |
150 (defn physical-hand [#^Node pieces joints] | 469 ;; will register the joint with the physics system |
151 ;; Make each piece a physical entity in the simulation. | 470 ;; when the simulation is started. |
471 (if-let [constraints | |
472 (map-vals | |
473 eval | |
474 (read-string | |
475 (meta-data (first (worm-joints)) "joint")))] | |
476 | |
477 (let [joint-type (:type constraints)] | |
478 (cond (= :point joint-type) | |
479 (do | |
480 (println-repl "creating POINT joint") | |
481 (Point2PointJoint. | |
482 control-a | |
483 control-b | |
484 pivot-a | |
485 pivot-b)) | |
486 (= :hinge joint-type) | |
487 (do | |
488 (println-repl "creating HINGE joint") | |
489 (let [axis (if-let | |
490 [axis (:axis constraints)] | |
491 axis | |
492 Vector3f/UNIT_X) | |
493 [limit-1 limit-2] (:limit constraints) | |
494 hinge-axis | |
495 (.mult | |
496 (.getWorldRotation joint) | |
497 (blender-to-jme axis))] | |
498 (doto | |
499 (HingeJoint. | |
500 control-a | |
501 control-b | |
502 pivot-a | |
503 pivot-b | |
504 hinge-axis | |
505 hinge-axis) | |
506 (.setLimit limit-1 limit-2)))) | |
507 (= :cone joint-type) | |
508 (do | |
509 (let [limit-xy (:limit-xz constraints) | |
510 limit-yz (:limit-yz constraints) | |
511 twist (:twist constraints)] | |
512 | |
513 (println-repl "creating CONE joint") | |
514 (doto | |
515 (ConeJoint. | |
516 control-a | |
517 control-b | |
518 pivot-a | |
519 pivot-b | |
520 (doto (Matrix3f.) | |
521 (.fromStartEndVectors | |
522 Vector3f/UNIT_X | |
523 (.normalize | |
524 (.subtract (.getWorldTranslation joint) | |
525 (.getWorldTranslation obj-a))))) | |
526 (doto (Matrix3f.) | |
527 (.fromStartEndVectors | |
528 Vector3f/UNIT_X | |
529 (.normalize | |
530 (.subtract | |
531 (.getWorldTranslation obj-b) | |
532 (.getWorldTranslation joint)))))) | |
533 (.setLimit (float limit-xy) | |
534 (float limit-yz) | |
535 (float twist))))) | |
536 true | |
537 (println-repl | |
538 "joint-type " joint-type " not recognized"))) | |
539 | |
540 (println-repl "could not find joint meta-data!"))))) | |
541 | |
542 | |
543 | |
544 (defn physical-worm [#^Node pieces joints] | |
152 (dorun | 545 (dorun |
153 (map | 546 (map |
154 (fn [geom] | 547 (fn [geom] |
155 (let [physics-control | 548 (let [physics-control |
156 (RigidBodyControl. | 549 (RigidBodyControl. |
157 (HullCollisionShape. | 550 (HullCollisionShape. |
158 (.getMesh geom)) | 551 (.getMesh geom)) |
159 ;; TODO: fix this. | 552 (if-let [mass (meta-data geom "mass")] |
160 (float 1.0))] | 553 (do |
554 (println-repl | |
555 "setting mass to " (float mass)) | |
556 (float mass)) | |
557 (float 1)))] | |
558 | |
161 (.addControl geom physics-control))) | 559 (.addControl geom physics-control))) |
162 (filter #(isa? (class %) Geometry ) | 560 (filter #(isa? (class %) Geometry ) |
163 (node-seq pieces)))) | 561 (node-seq pieces)))) |
562 | |
164 (dorun | 563 (dorun |
165 (map | 564 (map |
166 (fn [joint-position] | 565 (fn [joint] |
167 (let [[geom-a geom-b] (find-joint pieces joint-position)] | 566 (let [[obj-a obj-b] |
168 (connect-at-point geom-a geom-b joint-position))) | 567 (joint-targets pieces joint)] |
169 joints)) | 568 (connect obj-a obj-b joint))) |
170 pieces) | 569 joints)) |
171 | 570 pieces) |
172 | 571 |
173 (defn the-hand! [] (physical-hand (hand) (hand-joints))) | 572 (defn the-worm [] |
174 | 573 (physical-worm (worm) (worm-joints))) |
175 | 574 |
176 (defn test-hand [] | 575 (defn test-worm [] |
177 (world | 576 (world |
178 (nodify [(the-hand!) | 577 (nodify [(the-worm) |
179 (box 10 1 10 :position (Vector3f. 0 -10 0) | 578 (box 10 2 10 :position (Vector3f. 0 -5 0) |
180 :color ColorRGBA/Gray | 579 :color ColorRGBA/Gray :mass 0)]) |
181 :mass 0)]) | |
182 standard-debug-controls | 580 standard-debug-controls |
183 enable-debug | 581 (comp light-up-everything enable-debug |
184 (fn [_ _] | 582 (fn [world] |
185 (Thread/sleep 100)))) | 583 (.setTimer world (NanoTimer.)) |
186 | 584 (speed-up world) |
187 | 585 ;;(set-gravity world (Vector3f. 0 0 0)) |
188 | 586 world |
189 | 587 )) |
190 | 588 no-op)) |
191 | |
192 | 589 |
193 #+end_src | 590 #+end_src |
194 | 591 |
195 #+results: body-1 | 592 #+results: body-1 |
196 : #'cortex.silly/test-hand | 593 : #'cortex.silly/test-try-again |
197 | 594 |
198 | 595 |
199 | 596 |
200 * COMMENT generate source | 597 * COMMENT generate source |
201 #+begin_src clojure :tangle ../src/cortex/silly.clj | 598 #+begin_src clojure :tangle ../src/cortex/silly.clj |