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