view org/cortex.org @ 24:e965675ec4d0

moving things around
author Robert McIntyre <rlm@mit.edu>
date Mon, 24 Oct 2011 01:19:15 -0700
parents cab2da252494
children 775d97247dd0
line wrap: on
line source
1 #+title: Simulated Senses
2 #+author: Robert McIntyre
3 #+email: rlm@mit.edu
4 #+description: Simulating senses for AI research using JMonkeyEngine3
5 #+SETUPFILE: ../../aurellem/org/setup.org
6 #+INCLUDE: ../../aurellem/org/level-0.org
7 #+babel: :mkdirp yes :noweb yes :exports both
10 * Simulation Base
13 ** Hello
14 Here are the jmonkeyengine "Hello" programs translated to clojure.
15 *** Hello Simple App
16 Here is the hello world example for jme3 in clojure. It's a more or
17 less direct translation from the java source [[http://jmonkeyengine.org/wiki/doku.php/jme3:beginner:hello_simpleapplication][here]].
19 Of note is the fact that since we don't have access to the
20 =AssetManager= via extendig =SimpleApplication=, we have to build one
21 ourselves.
23 #+srcname: hello-simple-app
24 #+begin_src clojure :results silent
25 (ns hello.hello-simple-app)
26 (require 'cortex.import)
27 (use 'clojure.contrib.def)
28 (rlm.rlm-commands/help)
29 (cortex.import/mega-import-jme3)
30 (use 'cortex.world)
33 (def cube (Box. Vector3f/ZERO 1 1 1))
35 (def geom (Geometry. "Box" cube))
37 (def mat (Material. (asset-manager) "Common/MatDefs/Misc/Unshaded.j3md"))
39 (.setColor mat "Color" ColorRGBA/Blue)
41 (.setMaterial geom mat)
43 (defn simple-app []
44 (doto
45 (proxy [SimpleApplication] []
46 (simpleInitApp
47 []
48 ;; Don't take control of the mouse
49 (org.lwjgl.input.Mouse/setGrabbed false)
50 (.attachChild (.getRootNode this) geom)))
51 ;; don't show a menu to change options.
52 (.setShowSettings false)
53 (.setPauseOnLostFocus false)
54 (.setSettings *app-settings*)))
55 #+end_src
57 Running this program will begin a new jMonkeyEngine game which
58 displays a single blue cube.
60 #+begin_src clojure :exports code :results silent
61 (.start (hello.hello-simple-app/simple-app))
62 #+end_src
64 #+caption: the simplest JME game.
65 [[./images/simple-app.jpg]]
69 *** Hello Physics
70 From http://jmonkeyengine.org/wiki/doku.php/jme3:beginner:hello_physics
72 #+srcname: brick-wall-header
73 #+begin_src clojure :results silent
74 (ns hello.brick-wall)
75 (require 'cortex.import)
76 (use 'clojure.contrib.def)
77 (rlm.rlm-commands/help)
78 (cortex.import/mega-import-jme3)
79 (use '[pokemon [lpsolve :only [constant-map]]])
80 (use 'cortex.world)
81 #+end_src
83 #+srcname: brick-wall-body
84 #+begin_src clojure :results silent
85 (in-ns 'hello.brick-wall)
87 (defn floor
88 "make a sturdy, unmovable physical floor"
89 []
90 (box 20 1 20 :mass 0 :color false :position (Vector3f. 0 -2 0)))
92 (def brick-length 0.48)
93 (def brick-width 0.24)
94 (def brick-height 0.12)
97 (defn brick* [position]
98 (doto (box brick-length brick-height brick-width
99 :position position :name "brick"
100 :material "Common/MatDefs/Misc/Unshaded.j3md"
101 :texture "Textures/Terrain/BrickWall/BrickWall.jpg"
102 :mass 36)
103 (->
104 (.getMesh)
105 (.scaleTextureCoordinates (Vector2f. 1 0.5)))
106 ;;(.setShadowMode RenderQueue$ShadowMode/CastAndReceive)
107 )
108 )
110 (defn inception-brick-wall
111 "construct a physical brick wall"
112 []
113 (let [node (Node. "brick-wall")]
114 (dorun
115 (map (comp #(.attachChild node %) brick*)
116 (for
117 [x (range 15)
118 y (range 10)
119 z (range 1)]
120 (Vector3f.
121 (* brick-length x 1.03)
122 (* brick-width y y 10)
123 (* brick-height z)))))
124 node))
126 (defn gravity-toggle
127 [new-value]
128 (fn [game value]
129 (println-repl "set gravity to " new-value)
130 (if value
131 (set-gravity* game new-value)
132 (set-gravity* game gravity))))
134 (defn fire-cannon-ball
135 ([node]
136 (fn [game value]
137 (if (not value)
138 (let [camera (.getCamera game)
139 cannon-ball
140 (sphere 0.7
141 :material "Common/MatDefs/Misc/Unshaded.j3md"
142 :texture "Textures/PokeCopper.jpg"
143 :position
144 (.add (.getLocation camera)
145 (.mult (.getDirection camera) (float 1)))
146 :mass 3)] ;200 0.05
147 (.setShadowMode cannon-ball RenderQueue$ShadowMode/CastAndReceive)
148 (.setLinearVelocity
149 (.getControl cannon-ball RigidBodyControl)
150 (.mult (.getDirection camera) (float 50))) ;50
151 (add-element game cannon-ball (if node node (.getRootNode game)))))))
152 ([]
153 (fire-cannon-ball false)))
156 (defn floor* []
157 (doto (box 10 0.1 5 :name "floor" ;10 0.1 5 ; 240 0.1 240
158 :material "Common/MatDefs/Misc/Unshaded.j3md"
159 :texture "Textures/Terrain/Pond/Pond.png"
160 :position (Vector3f. 0 -0.1 0 )
161 :mass 0)
162 (->
163 (.getMesh)
164 (.scaleTextureCoordinates (Vector2f. 3 6)));64 64
165 (->
166 (.getMaterial)
167 (.getTextureParam "ColorMap")
168 (.getTextureValue)
169 (.setWrap Texture$WrapMode/Repeat))
170 (.setShadowMode RenderQueue$ShadowMode/Receive)
171 ))
173 (defn brick-wall* []
174 (let [node (Node. "brick-wall")]
175 (dorun
176 (map
177 (comp #(.attachChild node %) brick*)
178 (for [y (range 15)
179 x (range 4)
180 z (range 1)]
181 (Vector3f.
182 (+ (* 2 x brick-length)
183 (if (even? (+ y z))
184 (/ brick-length 4) (/ brick-length -4)))
185 (+ (* brick-height (inc (* 2 y))))
186 (* 2 z brick-width) ))))
187 (.setShadowMode node RenderQueue$ShadowMode/CastAndReceive)
188 node))
190 (defn brick-wall-game-run []
191 (doto
192 (world
193 (doto (Node.) (.attachChild (floor*))
194 (.attachChild (brick-wall*))
195 )
196 {"key-i" (gravity-toggle (Vector3f. 0 0 -9.81))
197 "key-m" (gravity-toggle (Vector3f. 0 0 9.81))
198 "key-l" (gravity-toggle (Vector3f. 9.81 0 0))
199 "key-j" (gravity-toggle (Vector3f. -9.81 0 0))
200 "key-k" (gravity-toggle Vector3f/ZERO)
201 "key-u" (gravity-toggle (Vector3f. 0 9.81 0))
202 "key-o" (gravity-toggle (Vector3f. 0 -9.81 0))
203 "key-f" (fn[game value]
204 (if (not value) (add-element game (brick-wall*))))
205 "key-return" (fire-cannon-ball)}
206 position-camera
207 (fn [& _]))
208 (.start)))
209 #+end_src
211 #+begin_src clojure :results silent
212 (hello.brick-wall/brick-wall-game-run)
213 #+end_src
215 #+caption: the brick wall standing
216 [[./images/brick-wall-standing.jpg]]
218 #+caption: the brick wall after it has been knocked over by a "pok\eacute{}ball"
219 [[./images/brick-wall-knocked-down.jpg]]
221 *** Other Brick Games
222 #+srcname: other-games
223 #+begin_src clojure :results silent
224 (ns cortex.other-games
225 {:author "Dylan Holmes"})
226 (use 'cortex.world)
227 (use 'hello.brick-wall)
228 (use 'cortex.import)
229 (cortex.import/mega-import-jme3)
231 (defn scad [position]
232 (doto (box 0.1 0.1 0.1
233 :position position :name "brick"
234 :material "Common/MatDefs/Misc/Unshaded.j3md"
235 :texture "Textures/Terrain/BrickWall/BrickWall.jpg"
236 :mass 20)
237 (->
238 (.getMesh)
239 (.scaleTextureCoordinates (Vector2f. 1 0.5))
240 )
241 (-> (.getControl RigidBodyControl)
242 (.setLinearVelocity (Vector3f. 0 100 0))
243 )
245 ;;(.setShadowMode RenderQueue$ShadowMode/Cast)
246 ))
249 (defn shrapnel []
250 (let [node (Node. "explosion-day")]
251 (dorun
252 (map
253 (comp #(.attachChild node %) scad)
254 (for [y (range 15)
255 x (range 4)
256 z (range 1)]
257 (Vector3f.
258 (+ (* 2 x brick-height)
259 (if (even? (+ y z)) (/ brick-height 4) (/ brick-height -4)))
260 (+ (* brick-height (inc (* 2 y))))
261 (* 2 z brick-height) ))))
262 node))
265 (def domino-height 0.48)
266 (def domino-thickness 0.12)
267 (def domino-width 0.24)
269 (def domino-thickness 0.05)
270 (def domino-width 0.5)
271 (def domino-height 1)
273 (defn domino
274 ([position]
275 (domino position (Quaternion/IDENTITY)))
276 ([position rotation]
277 (doto (box domino-width domino-height domino-thickness
278 :position position :name "domino"
279 :material "Common/MatDefs/Misc/Unshaded.j3md"
280 :texture "Textures/Terrain/BrickWall/BrickWall.jpg"
281 :mass 1
282 :rotation rotation)
283 (.setShadowMode RenderQueue$ShadowMode/CastAndReceive)
284 )))
287 (defn domino-row []
288 (let [node (Node. "domino-row")]
289 (dorun
290 (map
291 (comp #(.attachChild node %) domino)
292 (for [
293 z (range 10)
294 x (range 5)
295 ]
296 (Vector3f.
297 (+ (* z domino-width) (* x 5 domino-width))
298 (/ domino-height 1)
299 (* -5.5 domino-thickness z) ))))
301 node))
303 (defn domino-cycle []
304 (let [node (Node. "domino-cycle")]
305 (dorun
306 (map
307 (comp #(.attachChild node %) (partial apply domino) )
308 (for [n (range 720)]
309 (let [space (* domino-height 5.5)
310 r (fn[n] (* (+ n 3) domino-width 0.5))
311 t (fn[n] (reduce
312 +
313 (map
314 (fn dt[n] (/ space (* 2 (Math/PI) (r n))))
315 (range n))))
316 t (t n)
317 r (r n)
318 ct (Math/cos t)
319 st (Math/sin t)
320 ]
321 (list
322 (Vector3f.
323 (* -1 r st)
324 (/ domino-height 1)
325 (* r ct))
326 (.fromAngleAxis (Quaternion.)
327 (- (/ 3.1415926 2) t) (Vector3f. 0 1 0))
328 )))
329 ))
330 node))
333 (defn domino-game-run []
334 (doto
335 (world
336 (doto (Node.) (.attachChild (floor*))
337 )
338 {"key-i" (gravity-toggle (Vector3f. 0 0 -9.81))
339 "key-m" (gravity-toggle (Vector3f. 0 0 9.81))
340 "key-l" (gravity-toggle (Vector3f. 9.81 0 0))
341 "key-j" (gravity-toggle (Vector3f. -9.81 0 0))
342 "key-k" (gravity-toggle (Vector3f. 0 9.81 0) )
343 "key-u" (fn[g v] ((gravity-toggle (Vector3f. 0 -0 0)) g true))
344 "key-o" (gravity-toggle (Vector3f. 0 -9.81 0))
346 "key-space"
347 (fn[game value]
349 (if (not value)
350 (let [d (domino (Vector3f. 0 (/ domino-height 0.25) 0)
351 (.fromAngleAxis (Quaternion.)
352 (/ Math/PI 2) (Vector3f. 0 1 0)))]
353 (add-element game d))))
354 "key-f"
355 (fn[game value](if (not value) (add-element game (domino-cycle))))
356 "key-return" (fire-cannon-ball)}
357 position-camera
358 (fn [& _]))
359 (.start)))
360 #+end_src
362 #+begin_src clojure :results silent
363 (cortex.other-games/domino-game-run)
364 #+end_src
366 #+caption: floating dominos
367 [[./images/dominos.jpg]]
369 *** Hello Loop
370 #+srcname: hello-loop
371 #+begin_src clojure :results silent
372 (ns hello.loop)
373 (use 'cortex.world)
374 (use 'cortex.import)
375 (cortex.import/mega-import-jme3)
376 (rlm.rlm-commands/help)
378 (defn blue-cube []
379 (box 1 1 1
380 :color ColorRGBA/Blue
381 :texture false
382 :material "Common/MatDefs/Misc/Unshaded.j3md"
383 :name "blue-cube"
384 :physical? false))
386 (defn blue-cube-game []
387 (let [cube (blue-cube)
388 root (doto (Node.) (.attachChild cube))]
389 (world root
390 {}
391 no-op
392 (fn [game tpf]
393 (.rotate cube 0.0 (* 2 tpf) 0.0)))))
394 #+end_src
396 *** Hello Collision
398 #+srcname: hello-collision
399 #+begin_src clojure :results silent
400 (ns hello.collision)
401 (use 'cortex.world)
402 (use 'cortex.import)
403 (use 'clojure.contrib.def)
406 (cortex.import/mega-import-jme3)
407 (rlm.rlm-commands/help)
408 (use '[hello [brick-wall :only [fire-cannon-ball brick-wall*]]])
411 (defn environment []
412 (let
413 [scene-model
414 (doto
415 (.loadModel
416 (doto (asset-manager)
417 (.registerLocator
418 "/home/r/cortex/assets/zips/town.zip" ZipLocator))
419 "main.scene")
420 (.setLocalScale (float 2.0)))
421 collision-shape
422 (CollisionShapeFactory/createMeshShape #^Node scene-model)
423 landscape (RigidBodyControl. collision-shape 0)]
424 (.setShadowMode scene-model RenderQueue$ShadowMode/CastAndReceive)
425 (.addControl scene-model landscape)
426 scene-model))
428 (defn player-fn []
429 (doto
430 (CharacterControl.
431 (CapsuleCollisionShape. (float 1.5) (float 6)(float 1))
432 (float 0.05))
433 (.setJumpSpeed 20)
434 (.setFallSpeed 30)
435 (.setGravity 30) ;30
436 (.setPhysicsLocation (Vector3f. 0 10 0))))
438 (defn lights []
439 [(doto (AmbientLight.) (.setColor (.mult (ColorRGBA. 1 1 1 1) (float 1))))
440 (doto (AmbientLight.) (.setColor (.mult (ColorRGBA. 1 0.7 0 1) (float 1))))
441 (doto (DirectionalLight.)
442 (.setColor (.mult ColorRGBA/White (float 0.9) ))
443 (.setDirection (.normalizeLocal (Vector3f. 2.8 -28 2.8))))])
445 (defn night-lights []
446 [(doto (AmbientLight.) (.setColor (.mult (ColorRGBA. 0.275 0.467 0.784 1) (float 0.3))))
447 (doto (DirectionalLight.)
448 (.setColor (.mult ColorRGBA/White (float 0.2) ))
449 (.setDirection (.normalizeLocal (Vector3f. 2.8 -28 2.8))))])
451 (def player (atom (player-fn)))
453 (defn setup-fn [game]
454 (dorun (map #(.addLight (.getRootNode game) %) (lights)))
455 ;; set the color of the sky
456 (.setBackgroundColor (.getViewPort game) (ColorRGBA. 0.3 0.4 0.9 1))
457 ;(.setBackgroundColor (.getViewPort game) (ColorRGBA. 0 0 0 1)
458 (doto (.getFlyByCamera game)
459 (.setMoveSpeed (float 100))
460 (.setRotationSpeed 3))
461 (.add
462 (.getPhysicsSpace
463 (.getState (.getStateManager game) BulletAppState))
464 @player)
466 (doto (Node.) (.attachChild (.getRootNode game))
467 (.attachChild (brick-wall*))
468 )
470 )
473 (def walking-up? (atom false))
474 (def walking-down? (atom false))
475 (def walking-left? (atom false))
476 (def walking-right? (atom false))
478 (defn set-walk [walk-atom game value]
479 ;;(println-repl "setting stuff to " value)
480 (reset! walk-atom value))
482 (defn responses []
483 {"key-w" (partial set-walk walking-up?)
484 "key-d" (partial set-walk walking-right?)
485 "key-s" (partial set-walk walking-down?)
486 "key-a" (partial set-walk walking-left?)
487 "key-return" (fire-cannon-ball)
488 "key-space" (fn [game value] (.jump @player))
489 })
491 (defn update-fn
492 [game tpf]
493 (let [camera (.getCamera game)
494 cam-dir (.multLocal
495 (.clone
496 (.getDirection camera)) (float 0.6))
497 cam-left (.multLocal
498 (.clone
499 (.getLeft camera)) (float 0.4))
500 walk-direction (Vector3f. 0 0 0)]
502 (cond
503 @walking-up? (.addLocal walk-direction cam-dir)
504 @walking-right? (.addLocal walk-direction (.negate cam-left))
505 @walking-down? (.addLocal walk-direction (.negate cam-dir))
506 @walking-left? (.addLocal walk-direction cam-left))
507 (.setWalkDirection @player walk-direction)
508 (.setLocation camera (.getPhysicsLocation @player))))
510 (defn run-game []
511 (.start
512 (world (environment)
513 (responses)
514 setup-fn
515 update-fn)))
516 #+end_src
518 *** Hello Terrain
519 #+srcname: hello-terrain
520 #+begin_src clojure :results silent
521 (ns hello.terrain)
522 (use 'cortex.world)
523 (use 'cortex.import)
524 (use 'clojure.contrib.def)
525 (import jme3tools.converters.ImageToAwt)
528 (cortex.import/mega-import-jme3)
529 (rlm.rlm-commands/help)
530 (use '[hello [brick-wall :only [fire-cannon-ball brick-wall*]]])
533 (defn setup-fn [type game]
534 (.setMoveSpeed (.getFlyByCamera game) 50)
535 (.setFrustumFar (.getCamera game) 10000)
536 (let [env (environment type)
537 cameras [(.getCamera game)]
538 control (TerrainLodControl. env cameras)]
539 ;;(.addControl env control)
540 (.attachChild (.getRootNode game) env)))
542 (defn environment [type]
543 (let
544 [mat_terrain
545 (Material. (asset-manager) "Common/MatDefs/Terrain/Terrain.j3md")
546 grass (.loadTexture (asset-manager) "Textures/Terrain/splat/grass.jpg")
547 dirt (.loadTexture (asset-manager) "Textures/Terrain/splat/dirt.jpg")
548 rock (.loadTexture (asset-manager) "Textures/Terrain/splat/road.jpg")
549 heightmap-image (.loadTexture (asset-manager)
550 ({:mountain "Textures/Terrain/splat/mountains512.png"
551 :fortress "Textures/Terrain/splat/fortress512.png"
552 }type))
553 heightmap (ImageBasedHeightMap.
554 (ImageToAwt/convert (.getImage heightmap-image) false true 0))
555 terrain (do (.load heightmap)
556 (TerrainQuad. "my terrain" 65 513 (.getHeightMap heightmap)))
557 ]
559 (dorun (map #(.setWrap % Texture$WrapMode/Repeat)
560 [grass dirt rock]))
562 (doto mat_terrain
563 (.setTexture "Tex1" grass)
564 (.setFloat "Tex1Scale" (float 64))
566 (.setTexture "Tex2" dirt)
567 (.setFloat "Tex2Scale" (float 32))
569 (.setTexture "Tex3" rock)
570 (.setFloat "Tex3Scale" (float 128))
572 (.setTexture "Alpha"
573 (.loadTexture
574 (asset-manager)
575 ({:mountain "Textures/Terrain/splat/alphamap.png"
576 :fortress "Textures/Terrain/splat/alphamap2.png"} type))))
578 (doto terrain
579 (.setMaterial mat_terrain)
580 (.setLocalTranslation 0 -100 0)
581 (.setLocalScale 2 1 2))))
585 (defn run-terrain-game [type]
586 (.start
587 (world
588 (Node.)
589 {}
590 (partial setup-fn type)
591 no-op)))
592 #+end_src
596 #+srcname: hello-animation
597 #+begin_src clojure :results silent
598 (ns hello.animation)
599 (use 'cortex.world)
600 (use 'cortex.import)
601 (use 'clojure.contrib.def)
602 (cortex.import/mega-import-jme3)
603 (rlm.rlm-commands/help)
604 (use '[hello [collision :only [lights]]])
606 (defn stand
607 [channel]
608 (doto channel
609 (.setAnim "stand" (float 0.5))
610 (.setLoopMode LoopMode/DontLoop)
611 (.setSpeed (float 1))))
613 (defn anim-listener []
614 (proxy [AnimEventListener] []
615 (onAnimChange
616 [control channel animation-name]
617 (println-repl "RLM --- onAnimChange"))
618 (onAnimCycleDone
619 [control channel animation-name]
620 (if (= animation-name "Walk")
621 (stand channel)
622 ))))
624 (defn setup-fn [channel game]
625 (dorun (map #(.addLight (.getRootNode game) %) (lights)))
626 ;; set the color of the sky
627 (.setBackgroundColor (.getViewPort game) (ColorRGBA. 0.3 0.4 0.9 1))
628 ;(.setBackgroundColor (.getViewPort game) (ColorRGBA. 0 0 0 1)
629 (.setAnim channel "stand")
630 (doto (.getFlyByCamera game)
631 (.setMoveSpeed (float 10))
632 (.setRotationSpeed 1)))
634 (defn walk [channel]
635 (println-repl "zzz")
636 (doto channel
637 (.setAnim "Walk" (float 0.5))
638 (.setLoopMode LoopMode/Loop)))
641 (defn key-map [channel]
642 {"key-space" (fn [game value]
643 (if (not value)
644 (walk channel)))})
646 (defn player []
647 (let [model (.loadModel (asset-manager) "Models/Oto/Oto.mesh.xml")
648 control (.getControl model AnimControl)]
649 (.setLocalScale model (float 0.5))
650 (.clearListeners control)
651 (.addListener control (anim-control))
652 model))
656 (defn run-anim-game []
657 (let [ninja (player)
658 control (.getControl ninja AnimControl)
659 channel (.createChannel control)]
660 (.start
661 (world
662 ninja
663 (key-map channel)
664 (partial setup-fn channel)
665 no-op))))
666 #+end_src
668 *** Hello Materials
669 #+srcname: material
670 #+begin_src clojure :results silent
671 (ns hello.material)
672 (use 'cortex.world)
673 (use 'cortex.import)
674 (use 'clojure.contrib.def)
675 (cortex.import/mega-import-jme3)
676 (rlm.rlm-commands/help)
678 (defn simple-cube []
679 (box 1 1 1
680 :position (Vector3f. -3 1.1 0)
681 :material "Common/MatDefs/Misc/Unshaded.j3md"
682 :texture "Interface/Logo/Monkey.jpg"
683 :physical? false))
685 (defn leaky-box []
686 (box 1 1 1
687 :position (Vector3f. 3 -1 0)
688 :material "Common/MatDefs/Misc/ColoredTextured.j3md"
689 :texture "Textures/ColoredTex/Monkey.png"
690 :color (ColorRGBA. 1 0 1 1)
691 :physical? false))
693 (defn transparent-box []
694 (doto
695 (box 1 1 0.1
696 :position Vector3f/ZERO
697 :name "window frame"
698 :material "Common/MatDefs/Misc/Unshaded.j3md"
699 :texture "Textures/ColoredTex/Monkey.png"
700 :physical? false)
701 (-> (.getMaterial)
702 (.getAdditionalRenderState)
703 (.setBlendMode RenderState$BlendMode/Alpha))
704 (.setQueueBucket RenderQueue$Bucket/Transparent)))
706 (defn bumpy-sphere []
707 (doto
708 (sphere 2
709 :position (Vector3f. 0 2 -2)
710 :name "Shiny rock"
711 :material "Common/MatDefs/Light/Lighting.j3md"
712 :texture false
713 :physical? false)
714 (-> (.getMesh)
715 (doto
716 (.setTextureMode Sphere$TextureMode/Projected)
717 (TangentBinormalGenerator/generate)))
718 (-> (.getMaterial)
719 (doto
720 (.setTexture "DiffuseMap" (.loadTexture (asset-manager)
721 "Textures/Terrain/Pond/Pond.png"))
722 (.setTexture "NormalMap" (.loadTexture (asset-manager)
723 "Textures/Terrain/Pond/Pond_normal.png"))
724 (.setFloat "Shininess" (float 5))))
725 (.rotate (float 1.6) 0 0)))
728 (defn start-game []
729 (.start
730 (world
731 (let [root (Node.)]
732 (dorun (map #(.attachChild root %)
733 [(simple-cube) (leaky-box) (transparent-box) (bumpy-sphere)]))
734 root)
735 {}
736 (fn [world]
737 (let [sun (doto (DirectionalLight.)
738 (.setDirection (.normalizeLocal (Vector3f. 1 0 -2)))
739 (.setColor ColorRGBA/White))]
740 (.addLight (.getRootNode world) sun)))
741 no-op
742 )))
743 #+end_src
747 * The Body
748 ** Eyes
750 Ultimately I want to make creatures with eyes. Each eye can be
751 independely moved and should see its own version of the world
752 depending on where it is.
753 #+srcname: eyes
754 #+begin_src clojure
755 (ns body.eye)
756 (use 'cortex.world)
757 (use 'cortex.import)
758 (use 'clojure.contrib.def)
759 (cortex.import/mega-import-jme3)
760 (rlm.rlm-commands/help)
761 (import java.nio.ByteBuffer)
762 (import java.awt.image.BufferedImage)
763 (import java.awt.Color)
764 (import java.awt.Dimension)
765 (import java.awt.Graphics)
766 (import java.awt.Graphics2D)
767 (import java.awt.event.WindowAdapter)
768 (import java.awt.event.WindowEvent)
769 (import java.awt.image.BufferedImage)
770 (import java.nio.ByteBuffer)
771 (import javax.swing.JFrame)
772 (import javax.swing.JPanel)
773 (import javax.swing.SwingUtilities)
774 (import javax.swing.ImageIcon)
775 (import javax.swing.JOptionPane)
776 (import java.awt.image.ImageObserver)
780 (defn scene-processor
781 "deals with converting FrameBuffers to BufferedImages so
782 that the continuation function can be defined only in terms
783 of what it does with BufferedImages"
784 [continuation]
785 (let [byte-buffer (atom nil)
786 renderer (atom nil)
787 image (atom nil)]
788 (proxy [SceneProcessor] []
789 (initialize
790 [renderManager viewPort]
791 (let [cam (.getCamera viewPort)
792 width (.getWidth cam)
793 height (.getHeight cam)]
794 (reset! renderer (.getRenderer renderManager))
795 (reset! byte-buffer
796 (BufferUtils/createByteBuffer
797 (* width height 4)))
798 (reset! image (BufferedImage. width height
799 BufferedImage/TYPE_4BYTE_ABGR))))
800 (isInitialized [] (not (nil? @byte-buffer)))
801 (reshape [_ _ _])
802 (preFrame [_])
803 (postQueue [_])
804 (postFrame
805 [#^FrameBuffer fb]
806 (.clear @byte-buffer)
807 (.readFrameBuffer @renderer fb @byte-buffer)
808 (Screenshots/convertScreenShot @byte-buffer @image)
809 (continuation @image))
810 (cleanup []))))
812 (defn add-eye
813 "Add an eye to the world, and call continuation on
814 every frame produced"
815 [world camera continuation]
816 (let [width (.getWidth camera)
817 height (.getHeight camera)
818 render-manager (.getRenderManager world)
819 viewport (.createMainView render-manager "eye-view" camera)]
820 (doto viewport
821 (.setBackgroundColor ColorRGBA/Black)
822 (.setClearFlags true true true)
823 (.addProcessor (scene-processor continuation))
824 (.attachScene (.getRootNode world)))))
826 (defn make-display-frame [display width height]
827 (SwingUtilities/invokeLater
828 (fn []
829 (.setPreferredSize display (Dimension. width height))
830 (doto (JFrame. "Eye Camera!")
831 (-> (.getContentPane) (.add display))
832 (.setDefaultCloseOperation JFrame/DISPOSE_ON_CLOSE)
833 (.pack)
834 (.setLocationRelativeTo nil)
835 (.setResizable false)
836 (.setVisible true)))))
838 (defn image-monitor [#^BufferedImage image]
839 (proxy [JPanel] []
840 (paintComponent
841 [g]
842 (proxy-super paintComponent g)
843 (locking image
844 (.drawImage g image 0 0
845 (proxy [ImageObserver]
846 []
847 (imageUpdate
848 []
849 (proxy-super imageUpdate))))))))
851 (defn movie-image []
852 (let [setup
853 (runonce
854 (fn [#^BufferedImage image]
855 (let [width (.getWidth image)
856 height (.getHeight image)
857 display (image-monitor image)
858 frame (make-display-frame display width height)]
859 display)))]
860 (fn [#^BufferedImage image]
861 (.repaint (setup image)))))
864 (defn observer
865 "place thy eye!"
866 [world camera]
867 (let [eye camera
868 width (.getWidth eye)
869 height (.getHeight eye)]
870 (no-exceptions
871 (add-eye
872 world
873 eye
874 (movie-image)))))
875 #+end_src
877 #+srcname: test-vision
878 #+begin_src clojure
880 (ns test.vision)
881 (use 'cortex.world)
882 (use 'cortex.import)
883 (use 'clojure.contrib.def)
884 (use 'body.eye)
885 (cortex.import/mega-import-jme3)
886 (rlm.rlm-commands/help)
887 (import java.nio.ByteBuffer)
888 (import java.awt.image.BufferedImage)
889 (import java.awt.Color)
890 (import java.awt.Dimension)
891 (import java.awt.Graphics)
892 (import java.awt.Graphics2D)
893 (import java.awt.event.WindowAdapter)
894 (import java.awt.event.WindowEvent)
895 (import java.awt.image.BufferedImage)
896 (import java.nio.ByteBuffer)
897 (import javax.swing.JFrame)
898 (import javax.swing.JPanel)
899 (import javax.swing.SwingUtilities)
900 (import javax.swing.ImageIcon)
901 (import javax.swing.JOptionPane)
902 (import java.awt.image.ImageObserver)
905 (def width 200)
906 (def height 200)
908 (defn camera []
909 (doto (Camera. width height)
910 (.setFrustumPerspective 45 1 1 1000)
911 (.setLocation (Vector3f. -3 0 -5))
912 (.lookAt Vector3f/ZERO Vector3f/UNIT_Y)))
914 (defn camera2 []
915 (doto (Camera. width height)
916 (.setFrustumPerspective 45 1 1 1000)
917 (.setLocation (Vector3f. 3 0 -5))
918 (.lookAt Vector3f/ZERO Vector3f/UNIT_Y)))
920 (defn setup-fn [world]
921 (let [eye (camera)
922 width (.getWidth eye)
923 height (.getHeight eye)]
924 (no-exceptions
925 (add-eye
926 world
927 eye
928 (runonce visual))
929 (add-eye
930 world
931 (camera2)
932 (runonce visual)))))
934 (defn spider-eye [position]
935 (doto (Camera. 200 200 )
936 (.setFrustumPerspective 45 1 1 1000)
937 (.setLocation position)
938 (.lookAt Vector3f/ZERO Vector3f/UNIT_Y)))
940 (defn setup-fn* [world]
941 (let [eye (camera)
942 width (.getWidth eye)
943 height (.getHeight eye)]
944 ;;(.setClearFlags (.getViewPort world) true true true)
945 (observer world (.getCamera world))
946 (observer world (spider-eye (Vector3f. 3 0 -5)))
947 ;;(observer world (spider-eye (Vector3f. 0 0 -5)))
948 ;; (observer world (spider-eye (Vector3f. -3 0 -5)))
949 ;; (observer world (spider-eye (Vector3f. 0 3 -5)))
950 ;; (observer world (spider-eye (Vector3f. 0 -3 -5)))
951 ;; (observer world (spider-eye (Vector3f. 3 3 -5)))
952 ;; (observer world (spider-eye (Vector3f. -3 3 -5)))
953 ;; (observer world (spider-eye (Vector3f. 3 -3 -5)))
954 ;; (observer world (spider-eye (Vector3f. -3 -3 -5)))
956 )
957 world)
959 (defn test-world []
960 (let [thing (box 1 1 1 :physical? false)]
961 (world
962 (doto (Node.)
963 (.attachChild thing))
964 {}
965 setup-fn
966 (fn [world tpf]
967 (.rotate thing (* tpf 0.2) 0 0)
968 ))))
971 #+end_src
974 #+results: eyes
975 : #'body.eye/test-world
977 Note the use of continuation passing style for connecting the eye to a
978 function to process the output. The example code will create two
979 videos of the same rotating cube from different angles, sutiable for
980 stereoscopic vision.
987 * COMMENT code generation
988 #+begin_src clojure :tangle ../src/cortex/import.clj
989 <<import>>
990 #+end_src
992 #+begin_src clojure :tangle ../src/hello/brick_wall.clj
993 <<brick-wall-header>>
994 <<brick-wall-body>>
995 #+end_src
997 #+begin_src clojure :tangle ../src/hello/hello_simple_app.clj
998 <<hello-simple-app>>
999 #+end_src
1001 #+begin_src clojure :tangle ../src/cortex/world.clj
1002 <<world-inputs>>
1003 <<world>>
1004 <<world-shapes>>
1005 <<world-view>>
1006 #+end_src
1008 #+begin_src clojure :tangle ../src/cortex/other_games.clj
1009 <<other-games>>
1010 #+end_src
1012 #+begin_src clojure :tangle ../src/hello/loop.clj
1013 <<hello-loop>>
1014 #+end_src
1016 #+begin_src clojure :tangle ../src/hello/collision.clj
1017 <<hello-collision>>
1018 #+end_src
1020 #+begin_src clojure :tangle ../src/hello/terrain.clj
1021 <<hello-terrain>>
1022 #+end_src
1024 #+begin_src clojure :tangle ../src/hello/animation.clj
1025 <<hello-animation>>
1026 #+end_src
1028 #+begin_src clojure :tangle ../src/hello/material.clj
1029 <<material>>
1030 #+end_src
1032 #+begin_src clojure :tangle ../src/body/eye.clj
1033 <<eyes>>
1034 #+end_src
1036 #+begin_src clojure :tangle ../src/test/vision.clj
1037 <<test-vision>>
1038 #+end_src