Mercurial > cortex
comparison org/util.org @ 29:6372c108c5c6
cleaned up util.org
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Mon, 24 Oct 2011 12:35:15 -0700 |
parents | 122f12f81dc1 |
children | 0206878c28b4 |
comparison
equal
deleted
inserted
replaced
28:122f12f81dc1 | 29:6372c108c5c6 |
---|---|
1 #+title: Helper Utilities | 1 #+title: Clojure Utilities for jMonkeyEngine3 |
2 #+author: Robert McIntyre | 2 #+author: Robert McIntyre |
3 #+email: rlm@mit.edu | 3 #+email: rlm@mit.edu |
4 #+description: Simulating senses for AI research using JMonkeyEngine3 | 4 #+description: |
5 #+keywords: JME3, clojure, import, utilities | |
5 #+SETUPFILE: ../../aurellem/org/setup.org | 6 #+SETUPFILE: ../../aurellem/org/setup.org |
6 #+INCLUDE: ../../aurellem/org/level-0.org | 7 #+INCLUDE: ../../aurellem/org/level-0.org |
7 #+babel: :mkdirp yes :noweb yes :exports both | 8 |
9 * Utilities | |
10 | |
11 These are a collection of functions to make programming jMonkeyEngine | |
12 in clojure easier. | |
8 | 13 |
9 ** Imports | 14 ** Imports |
10 | |
11 jMonkeyEngine has a plethora of classes which can be overwhelming at | |
12 first. So that I one can get right to coding, it's good to take the | |
13 time right now and make a "import all" function which brings in all of | |
14 the important jme3 classes. Once I'm happy with the general structure | |
15 of a namespace I can deal with importing only the classes it actually | |
16 needs. | |
17 | 15 |
18 #+srcname: import | 16 #+srcname: import |
19 #+begin_src clojure :results silent | 17 #+begin_src clojure :results silent |
20 (ns cortex.import | 18 (ns cortex.import |
21 (:require swank.util.class-browse)) | 19 (:require swank.util.class-browse)) |
47 [] | 45 [] |
48 (doall | 46 (doall |
49 (map (comp permissive-import symbol) (jme-classes)))) | 47 (map (comp permissive-import symbol) (jme-classes)))) |
50 #+end_src | 48 #+end_src |
51 | 49 |
50 jMonkeyEngine3 has a plethora of classes which can be overwhelming to | |
51 manage. This code uses reflection to import all of them. Once I'm | |
52 happy with the general structure of a namespace I can deal with | |
53 importing only the classes it actually needs. | |
54 | |
52 The =mega-import-jme3= is quite usefull for debugging purposes since | 55 The =mega-import-jme3= is quite usefull for debugging purposes since |
53 it allows completion for almost all of JME's classes. | 56 it allows completion for almost all of JME's classes. |
54 | 57 |
55 Out of curiousity, let's see just how many classes =mega-import-jme3= | 58 Out of curiousity, let's see just how many classes =mega-import-jme3= |
56 imports: | 59 imports: |
57 | 60 |
58 #+begin_src clojure :exports both | 61 #+begin_src clojure :exports both :results output |
59 (clojure.core/count (cortex.import/jme-classes)) | 62 (println (clojure.core/count (cortex.import/jme-classes)) "classes") |
60 #+end_src | 63 #+end_src |
61 | 64 |
62 #+results: | 65 #+results: |
63 : 955 | 66 : 955 classes |
64 | 67 |
65 | 68 |
66 #+srcname: world-view | 69 ** Utilities |
67 #+begin_src clojure :results silent | 70 |
68 (ns cortex.util) | 71 The utilities here come in three main groups: |
69 (require 'cortex.import) | 72 - Changing settings in a running =Application= |
70 (cortex.import/mega-import-jme3) | 73 - Creating objects |
71 (use 'cortex.world) | 74 - Visualizing objects |
72 (defprotocol Viewable | 75 |
73 (view [something])) | 76 |
74 | 77 *** Changing Settings |
75 (extend-type com.jme3.scene.Geometry | |
76 Viewable | |
77 (view [geo] | |
78 (view (doto (Node.)(.attachChild geo))))) | |
79 | |
80 (extend-type com.jme3.scene.Node | |
81 Viewable | |
82 (view [node] | |
83 (.start | |
84 (world node | |
85 {} | |
86 (fn [world] | |
87 (.enableDebug | |
88 (.getPhysicsSpace | |
89 (.getState | |
90 (.getStateManager world) | |
91 BulletAppState)) | |
92 (asset-manager)) | |
93 (set-gravity* world Vector3f/ZERO) | |
94 ;; (set-gravity* world (Vector3f. 0 (float -0.4) 0)) | |
95 (let [sun (doto (DirectionalLight.) | |
96 (.setDirection (.normalizeLocal (Vector3f. 1 0 -2))) | |
97 (.setColor ColorRGBA/White))] | |
98 (.addLight (.getRootNode world) sun))) | |
99 no-op)))) | |
100 #+end_src | |
101 | |
102 Here I make the =Viewable= protocol and extend it to JME's types. Now | |
103 hello-world can be written as easily as: | |
104 | |
105 #+begin_src clojure :results silent | |
106 (cortex.world/view (cortex.world/box)) | |
107 #+end_src | |
108 | |
109 | 78 |
110 #+srcname: util | 79 #+srcname: util |
111 #+begin_src clojure | 80 #+begin_src clojure |
112 (in-ns 'cortex.util) | 81 (ns cortex.util |
113 | 82 "Utility functions for making jMonkeyEngine easier to program from |
114 (def println-repl (bound-fn [& args] (apply println args))) | 83 clojure" |
115 | 84 {:author "Robert McIntyre"} |
116 (defn position-camera [game] | 85 (:use cortex.world) |
117 (doto (.getCamera game) | 86 (:use clojure.contrib.def) |
118 (.setLocation (Vector3f. 0 6 6)) | 87 (:import com.jme3.math.Vector3f) |
119 (.lookAt Vector3f/ZERO (Vector3f. 0 1 0)))) | 88 (:import com.jme3.math.Quaternion) |
120 | 89 (:import com.jme3.asset.TextureKey) |
121 (defn set-gravity* | 90 (:import com.jme3.bullet.control.RigidBodyControl) |
91 (:import com.jme3.bullet.collision.shapes.GImpactCollisionShape) | |
92 (:import com.jme3.scene.shape.Box) | |
93 (:import com.jme3.scene.Node) | |
94 (:import com.jme3.scene.shape.Sphere) | |
95 (:import com.jme3.light.DirectionalLight) | |
96 (:import com.jme3.math.ColorRGBA) | |
97 (:import com.jme3.bullet.BulletAppState) | |
98 (:import com.jme3.material.Material) | |
99 (:import com.jme3.scene.Geometry)) | |
100 | |
101 (defvar println-repl | |
102 (bound-fn [& args] (apply println args)) | |
103 "println called from the LWJGL thread will not go to the REPL, but | |
104 instead to whatever terminal started the JVM process. This function | |
105 will always output to the REPL") | |
106 | |
107 (defn position-camera | |
108 ([game position direction up] | |
109 (doto (.getCamera game) | |
110 (.setLocation ) | |
111 (.lookAt direction up))) | |
112 ([game position direction] | |
113 (position-camera | |
114 game position direction Vector3f/UNIT_Y))) | |
115 | |
116 (defn enable-debug | |
117 "Turn on the debug wireframes for every object in this simulation" | |
118 [world] | |
119 (.enableDebug | |
120 (.getPhysicsSpace | |
121 (.getState | |
122 (.getStateManager world) | |
123 BulletAppState)) | |
124 (asset-manager))) | |
125 | |
126 (defn set-gravity | |
127 "In order to change the gravity of a scene, it is not only necessary | |
128 to set the gravity variable, but to \"tap\" every physics object in | |
129 the scene to reactivate physics calculations." | |
122 [game gravity] | 130 [game gravity] |
123 (traverse | 131 (traverse |
124 (fn [geom] | 132 (fn [geom] |
125 (if-let | 133 (if-let |
134 ;; only set gravity for physical objects. | |
126 [control (.getControl geom RigidBodyControl)] | 135 [control (.getControl geom RigidBodyControl)] |
127 (do | 136 (do |
128 (.setGravity control gravity) | 137 (.setGravity control gravity) |
129 (.applyImpulse control Vector3f/ZERO Vector3f/ZERO) | 138 ;; tappsies! |
130 ))) | 139 (.applyImpulse control Vector3f/ZERO Vector3f/ZERO)))) |
131 (.getRootNode game))) | 140 (.getRootNode game))) |
132 #+end_src | 141 |
133 | 142 (defn add-element |
143 "Add the Spatial to the game's environment" | |
144 ([game element node] | |
145 (.addAll | |
146 (.getPhysicsSpace | |
147 (.getState | |
148 (.getStateManager game) | |
149 BulletAppState)) | |
150 element) | |
151 (.attachChild node element)) | |
152 ([game element] | |
153 (add-element game element (.getRootNode game)))) | |
154 | |
155 (defn apply-map | |
156 "Like apply, but works for maps and functions that expect an | |
157 implicit map and nothing else as in (fn [& {}]). | |
158 ------- Example ------- | |
159 (defn demo [& {:keys [www] :or {www \"oh yeah\"} :as env}] | |
160 (println www)) | |
161 (apply-map demo {:www \"hello!\"}) | |
162 -->\"hello\"" | |
163 [fn m] | |
164 (apply fn (reduce #(into %1 %2) [] m))) | |
165 | |
166 #+end_src | |
167 | |
168 | |
169 *** Creating Basic Shapes | |
134 | 170 |
135 #+srcname: shapes | 171 #+srcname: shapes |
136 #+begin_src clojure :results silent | 172 #+begin_src clojure :results silent |
137 (in-ns 'cortex.util) | 173 (in-ns 'cortex.util) |
174 | |
138 (defrecord shape-description | 175 (defrecord shape-description |
139 [name | 176 [name |
140 color | 177 color |
141 mass | 178 mass |
142 friction | 179 friction |
143 texture | 180 texture |
144 material | 181 material |
145 position | 182 position |
146 rotation | 183 rotation |
147 shape | 184 shape |
148 physical?]) | 185 physical? |
186 GImpact? | |
187 ]) | |
149 | 188 |
150 (def base-shape | 189 (def base-shape |
151 (shape-description. | 190 (shape-description. |
152 "default-shape" | 191 "default-shape" |
153 false | 192 false |
159 ;; material | 198 ;; material |
160 "Common/MatDefs/Misc/Unshaded.j3md" | 199 "Common/MatDefs/Misc/Unshaded.j3md" |
161 Vector3f/ZERO | 200 Vector3f/ZERO |
162 Quaternion/IDENTITY | 201 Quaternion/IDENTITY |
163 (Box. Vector3f/ZERO 0.5 0.5 0.5) | 202 (Box. Vector3f/ZERO 0.5 0.5 0.5) |
164 true)) | 203 true |
204 false)) | |
165 | 205 |
166 (defn make-shape | 206 (defn make-shape |
167 [#^shape-description d] | 207 [#^shape-description d] |
168 (let [asset-manager (if (:asset-manager d) (:asset-manager d) (asset-manager)) | 208 (let [asset-manager (asset-manager) |
169 mat (Material. asset-manager (:material d)) | 209 mat (Material. asset-manager (:material d)) |
170 geom (Geometry. (:name d) (:shape d))] | 210 geom (Geometry. (:name d) (:shape d))] |
171 (if (:texture d) | 211 (if (:texture d) |
172 (let [key (TextureKey. (:texture d))] | 212 (let [key (TextureKey. (:texture d))] |
173 (.setGenerateMips key true) | 213 (.setGenerateMips key true) |
175 (if (:color d) (.setColor mat "Color" (:color d))) | 215 (if (:color d) (.setColor mat "Color" (:color d))) |
176 (.setMaterial geom mat) | 216 (.setMaterial geom mat) |
177 (if-let [rotation (:rotation d)] (.rotate geom rotation)) | 217 (if-let [rotation (:rotation d)] (.rotate geom rotation)) |
178 (.setLocalTranslation geom (:position d)) | 218 (.setLocalTranslation geom (:position d)) |
179 (if (:physical? d) | 219 (if (:physical? d) |
180 (let [impact-shape (doto (GImpactCollisionShape. | 220 (let [physics-control |
181 (.getMesh geom)) (.setMargin 0)) | 221 (if (:GImpact d) |
182 physics-control (RigidBodyControl. | 222 ;; Create an accurate mesh collision shape if desired. |
183 ;;impact-shape ;; comment to disable | 223 (RigidBodyControl. |
184 (float (:mass d)))] | 224 (doto (GImpactCollisionShape. |
185 (.createJmeMesh impact-shape) | 225 (.getMesh geom)) |
226 (.createJmeMesh) | |
227 (.setMargin 0)) | |
228 (float (:mass d))) | |
229 ;; otherwise use jme3's default | |
230 (RigidBodyControl. (float (:mass d))))] | |
186 (.addControl geom physics-control) | 231 (.addControl geom physics-control) |
187 ;;(.setSleepingThresholds physics-control (float 0) (float 0)) | 232 ;;(.setSleepingThresholds physics-control (float 0) (float 0)) |
188 (.setFriction physics-control (:friction d)))) | 233 (.setFriction physics-control (:friction d)))) |
189 ;;the default is to keep this node in the physics engine forever. | |
190 ;;these commands must come after the control is added to the geometry. | |
191 ;; | |
192 geom)) | 234 geom)) |
193 | 235 |
194 (defn box | 236 (defn box |
195 ([l w h & {:as options}] | 237 ([l w h & {:as options}] |
196 (let [options (merge base-shape options)] | 238 (let [options (merge base-shape options)] |
202 ([r & {:as options}] | 244 ([r & {:as options}] |
203 (let [options (merge base-shape options)] | 245 (let [options (merge base-shape options)] |
204 (make-shape (assoc options | 246 (make-shape (assoc options |
205 :shape (Sphere. 32 32 (float r)))))) | 247 :shape (Sphere. 32 32 (float r)))))) |
206 ([] (sphere 0.5))) | 248 ([] (sphere 0.5))) |
207 | 249 #+end_src |
208 (defn add-element | 250 |
209 ([game element node] | 251 |
210 (.addAll | 252 *** Viewing Objects |
211 (.getPhysicsSpace | 253 |
212 (.getState | 254 #+srcname: world-view |
213 (.getStateManager game) | 255 #+begin_src clojure :results silent |
214 BulletAppState)) | 256 (in-ns 'cortex.util) |
215 element) | 257 |
216 (.attachChild node element)) | 258 (defprotocol Viewable |
217 ([game element] | 259 (view [something])) |
218 (add-element game element (.getRootNode game)))) | 260 |
219 | 261 (extend-type com.jme3.scene.Geometry |
220 | 262 Viewable |
221 (defn apply-map | 263 (view [geo] |
222 "Like apply, but works for maps and functions that expect an | 264 (view (doto (Node.)(.attachChild geo))))) |
223 implicit map and nothing else as in (fn [& {}]). | 265 |
224 ------- Example ------- | 266 (extend-type com.jme3.scene.Node |
225 (defn demo [& {:keys [www] :or {www \"oh yeah\"} :as env}] | 267 Viewable |
226 (println www)) | 268 (view |
227 (apply-map demo {:www \"hello!\"}) | 269 [node] |
228 -->\"hello\"" | 270 (.start |
229 [fn m] | 271 (world |
230 (apply fn (reduce #(into %1 %2) [] m))) | 272 node |
231 | 273 {} |
232 #+end_src | 274 (fn [world] |
275 (enable-debug world) | |
276 (set-gravity world Vector3f/ZERO) | |
277 (let [sun | |
278 (doto (DirectionalLight.) | |
279 (.setDirection | |
280 (.normalizeLocal (Vector3f. 1 0 -2))) | |
281 (.setColor ColorRGBA/White))] | |
282 (.addLight (.getRootNode world) sun))) | |
283 no-op)))) | |
284 #+end_src | |
285 | |
286 Here I make the =Viewable= protocol and extend it to JME's types. Now | |
287 hello-world can be written as easily as: | |
288 | |
289 #+begin_src clojure :results silent | |
290 (cortex.util/view (cortex.util/box)) | |
291 #+end_src | |
292 | |
233 | 293 |
234 | 294 |
235 | 295 |
236 * COMMENT code generation | 296 * COMMENT code generation |
237 #+begin_src clojure :tangle ../src/cortex/import.clj | 297 #+begin_src clojure :tangle ../src/cortex/import.clj |
238 <<import>> | 298 <<import>> |
239 #+end_src | 299 #+end_src |
240 | 300 |
241 | 301 |
242 #+begin_src clojure :tangle ../src/cortex/util.clj | 302 #+begin_src clojure :tangle ../src/cortex/util.clj :noweb yes |
243 <<world-view>> | |
244 <<util>> | 303 <<util>> |
245 <<shapes>> | 304 <<shapes>> |
246 #+end_src | 305 <<world-view>> |
247 | 306 #+end_src |
307 | |
308 | |
309 | |
310 | |
311 | |
312 | |
313 | |
314 | |
315 | |
316 | |
317 | |
318 | |
319 | |
320 | |
321 | |
322 | |
323 |