view org/test-creature.org @ 88:3e929630a25f

multimethod dispatch works
author Robert McIntyre <rlm@mit.edu>
date Sat, 07 Jan 2012 05:24:14 -0700
parents af1bb43661f9
children cd5151b5e7c3
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 joint-dispatch
129 "Translate blender pseudo-joints into real JME joints."
130 (fn [constraints & _]
131 (:type constraints)))
133 (defmethod joint-dispatch :point
134 [constraints control-a control-b pivot-a pivot-b rotation]
135 (println-repl "creating POINT2POINT joint")
136 (Point2PointJoint.
137 control-a
138 control-b
139 pivot-a
140 pivot-b))
142 (defmethod joint-dispatch :hinge
143 [constraints control-a control-b pivot-a pivot-b rotation]
144 (println-repl "creating HINGE joint")
145 (let [axis
146 (if-let
147 [axis (:axis constraints)]
148 axis
149 Vector3f/UNIT_X)
150 [limit-1 limit-2] (:limit constraints)
151 hinge-axis
152 (.mult
153 rotation
154 (blender-to-jme axis))]
155 (doto
156 (HingeJoint.
157 control-a
158 control-b
159 pivot-a
160 pivot-b
161 hinge-axis
162 hinge-axis)
163 (.setLimit limit-1 limit-2))))
166 (defmethod joint-dispatch :cone
167 [constraints control-a control-b pivot-a pivot-b rotation]
168 (let [limit-xz (:limit-xz constraints)
169 limit-xy (:limit-xy constraints)
170 twist (:twist constraints)]
173 (println-repl "creating CONE joint")
174 (println-repl rotation)
175 (println-repl
176 "UNIT_X --> " (.mult rotation (Vector3f. 1 0 0)))
177 (println-repl
178 "UNIT_Y --> " (.mult rotation (Vector3f. 0 1 0)))
179 (println-repl
180 "UNIT_Z --> " (.mult rotation (Vector3f. 0 0 1)))
181 (doto
182 (ConeJoint.
183 control-a
184 control-b
185 pivot-a
186 pivot-b
187 rotation
188 rotation)
189 (.setLimit (float limit-xz)
190 (float limit-xy)
191 (float twist)))))
195 (defn connect
196 "here are some examples:
197 {:type :point}
198 {:type :hinge :limit [0 (/ Math/PI 2)] :axis (Vector3f. 0 1 0)}
199 (:axis defaults to (Vector3f. 1 0 0) if not provided for hinge joints)
201 {:type :cone :limit-xz 0]
202 :limit-xy 0]
203 :twist 0]} (use XZY rotation mode in blender!)"
204 [#^Node obj-a #^Node obj-b #^Node joint]
205 (let [control-a (.getControl obj-a RigidBodyControl)
206 control-b (.getControl obj-b RigidBodyControl)
207 joint-center (.getWorldTranslation joint)
208 joint-rotation (.toRotationMatrix (.getWorldRotation joint))
209 pivot-a (world-to-local obj-a joint-center)
210 pivot-b (world-to-local obj-b joint-center)]
211 ;; A side-effect of creating a joint registers
212 ;; it with both physics objects which in turn
213 ;; will register the joint with the physics system
214 ;; when the simulation is started.
215 (if-let [constraints
216 (map-vals
217 eval
218 (read-string
219 (meta-data joint "joint")))]
220 (do
221 (println-repl "creating joint between"
222 (.getName obj-a) "and" (.getName obj-b))
223 (joint-dispatch constraints
224 control-a control-b
225 pivot-a pivot-b
226 joint-rotation))
228 (println-repl "could not find joint meta-data!"))))
230 (defn assemble-creature [#^Node pieces joints]
231 (dorun
232 (map
233 (fn [geom]
234 (let [physics-control
235 (RigidBodyControl.
236 (HullCollisionShape.
237 (.getMesh geom))
238 (if-let [mass (meta-data geom "mass")]
239 (do
240 (println-repl
241 "setting" (.getName geom) "mass to" (float mass))
242 (float mass))
243 (float 1)))]
245 (.addControl geom physics-control)))
246 (filter #(isa? (class %) Geometry )
247 (node-seq pieces))))
249 (dorun
250 (map
251 (fn [joint]
252 (let [[obj-a obj-b]
253 (joint-targets pieces joint)]
254 (connect obj-a obj-b joint)))
255 joints))
256 pieces)
258 (defn blender-creature [blender-path]
259 (let [model (load-blender-model blender-path)
260 joints
261 (if-let [joint-node (.getChild model "joints")]
262 (seq (.getChildren joint-node))
263 (do (println-repl "could not find joints node")
264 []))]
265 (assemble-creature model joints)))
267 (def hand "Models/creature1/one.blend")
269 (def worm "Models/creature1/try-again.blend")
271 (defn x-ray [#^ColorRGBA color]
272 (doto (Material. (asset-manager)
273 "Common/MatDefs/Misc/Unshaded.j3md")
274 (.setColor "Color" color)
275 (-> (.getAdditionalRenderState)
276 (.setDepthTest false))))
278 (defn test-creature [thing]
279 (let [x-axis
280 (box 1 0.01 0.01 :physical? false :color ColorRGBA/Red)
281 y-axis
282 (box 0.01 1 0.01 :physical? false :color ColorRGBA/Green)
283 z-axis
284 (box 0.01 0.01 1 :physical? false :color ColorRGBA/Blue)]
285 (world
286 (nodify [(blender-creature thing)
287 (box 10 2 10 :position (Vector3f. 0 -9 0)
288 :color ColorRGBA/Gray :mass 0)
289 x-axis y-axis z-axis
290 ])
291 standard-debug-controls
292 (comp light-up-everything enable-debug
293 (fn [world]
294 (.setTimer world (NanoTimer.))
295 ;;(set-gravity world (Vector3f. 0 0 0))
296 (speed-up world)
297 world
298 ))
299 no-op)))
301 (defn world-setup [joint]
302 (let [
304 joint-position (Vector3f. 0 0 0)
305 joint-rotation
306 (.toRotationMatrix
307 (.mult
308 (doto (Quaternion.)
309 (.fromAngleAxis
310 (* 1 (/ Math/PI 4))
311 (Vector3f. -1 0 0)))
312 (doto (Quaternion.)
313 (.fromAngleAxis
314 (* 1 (/ Math/PI 2))
315 (Vector3f. 0 0 1)))))
316 top-position (.mult joint-rotation (Vector3f. 8 0 0))
318 origin (doto
319 (sphere 0.1 :physical? false :color ColorRGBA/Cyan
320 :position top-position))
321 top (doto
322 (sphere 0.1 :physical? false :color ColorRGBA/Yellow
323 :position top-position)
325 (.addControl
326 (RigidBodyControl.
327 (CapsuleCollisionShape. 0.5 1.5 1) (float 20))))
328 bottom (doto
329 (sphere 0.1 :physical? false :color ColorRGBA/DarkGray
330 :position (Vector3f. 0 0 0))
331 (.addControl
332 (RigidBodyControl.
333 (CapsuleCollisionShape. 0.5 1.5 1) (float 0))))
334 table (box 10 2 10 :position (Vector3f. 0 -20 0)
335 :color ColorRGBA/Gray :mass 0)
336 a (.getControl top RigidBodyControl)
337 b (.getControl bottom RigidBodyControl)]
339 (cond
340 (= joint :cone)
342 (doto (ConeJoint.
343 a b
344 (world-to-local top joint-position)
345 (world-to-local bottom joint-position)
346 joint-rotation
347 joint-rotation
348 )
351 (.setLimit (* (/ 10) Math/PI)
352 (* (/ 4) Math/PI)
353 0)))
354 [origin top bottom table]))
358 (defn test-joint [joint]
359 (let [[origin top bottom floor] (world-setup joint)
360 control (.getControl top RigidBodyControl)
361 move-up? (atom false)
362 move-down? (atom false)
363 move-left? (atom false)
364 move-right? (atom false)
365 roll-left? (atom false)
366 roll-right? (atom false)
367 timer (atom 0)]
369 (world
370 (nodify [top bottom floor origin])
371 (merge standard-debug-controls
372 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
373 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
374 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
375 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
376 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
377 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
379 (fn [world]
380 (light-up-everything world)
381 (enable-debug world)
382 (set-gravity world (Vector3f. 0 0 0))
383 )
385 (fn [world _]
386 (if (zero? (rem (swap! timer inc) 100))
387 (do
388 ;; (println-repl @timer)
389 (.attachChild (.getRootNode world)
390 (sphere 0.05 :color ColorRGBA/Yellow
391 :position (.getWorldTranslation top)
392 :physical? false))
393 (.attachChild (.getRootNode world)
394 (sphere 0.05 :color ColorRGBA/LightGray
395 :position (.getWorldTranslation bottom)
396 :physical? false))))
398 (if @move-up?
399 (.applyTorque control
400 (.mult (.getPhysicsRotation control)
401 (Vector3f. 0 0 10))))
402 (if @move-down?
403 (.applyTorque control
404 (.mult (.getPhysicsRotation control)
405 (Vector3f. 0 0 -10))))
406 (if @move-left?
407 (.applyTorque control
408 (.mult (.getPhysicsRotation control)
409 (Vector3f. 0 10 0))))
410 (if @move-right?
411 (.applyTorque control
412 (.mult (.getPhysicsRotation control)
413 (Vector3f. 0 -10 0))))
414 (if @roll-left?
415 (.applyTorque control
416 (.mult (.getPhysicsRotation control)
417 (Vector3f. -1 0 0))))
418 (if @roll-right?
419 (.applyTorque control
420 (.mult (.getPhysicsRotation control)
421 (Vector3f. 1 0 0))))))))
425 #+end_src
427 #+results: body-1
428 : #'cortex.silly/test-joint
431 * COMMENT purgatory
432 #+begin_src clojure
433 (defn bullet-trans []
434 (let [obj-a (sphere 0.5 :color ColorRGBA/Red
435 :position (Vector3f. -10 5 0))
436 obj-b (sphere 0.5 :color ColorRGBA/Blue
437 :position (Vector3f. -10 -5 0)
438 :mass 0)
439 control-a (.getControl obj-a RigidBodyControl)
440 control-b (.getControl obj-b RigidBodyControl)
441 swivel
442 (.toRotationMatrix
443 (doto (Quaternion.)
444 (.fromAngleAxis (/ Math/PI 2)
445 Vector3f/UNIT_X)))]
446 (doto
447 (ConeJoint.
448 control-a control-b
449 (Vector3f. 0 5 0)
450 (Vector3f. 0 -5 0)
451 swivel swivel)
452 (.setLimit (* 0.6 (/ Math/PI 4))
453 (/ Math/PI 4)
454 (* Math/PI 0.8)))
455 (world (nodify
456 [obj-a obj-b])
457 standard-debug-controls
458 enable-debug
459 no-op)))
462 (defn bullet-trans* []
463 (let [obj-a (box 1.5 0.5 0.5 :color ColorRGBA/Red
464 :position (Vector3f. 5 0 0)
465 :mass 90)
466 obj-b (sphere 0.5 :color ColorRGBA/Blue
467 :position (Vector3f. -5 0 0)
468 :mass 0)
469 control-a (.getControl obj-a RigidBodyControl)
470 control-b (.getControl obj-b RigidBodyControl)
471 move-up? (atom nil)
472 move-down? (atom nil)
473 move-left? (atom nil)
474 move-right? (atom nil)
475 roll-left? (atom nil)
476 roll-right? (atom nil)
477 force 100
478 swivel
479 (.toRotationMatrix
480 (doto (Quaternion.)
481 (.fromAngleAxis (/ Math/PI 2)
482 Vector3f/UNIT_X)))
483 x-move
484 (doto (Matrix3f.)
485 (.fromStartEndVectors Vector3f/UNIT_X
486 (.normalize (Vector3f. 1 1 0))))
488 timer (atom 0)]
489 (doto
490 (ConeJoint.
491 control-a control-b
492 (Vector3f. -8 0 0)
493 (Vector3f. 2 0 0)
494 ;;swivel swivel
495 ;;Matrix3f/IDENTITY Matrix3f/IDENTITY
496 x-move Matrix3f/IDENTITY
497 )
498 (.setCollisionBetweenLinkedBodys false)
499 (.setLimit (* 1 (/ Math/PI 4)) ;; twist
500 (* 1 (/ Math/PI 4)) ;; swing span in X-Y plane
501 (* 0 (/ Math/PI 4)))) ;; swing span in Y-Z plane
502 (world (nodify
503 [obj-a obj-b])
504 (merge standard-debug-controls
505 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
506 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
507 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
508 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
509 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
510 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
512 (fn [world]
513 (enable-debug world)
514 (set-gravity world Vector3f/ZERO)
515 )
517 (fn [world _]
519 (if @move-up?
520 (.applyForce control-a
521 (Vector3f. force 0 0)
522 (Vector3f. 0 0 0)))
523 (if @move-down?
524 (.applyForce control-a
525 (Vector3f. (- force) 0 0)
526 (Vector3f. 0 0 0)))
527 (if @move-left?
528 (.applyForce control-a
529 (Vector3f. 0 force 0)
530 (Vector3f. 0 0 0)))
531 (if @move-right?
532 (.applyForce control-a
533 (Vector3f. 0 (- force) 0)
534 (Vector3f. 0 0 0)))
536 (if @roll-left?
537 (.applyForce control-a
538 (Vector3f. 0 0 force)
539 (Vector3f. 0 0 0)))
540 (if @roll-right?
541 (.applyForce control-a
542 (Vector3f. 0 0 (- force))
543 (Vector3f. 0 0 0)))
545 (if (zero? (rem (swap! timer inc) 100))
546 (.attachChild
547 (.getRootNode world)
548 (sphere 0.05 :color ColorRGBA/Yellow
549 :physical? false :position
550 (.getWorldTranslation obj-a)))))
551 )
552 ))
556 #+end_src
559 * COMMENT generate source
560 #+begin_src clojure :tangle ../src/cortex/silly.clj
561 <<body-1>>
562 #+end_src