annotate org/util.org @ 25:775d97247dd0

cleaning up world.org
author Robert McIntyre <rlm@mit.edu>
date Mon, 24 Oct 2011 05:25:01 -0700
parents e965675ec4d0
children bbffa41a12a9
rev   line source
rlm@23 1 #+title: Helper Utilities
rlm@23 2 #+author: Robert McIntyre
rlm@23 3 #+email: rlm@mit.edu
rlm@23 4 #+description: Simulating senses for AI research using JMonkeyEngine3
rlm@23 5 #+SETUPFILE: ../../aurellem/org/setup.org
rlm@23 6 #+INCLUDE: ../../aurellem/org/level-0.org
rlm@23 7 #+babel: :mkdirp yes :noweb yes :exports both
rlm@23 8
rlm@23 9 ** Imports
rlm@23 10 jMonkeyEngine has a plethora of classes which can be overwhelming at
rlm@23 11 first. So that I one can get right to coding, it's good to take the
rlm@23 12 time right now and make a "import all" function which brings in all of
rlm@23 13 the important jme3 classes. Once I'm happy with the general structure
rlm@23 14 of a namespace I can deal with importing only the classes it actually
rlm@23 15 needs.
rlm@23 16
rlm@23 17 #+srcname: import
rlm@23 18 #+begin_src clojure :results silent
rlm@23 19 (ns cortex.import
rlm@23 20 (:require swank.util.class-browse))
rlm@23 21
rlm@23 22 (defn permissive-import
rlm@23 23 [classname]
rlm@23 24 (eval `(try (import '~classname)
rlm@23 25 (catch java.lang.Exception e#
rlm@23 26 (println "couldn't import " '~classname))))
rlm@23 27 classname)
rlm@23 28
rlm@23 29 (defn jme-class? [classname]
rlm@23 30 (and
rlm@23 31 (.startsWith classname "com.jme3.")
rlm@23 32 ;; Don't import the Lwjgl stuff since it can throw exceptions
rlm@23 33 ;; upon being loaded.
rlm@23 34 (not (re-matches #".*Lwjgl.*" classname))))
rlm@23 35
rlm@23 36 (defn jme-classes
rlm@23 37 "returns a list of all jme3 classes"
rlm@23 38 []
rlm@23 39 (filter
rlm@23 40 jme-class?
rlm@23 41 (map :name
rlm@23 42 swank.util.class-browse/available-classes)))
rlm@23 43
rlm@23 44 (defn mega-import-jme3
rlm@23 45 "Import ALL the jme classes. For REPL use."
rlm@23 46 []
rlm@23 47 (doall
rlm@23 48 (map (comp permissive-import symbol) (jme-classes))))
rlm@23 49 #+end_src
rlm@23 50
rlm@23 51 The =mega-import-jme3= is quite usefull for debugging purposes since
rlm@23 52 it allows completion for almost all of JME's classes.
rlm@23 53
rlm@23 54 Out of curiousity, let's see just how many classes =mega-import-jme3=
rlm@23 55 imports:
rlm@23 56
rlm@23 57 #+begin_src clojure :exports both
rlm@23 58 (clojure.core/count (cortex.import/jme-classes))
rlm@23 59 #+end_src
rlm@23 60
rlm@23 61 #+results:
rlm@23 62 : 955
rlm@23 63
rlm@25 64
rlm@23 65 #+srcname: world-view
rlm@23 66 #+begin_src clojure :results silent
rlm@25 67 (ns cortex.util)
rlm@25 68 (require 'cortex.import)
rlm@25 69 (cortex.import/mega-import-jme3)
rlm@25 70 (use 'cortex.world)
rlm@23 71 (defprotocol Viewable
rlm@23 72 (view [something]))
rlm@23 73
rlm@23 74 (extend-type com.jme3.scene.Geometry
rlm@23 75 Viewable
rlm@23 76 (view [geo]
rlm@23 77 (view (doto (Node.)(.attachChild geo)))))
rlm@23 78
rlm@23 79 (extend-type com.jme3.scene.Node
rlm@23 80 Viewable
rlm@23 81 (view [node]
rlm@23 82 (.start
rlm@23 83 (world node
rlm@23 84 {}
rlm@23 85 (fn [world]
rlm@23 86 (.enableDebug
rlm@23 87 (.getPhysicsSpace
rlm@23 88 (.getState
rlm@23 89 (.getStateManager world)
rlm@23 90 BulletAppState))
rlm@23 91 (asset-manager))
rlm@23 92 (set-gravity* world Vector3f/ZERO)
rlm@23 93 ;; (set-gravity* world (Vector3f. 0 (float -0.4) 0))
rlm@23 94 (let [sun (doto (DirectionalLight.)
rlm@23 95 (.setDirection (.normalizeLocal (Vector3f. 1 0 -2)))
rlm@23 96 (.setColor ColorRGBA/White))]
rlm@23 97 (.addLight (.getRootNode world) sun)))
rlm@23 98 no-op))))
rlm@23 99 #+end_src
rlm@23 100
rlm@23 101 Here I make the =Viewable= protocol and extend it to JME's types. Now
rlm@23 102 hello-world can be written as easily as:
rlm@23 103
rlm@23 104 #+begin_src clojure :results silent
rlm@23 105 (cortex.world/view (cortex.world/box))
rlm@23 106 #+end_src
rlm@24 107
rlm@24 108
rlm@25 109 #+srcname: util
rlm@25 110 #+begin_src clojure
rlm@25 111 (in-ns 'cortex.util)
rlm@25 112
rlm@25 113 (def println-repl (bound-fn [& args] (apply println args)))
rlm@25 114
rlm@25 115 (defn position-camera [game]
rlm@25 116 (doto (.getCamera game)
rlm@25 117 (.setLocation (Vector3f. 0 6 6))
rlm@25 118 (.lookAt Vector3f/ZERO (Vector3f. 0 1 0))))
rlm@25 119
rlm@25 120 (defn set-gravity*
rlm@25 121 [game gravity]
rlm@25 122 (traverse
rlm@25 123 (fn [geom]
rlm@25 124 (if-let
rlm@25 125 [control (.getControl geom RigidBodyControl)]
rlm@25 126 (do
rlm@25 127 (.setGravity control gravity)
rlm@25 128 (.applyImpulse control Vector3f/ZERO Vector3f/ZERO)
rlm@25 129 )))
rlm@25 130 (.getRootNode game)))
rlm@25 131 #+end_src
rlm@25 132
rlm@25 133
rlm@25 134 #+srcname: shapes
rlm@25 135 #+begin_src clojure :results silent
rlm@25 136 (in-ns 'cortex.util)
rlm@25 137 (defrecord shape-description
rlm@25 138 [name
rlm@25 139 color
rlm@25 140 mass
rlm@25 141 friction
rlm@25 142 texture
rlm@25 143 material
rlm@25 144 position
rlm@25 145 rotation
rlm@25 146 shape
rlm@25 147 physical?])
rlm@25 148
rlm@25 149 (def base-shape
rlm@25 150 (shape-description.
rlm@25 151 "default-shape"
rlm@25 152 false
rlm@25 153 ;;ColorRGBA/Blue
rlm@25 154 1.0 ;; mass
rlm@25 155 1.0 ;; friction
rlm@25 156 ;; texture
rlm@25 157 "Textures/Terrain/BrickWall/BrickWall.jpg"
rlm@25 158 ;; material
rlm@25 159 "Common/MatDefs/Misc/Unshaded.j3md"
rlm@25 160 Vector3f/ZERO
rlm@25 161 Quaternion/IDENTITY
rlm@25 162 (Box. Vector3f/ZERO 0.5 0.5 0.5)
rlm@25 163 true))
rlm@25 164
rlm@25 165 (defn make-shape
rlm@25 166 [#^shape-description d]
rlm@25 167 (let [asset-manager (if (:asset-manager d) (:asset-manager d) (asset-manager))
rlm@25 168 mat (Material. asset-manager (:material d))
rlm@25 169 geom (Geometry. (:name d) (:shape d))]
rlm@25 170 (if (:texture d)
rlm@25 171 (let [key (TextureKey. (:texture d))]
rlm@25 172 (.setGenerateMips key true)
rlm@25 173 (.setTexture mat "ColorMap" (.loadTexture asset-manager key))))
rlm@25 174 (if (:color d) (.setColor mat "Color" (:color d)))
rlm@25 175 (.setMaterial geom mat)
rlm@25 176 (if-let [rotation (:rotation d)] (.rotate geom rotation))
rlm@25 177 (.setLocalTranslation geom (:position d))
rlm@25 178 (if (:physical? d)
rlm@25 179 (let [impact-shape (doto (GImpactCollisionShape.
rlm@25 180 (.getMesh geom)) (.setMargin 0))
rlm@25 181 physics-control (RigidBodyControl.
rlm@25 182 ;;impact-shape ;; comment to disable
rlm@25 183 (float (:mass d)))]
rlm@25 184 (.createJmeMesh impact-shape)
rlm@25 185 (.addControl geom physics-control)
rlm@25 186 ;;(.setSleepingThresholds physics-control (float 0) (float 0))
rlm@25 187 (.setFriction physics-control (:friction d))))
rlm@25 188 ;;the default is to keep this node in the physics engine forever.
rlm@25 189 ;;these commands must come after the control is added to the geometry.
rlm@25 190 ;;
rlm@25 191 geom))
rlm@25 192
rlm@25 193 (defn box
rlm@25 194 ([l w h & {:as options}]
rlm@25 195 (let [options (merge base-shape options)]
rlm@25 196 (make-shape (assoc options
rlm@25 197 :shape (Box. l w h)))))
rlm@25 198 ([] (box 0.5 0.5 0.5)))
rlm@25 199
rlm@25 200 (defn sphere
rlm@25 201 ([r & {:as options}]
rlm@25 202 (let [options (merge base-shape options)]
rlm@25 203 (make-shape (assoc options
rlm@25 204 :shape (Sphere. 32 32 (float r))))))
rlm@25 205 ([] (sphere 0.5)))
rlm@25 206
rlm@25 207 (defn add-element
rlm@25 208 ([game element node]
rlm@25 209 (.addAll
rlm@25 210 (.getPhysicsSpace
rlm@25 211 (.getState
rlm@25 212 (.getStateManager game)
rlm@25 213 BulletAppState))
rlm@25 214 element)
rlm@25 215 (.attachChild node element))
rlm@25 216 ([game element]
rlm@25 217 (add-element game element (.getRootNode game))))
rlm@25 218
rlm@25 219
rlm@25 220
rlm@25 221 #+end_src
rlm@25 222
rlm@25 223
rlm@24 224
rlm@24 225 * COMMENT code generation
rlm@24 226 #+begin_src clojure :tangle ../src/cortex/import.clj
rlm@24 227 <<import>>
rlm@24 228 #+end_src
rlm@25 229
rlm@25 230
rlm@25 231 #+begin_src clojure :tangle ../src/cortex/util.clj
rlm@25 232 <<world-view>>
rlm@25 233 <<util>>
rlm@25 234 <<shapes>>
rlm@25 235 #+end_src
rlm@25 236