view org/test-creature.org @ 87:af1bb43661f9

working on multimethod joint creation
author Robert McIntyre <rlm@mit.edu>
date Sat, 07 Jan 2012 05:06:58 -0700
parents 00ab1f10266f
children 3e929630a25f
line wrap: on
line source
1 #+title: First attempt at a creature!
2 #+author: Robert McIntyre
3 #+email: rlm@mit.edu
4 #+description:
5 #+keywords: simulation, jMonkeyEngine3, clojure
6 #+SETUPFILE: ../../aurellem/org/setup.org
7 #+INCLUDE: ../../aurellem/org/level-0.org
9 * Intro
10 So far, I've made the following senses --
11 - Vision
12 - Hearing
13 - Touch
14 - Proprioception
16 And one effector:
17 - Movement
19 However, the code so far has only enabled these senses, but has not
20 actually implemented them. For example, there is still a lot of work
21 to be done for vision. I need to be able to create an /eyeball/ in
22 simulation that can be moved around and see the world from different
23 angles. I also need to determine weather to use log-polar or cartesian
24 for the visual input, and I need to determine how/wether to
25 disceritise the visual input.
27 I also want to be able to visualize both the sensors and the
28 effectors in pretty pictures. This semi-retarted creature will by my
29 first attempt at bringing everything together.
31 * The creature's body
33 Still going to do an eve-like body in blender, but due to problems
34 importing the joints, etc into jMonkeyEngine3, I',m going to do all
35 the connecting here in clojure code, using the names of the individual
36 components and trial and error. Later, I'll maybe make some sort of
37 creature-building modifications to blender that support whatever
38 discreitized senses I'm going to make.
40 #+name: body-1
41 #+begin_src clojure
42 (ns cortex.silly
43 "let's play!"
44 {:author "Robert McIntyre"})
46 ;; TODO remove this!
47 (require 'cortex.import)
48 (cortex.import/mega-import-jme3)
49 (use '(cortex world util body hearing touch vision))
51 (rlm.rlm-commands/help)
53 (declare joint-create)
55 (defn load-bullet []
56 (let [sim (world (Node.) {} no-op no-op)]
57 (.enqueue
58 sim
59 (fn []
60 (.stop sim)))
61 (.start sim)))
63 (defn load-blender-model
64 "Load a .blend file using an asset folder relative path."
65 [^String model]
66 (.loadModel
67 (doto (asset-manager)
68 (.registerLoader BlenderModelLoader (into-array String ["blend"])))
69 model))
71 (defn meta-data [blender-node key]
72 (if-let [data (.getUserData blender-node "properties")]
73 (.findValue data key)
74 nil))
76 (defn blender-to-jme
77 "Convert from Blender coordinates to JME coordinates"
78 [#^Vector3f in]
79 (Vector3f. (.getX in)
80 (.getZ in)
81 (- (.getY in))))
83 (defn jme-to-blender
84 "Convert from JME coordinates to Blender coordinates"
85 [#^Vector3f in]
86 (Vector3f. (.getX in)
87 (- (.getZ in))
88 (.getY in)))
90 (defn joint-targets
91 "Return the two closest two objects to the joint object, ordered
92 from bottom to top according to the joint's rotation."
93 [#^Node parts #^Node joint]
94 ;;(println (meta-data joint "joint"))
95 (.getWorldRotation joint)
96 (loop [radius (float 0.01)]
97 (let [results (CollisionResults.)]
98 (.collideWith
99 parts
100 (BoundingBox. (.getWorldTranslation joint)
101 radius radius radius)
102 results)
103 (let [targets
104 (distinct
105 (map #(.getGeometry %) results))]
106 (if (>= (count targets) 2)
107 (sort-by
108 #(let [v
109 (jme-to-blender
110 (.mult
111 (.inverse (.getWorldRotation joint))
112 (.subtract (.getWorldTranslation %)
113 (.getWorldTranslation joint))))]
114 (println-repl (.getName %) ":" v)
115 (.dot (Vector3f. 1 1 1)
116 v))
117 (take 2 targets))
118 (recur (float (* radius 2))))))))
120 (defn world-to-local
121 "Convert the world coordinates into coordinates relative to the
122 object (i.e. local coordinates), taking into account the rotation
123 of object."
124 [#^Spatial object world-coordinate]
125 (let [out (Vector3f.)]
126 (.worldToLocal object world-coordinate out) out))
128 (defmulti zz
129 (fn [a b _ _ _ _ _]
131 (:type a)))
132 (defmethod zz :p [a b] (println "hi"))
135 (defmulti joint-dispatch
136 "Translate blender pseudo-joints into real JME joints."
137 (fn [constraints _ _ _ _ _]
138 (:type constraints)))
140 (defmethod joint-dispatch :point
141 [constraints control-a control-b pivot-a pivot-b rotation]
142 (println-repl "creating POINT2POINT joint")
143 (Point2PointJoint.
144 control-a
145 control-b
146 pivot-a
147 pivot-b))
149 (defmethod joint-dispatch :hinge
150 [constraints control-a control-b pivot-a pivot-b rotation]
151 (println-repl "creating HINGE joint")
152 (let [axis
153 (if-let
154 [axis (:axis constraints)]
155 axis
156 Vector3f/UNIT_X)
157 [limit-1 limit-2] (:limit constraints)
158 hinge-axis
159 (.mult
160 rotation
161 (blender-to-jme axis))]
162 (doto
163 (HingeJoint.
164 control-a
165 control-b
166 pivot-a
167 pivot-b
168 hinge-axis
169 hinge-axis)
170 (.setLimit limit-1 limit-2))))
173 (defmethod joint-dispatch :cone
174 [constraints control-a control-b pivot-a pivot-b rotation]
175 (let [limit-xz (:limit-xz constraints)
176 limit-xy (:limit-xy constraints)
177 twist (:twist constraints)]
180 (println-repl "creating CONE joint")
181 (println-repl rotation)
182 (println-repl
183 "UNIT_X --> " (.mult rotation (Vector3f. 1 0 0)))
184 (println-repl
185 "UNIT_Y --> " (.mult rotation (Vector3f. 0 1 0)))
186 (println-repl
187 "UNIT_Z --> " (.mult rotation (Vector3f. 0 0 1)))
188 (doto
189 (ConeJoint.
190 control-a
191 control-b
192 pivot-a
193 pivot-b
194 rotation
195 rotation)
196 (.setLimit (float limit-xz)
197 (float limit-xy)
198 (float twist)))))
202 (defn connect*
203 "here are some examples:
204 {:type :point}
205 {:type :hinge :limit [0 (/ Math/PI 2)] :axis (Vector3f. 0 1 0)}
206 (:axis defaults to (Vector3f. 1 0 0) if not provided for hinge joints)
208 {:type :cone :limit-xz 0]
209 :limit-xy 0]
210 :twist 0]} (use XZY rotation mode in blender!)"
211 [#^Node obj-a #^Node obj-b #^Node joint]
212 (let [control-a (.getControl obj-a RigidBodyControl)
213 control-b (.getControl obj-b RigidBodyControl)
214 joint-center (.getWorldTranslation joint)
215 joint-rotation (.toRotationMatrix (.getWorldRotation joint))
216 pivot-a (world-to-local obj-a joint-center)
217 pivot-b (world-to-local obj-b joint-center)]
218 ;; A side-effect of creating a joint registers
219 ;; it with both physics objects which in turn
220 ;; will register the joint with the physics system
221 ;; when the simulation is started.
222 (if-let [constraints
223 (map-vals
224 eval
225 (read-string
226 (meta-data joint "joint")))]
227 (do
228 (println-repl "creating joint between"
229 (.getName obj-a) "and" (.getName obj-b))
230 (joint-dispatch constraints
231 control-a control-b
232 pivot-a pivot-b
233 joint-rotation))
235 (println-repl "could not find joint meta-data!"))))
240 (defn connect
241 "here are some examples:
242 {:type :point}
243 {:type :hinge :limit [0 (/ Math/PI 2)] :axis (Vector3f. 0 1 0)}
244 (:axis defaults to (Vector3f. 1 0 0) if not provided for hinge joints)
246 {:type :cone :limit-xz 0]
247 :limit-xy 0]
248 :twist 0]} (use XZY rotation mode in blender!)"
249 [#^Node obj-a #^Node obj-b #^Node joint]
250 (let [control-a (.getControl obj-a RigidBodyControl)
251 control-b (.getControl obj-b RigidBodyControl)
252 joint-center (.getWorldTranslation joint)
253 joint-rotation (.toRotationMatrix (.getWorldRotation joint))
254 pivot-a (world-to-local obj-a joint-center)
255 pivot-b (world-to-local obj-b joint-center)]
256 ;; A side-effect of creating a joint registers
257 ;; it with both physics objects which in turn
258 ;; will register the joint with the physics system
259 ;; when the simulation is started.
260 (if-let [constraints
261 (map-vals
262 eval
263 (read-string
264 (meta-data joint "joint")))]
266 (let [joint-type (:type constraints)]
267 (println-repl "creating joint between"
268 (.getName obj-a) "and" (.getName obj-b))
269 (cond (= :point joint-type)
270 (do
271 (println-repl "creating POINT joint")
272 (Point2PointJoint.
273 control-a
274 control-b
275 pivot-a
276 pivot-b))
277 (= :hinge joint-type)
278 (do
279 (println-repl "creating HINGE joint")
280 (let [axis (if-let
281 [axis (:axis constraints)]
282 axis
283 Vector3f/UNIT_X)
284 [limit-1 limit-2] (:limit constraints)
285 hinge-axis
286 (.mult
287 (.getWorldRotation joint)
288 (blender-to-jme axis))]
289 (doto
290 (HingeJoint.
291 control-a
292 control-b
293 pivot-a
294 pivot-b
295 hinge-axis
296 hinge-axis)
297 (.setLimit limit-1 limit-2))))
298 (= :cone joint-type)
299 (do
300 (let [limit-xz (:limit-xz constraints)
301 limit-xy (:limit-xy constraints)
302 twist (:twist constraints)]
305 (println-repl "creating CONE joint")
306 (println-repl joint-rotation)
307 (println-repl
308 "UNIT_X --> " (.mult joint-rotation (Vector3f. 1 0 0)))
309 (println-repl
310 "UNIT_Y --> " (.mult joint-rotation (Vector3f. 0 1 0)))
311 (println-repl
312 "UNIT_Z --> " (.mult joint-rotation (Vector3f. 0 0 1)))
313 (doto
314 (ConeJoint.
315 control-a
316 control-b
317 pivot-a
318 pivot-b
319 joint-rotation
320 joint-rotation
321 )
322 (.setLimit (float limit-xz)
323 (float limit-xy)
324 (float twist)))))
325 true
326 (println-repl
327 "joint-type" joint-type "not recognized")))
329 (println-repl "could not find joint meta-data!"))))
332 (defn assemble-creature [#^Node pieces joints]
333 (dorun
334 (map
335 (fn [geom]
336 (let [physics-control
337 (RigidBodyControl.
338 (HullCollisionShape.
339 (.getMesh geom))
340 (if-let [mass (meta-data geom "mass")]
341 (do
342 (println-repl
343 "setting" (.getName geom) "mass to" (float mass))
344 (float mass))
345 (float 1)))]
347 (.addControl geom physics-control)))
348 (filter #(isa? (class %) Geometry )
349 (node-seq pieces))))
351 (dorun
352 (map
353 (fn [joint]
354 (let [[obj-a obj-b]
355 (joint-targets pieces joint)]
356 (connect* obj-a obj-b joint)))
357 joints))
358 pieces)
360 (defn blender-creature [blender-path]
361 (let [model (load-blender-model blender-path)
362 joints
363 (if-let [joint-node (.getChild model "joints")]
364 (seq (.getChildren joint-node))
365 (do (println-repl "could not find joints node")
366 []))]
367 (assemble-creature model joints)))
369 (def hand "Models/creature1/one.blend")
371 (def worm "Models/creature1/try-again.blend")
373 (defn x-ray [#^ColorRGBA color]
374 (doto (Material. (asset-manager)
375 "Common/MatDefs/Misc/Unshaded.j3md")
376 (.setColor "Color" color)
377 (-> (.getAdditionalRenderState)
378 (.setDepthTest false))))
380 (defn test-creature [thing]
381 (let [x-axis
382 (box 1 0.01 0.01 :physical? false :color ColorRGBA/Red)
383 y-axis
384 (box 0.01 1 0.01 :physical? false :color ColorRGBA/Green)
385 z-axis
386 (box 0.01 0.01 1 :physical? false :color ColorRGBA/Blue)]
387 (world
388 (nodify [(blender-creature thing)
389 (box 10 2 10 :position (Vector3f. 0 -9 0)
390 :color ColorRGBA/Gray :mass 0)
391 x-axis y-axis z-axis
392 ])
393 standard-debug-controls
394 (comp light-up-everything enable-debug
395 (fn [world]
396 (.setTimer world (NanoTimer.))
397 ;;(set-gravity world (Vector3f. 0 0 0))
398 (speed-up world)
399 world
400 ))
401 no-op)))
403 (defn world-setup [joint]
404 (let [
406 joint-position (Vector3f. 0 0 0)
407 joint-rotation
408 (.toRotationMatrix
409 (.mult
410 (doto (Quaternion.)
411 (.fromAngleAxis
412 (* 1 (/ Math/PI 4))
413 (Vector3f. -1 0 0)))
414 (doto (Quaternion.)
415 (.fromAngleAxis
416 (* 1 (/ Math/PI 2))
417 (Vector3f. 0 0 1)))))
418 top-position (.mult joint-rotation (Vector3f. 8 0 0))
420 origin (doto
421 (sphere 0.1 :physical? false :color ColorRGBA/Cyan
422 :position top-position))
423 top (doto
424 (sphere 0.1 :physical? false :color ColorRGBA/Yellow
425 :position top-position)
427 (.addControl
428 (RigidBodyControl.
429 (CapsuleCollisionShape. 0.5 1.5 1) (float 20))))
430 bottom (doto
431 (sphere 0.1 :physical? false :color ColorRGBA/DarkGray
432 :position (Vector3f. 0 0 0))
433 (.addControl
434 (RigidBodyControl.
435 (CapsuleCollisionShape. 0.5 1.5 1) (float 0))))
436 table (box 10 2 10 :position (Vector3f. 0 -20 0)
437 :color ColorRGBA/Gray :mass 0)
438 a (.getControl top RigidBodyControl)
439 b (.getControl bottom RigidBodyControl)]
441 (cond
442 (= joint :cone)
444 (doto (ConeJoint.
445 a b
446 (world-to-local top joint-position)
447 (world-to-local bottom joint-position)
448 joint-rotation
449 joint-rotation
450 )
453 (.setLimit (* (/ 10) Math/PI)
454 (* (/ 4) Math/PI)
455 0)))
456 [origin top bottom table]))
460 (defn test-joint [joint]
461 (let [[origin top bottom floor] (world-setup joint)
462 control (.getControl top RigidBodyControl)
463 move-up? (atom false)
464 move-down? (atom false)
465 move-left? (atom false)
466 move-right? (atom false)
467 roll-left? (atom false)
468 roll-right? (atom false)
469 timer (atom 0)]
471 (world
472 (nodify [top bottom floor origin])
473 (merge standard-debug-controls
474 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
475 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
476 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
477 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
478 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
479 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
481 (fn [world]
482 (light-up-everything world)
483 (enable-debug world)
484 (set-gravity world (Vector3f. 0 0 0))
485 )
487 (fn [world _]
488 (if (zero? (rem (swap! timer inc) 100))
489 (do
490 ;; (println-repl @timer)
491 (.attachChild (.getRootNode world)
492 (sphere 0.05 :color ColorRGBA/Yellow
493 :position (.getWorldTranslation top)
494 :physical? false))
495 (.attachChild (.getRootNode world)
496 (sphere 0.05 :color ColorRGBA/LightGray
497 :position (.getWorldTranslation bottom)
498 :physical? false))))
500 (if @move-up?
501 (.applyTorque control
502 (.mult (.getPhysicsRotation control)
503 (Vector3f. 0 0 10))))
504 (if @move-down?
505 (.applyTorque control
506 (.mult (.getPhysicsRotation control)
507 (Vector3f. 0 0 -10))))
508 (if @move-left?
509 (.applyTorque control
510 (.mult (.getPhysicsRotation control)
511 (Vector3f. 0 10 0))))
512 (if @move-right?
513 (.applyTorque control
514 (.mult (.getPhysicsRotation control)
515 (Vector3f. 0 -10 0))))
516 (if @roll-left?
517 (.applyTorque control
518 (.mult (.getPhysicsRotation control)
519 (Vector3f. -1 0 0))))
520 (if @roll-right?
521 (.applyTorque control
522 (.mult (.getPhysicsRotation control)
523 (Vector3f. 1 0 0))))))))
527 #+end_src
529 #+results: body-1
530 : #'cortex.silly/test-joint
533 * COMMENT purgatory
534 #+begin_src clojure
535 (defn bullet-trans []
536 (let [obj-a (sphere 0.5 :color ColorRGBA/Red
537 :position (Vector3f. -10 5 0))
538 obj-b (sphere 0.5 :color ColorRGBA/Blue
539 :position (Vector3f. -10 -5 0)
540 :mass 0)
541 control-a (.getControl obj-a RigidBodyControl)
542 control-b (.getControl obj-b RigidBodyControl)
543 swivel
544 (.toRotationMatrix
545 (doto (Quaternion.)
546 (.fromAngleAxis (/ Math/PI 2)
547 Vector3f/UNIT_X)))]
548 (doto
549 (ConeJoint.
550 control-a control-b
551 (Vector3f. 0 5 0)
552 (Vector3f. 0 -5 0)
553 swivel swivel)
554 (.setLimit (* 0.6 (/ Math/PI 4))
555 (/ Math/PI 4)
556 (* Math/PI 0.8)))
557 (world (nodify
558 [obj-a obj-b])
559 standard-debug-controls
560 enable-debug
561 no-op)))
564 (defn bullet-trans* []
565 (let [obj-a (box 1.5 0.5 0.5 :color ColorRGBA/Red
566 :position (Vector3f. 5 0 0)
567 :mass 90)
568 obj-b (sphere 0.5 :color ColorRGBA/Blue
569 :position (Vector3f. -5 0 0)
570 :mass 0)
571 control-a (.getControl obj-a RigidBodyControl)
572 control-b (.getControl obj-b RigidBodyControl)
573 move-up? (atom nil)
574 move-down? (atom nil)
575 move-left? (atom nil)
576 move-right? (atom nil)
577 roll-left? (atom nil)
578 roll-right? (atom nil)
579 force 100
580 swivel
581 (.toRotationMatrix
582 (doto (Quaternion.)
583 (.fromAngleAxis (/ Math/PI 2)
584 Vector3f/UNIT_X)))
585 x-move
586 (doto (Matrix3f.)
587 (.fromStartEndVectors Vector3f/UNIT_X
588 (.normalize (Vector3f. 1 1 0))))
590 timer (atom 0)]
591 (doto
592 (ConeJoint.
593 control-a control-b
594 (Vector3f. -8 0 0)
595 (Vector3f. 2 0 0)
596 ;;swivel swivel
597 ;;Matrix3f/IDENTITY Matrix3f/IDENTITY
598 x-move Matrix3f/IDENTITY
599 )
600 (.setCollisionBetweenLinkedBodys false)
601 (.setLimit (* 1 (/ Math/PI 4)) ;; twist
602 (* 1 (/ Math/PI 4)) ;; swing span in X-Y plane
603 (* 0 (/ Math/PI 4)))) ;; swing span in Y-Z plane
604 (world (nodify
605 [obj-a obj-b])
606 (merge standard-debug-controls
607 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
608 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
609 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
610 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
611 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
612 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
614 (fn [world]
615 (enable-debug world)
616 (set-gravity world Vector3f/ZERO)
617 )
619 (fn [world _]
621 (if @move-up?
622 (.applyForce control-a
623 (Vector3f. force 0 0)
624 (Vector3f. 0 0 0)))
625 (if @move-down?
626 (.applyForce control-a
627 (Vector3f. (- force) 0 0)
628 (Vector3f. 0 0 0)))
629 (if @move-left?
630 (.applyForce control-a
631 (Vector3f. 0 force 0)
632 (Vector3f. 0 0 0)))
633 (if @move-right?
634 (.applyForce control-a
635 (Vector3f. 0 (- force) 0)
636 (Vector3f. 0 0 0)))
638 (if @roll-left?
639 (.applyForce control-a
640 (Vector3f. 0 0 force)
641 (Vector3f. 0 0 0)))
642 (if @roll-right?
643 (.applyForce control-a
644 (Vector3f. 0 0 (- force))
645 (Vector3f. 0 0 0)))
647 (if (zero? (rem (swap! timer inc) 100))
648 (.attachChild
649 (.getRootNode world)
650 (sphere 0.05 :color ColorRGBA/Yellow
651 :physical? false :position
652 (.getWorldTranslation obj-a)))))
653 )
654 ))
658 #+end_src
661 * COMMENT generate source
662 #+begin_src clojure :tangle ../src/cortex/silly.clj
663 <<body-1>>
664 #+end_src