comparison org/touch.org @ 233:f27c9fd9134d

seperated out image generating code from touch-kernel
author Robert McIntyre <rlm@mit.edu>
date Sun, 12 Feb 2012 06:21:30 -0700
parents b7762699eeb5
children 712bd7e5b148
comparison
equal deleted inserted replaced
232:b7762699eeb5 233:f27c9fd9134d
58 "Return the touch-sensor distribution image in BufferedImage format, 58 "Return the touch-sensor distribution image in BufferedImage format,
59 or nil if it does not exist." 59 or nil if it does not exist."
60 [#^Geometry obj] 60 [#^Geometry obj]
61 (if-let [image-path (meta-data obj "touch")] 61 (if-let [image-path (meta-data obj "touch")]
62 (load-image image-path))) 62 (load-image image-path)))
63 #+end_src 63
64 64 (defn tactile-scale
65 "Return the maximum length of a hair. All hairs are scalled between
66 0.0 and this length, depending on their color. Black is 0, and
67 white is maximum length, and everything in between is scalled
68 linearlly. Default scale is 0.01 jMonkeyEngine units."
69 [#^Geometry obj]
70 (if-let [scale (meta-data obj "scale")]
71 scale 0.1))
72 #+end_src
65 73
66 ** TODO add image showing example touch-uv map 74 ** TODO add image showing example touch-uv map
67 ** TODO add metadata display for worm 75 ** TODO add metadata display for worm
68 76
69 * Triangle Manipulation Functions
70
71 The rigid bodies which make up a creature have an underlying
72 =Geometry=, which is a =Mesh= plus a =Material= and other important
73 data involved with displaying the body.
74
75 A =Mesh= is composed of =Triangles=, and each =Triangle= has three
76 verticies which have coordinates in XYZ space and UV space.
77
78 Here, =(triangles)= gets all the triangles which compose a mesh, and
79 =(triangle-UV-coord)= returns the the UV coordinates of the verticies
80 of a triangle.
81
82 #+name: triangles-1
83 #+begin_src clojure
84 (defn triangles
85 "Return a sequence of all the Triangles which compose a given
86 Geometry."
87 [#^Geometry geom]
88 (let
89 [mesh (.getMesh geom)
90 triangles (transient [])]
91 (dorun
92 (for [n (range (.getTriangleCount mesh))]
93 (let [tri (Triangle.)]
94 (.getTriangle mesh n tri)
95 ;; (.calculateNormal tri)
96 ;; (.calculateCenter tri)
97 (conj! triangles tri))))
98 (persistent! triangles)))
99
100 (defn mesh-triangle
101 "Get the triangle specified by triangle-index from the mesh within
102 bounds."
103 [#^Mesh mesh triangle-index]
104 (let [scratch (Triangle.)]
105 (.getTriangle mesh triangle-index scratch)
106 scratch))
107
108 (defn triangle-vertex-indices
109 "Get the triangle vertex indices of a given triangle from a given
110 mesh."
111 [#^Mesh mesh triangle-index]
112 (let [indices (int-array 3)]
113 (.getTriangle mesh triangle-index indices)
114 (vec indices)))
115
116 (defn vertex-UV-coord
117 "Get the UV-coordinates of the vertex named by vertex-index"
118 [#^Mesh mesh vertex-index]
119 (let [UV-buffer
120 (.getData
121 (.getBuffer
122 mesh
123 VertexBuffer$Type/TexCoord))]
124 [(.get UV-buffer (* vertex-index 2))
125 (.get UV-buffer (+ 1 (* vertex-index 2)))]))
126
127 (defn triangle-UV-coord
128 "Get the UV-cooridnates of the triangle's verticies."
129 [#^Mesh mesh width height triangle-index]
130 (map (fn [[u v]] (vector (* width u) (* height v)))
131 (map (partial vertex-UV-coord mesh)
132 (triangle-vertex-indices mesh triangle-index))))
133 #+end_src
134
135 * Schrapnel Conversion Functions
136
137 It is convienent to treat a =Triangle= as a sequence of verticies, and
138 a =Vector2f= and =Vector3f= as a sequence of floats. These conversion
139 functions make this easy. If these classes implemented =Iterable= then
140 this code would not be necessary. Hopefully they will in the future.
141
142 #+name: triangles-2
143 #+begin_src clojure
144 (defn triangle-seq [#^Triangle tri]
145 [(.get1 tri) (.get2 tri) (.get3 tri)])
146
147 (defn vector3f-seq [#^Vector3f v]
148 [(.getX v) (.getY v) (.getZ v)])
149
150 (defn point->vector2f [[u v]]
151 (Vector2f. u v))
152
153 (defn vector2f->vector3f [v]
154 (Vector3f. (.getX v) (.getY v) 0))
155
156 (defn map-triangle [f #^Triangle tri]
157 (Triangle.
158 (f 0 (.get1 tri))
159 (f 1 (.get2 tri))
160 (f 2 (.get3 tri))))
161
162 (defn points->triangle
163 "Convert a list of points into a triangle."
164 [points]
165 (apply #(Triangle. %1 %2 %3)
166 (map (fn [point]
167 (let [point (vec point)]
168 (Vector3f. (get point 0 0)
169 (get point 1 0)
170 (get point 2 0))))
171 (take 3 points))))
172 #+end_src
173
174 * Triangle Affine Transforms
175
176 The position of each hair is stored in a 2D image in UV
177 coordinates. To place the hair in 3D space we must convert from UV
178 coordinates to XYZ coordinates. Each =Triangle= has coordinates in
179 both UV-space and XYZ-space, which defines a unique [[http://mathworld.wolfram.com/AffineTransformation.html ][Affine Transform]]
180 for translating any coordinate within the UV triangle to the
181 cooresponding coordinate in the XYZ triangle.
182
183 #+name: triangles-3
184 #+begin_src clojure
185 (defn triangle->matrix4f
186 "Converts the triangle into a 4x4 matrix: The first three columns
187 contain the vertices of the triangle; the last contains the unit
188 normal of the triangle. The bottom row is filled with 1s."
189 [#^Triangle t]
190 (let [mat (Matrix4f.)
191 [vert-1 vert-2 vert-3]
192 ((comp vec map) #(.get t %) (range 3))
193 unit-normal (do (.calculateNormal t)(.getNormal t))
194 vertices [vert-1 vert-2 vert-3 unit-normal]]
195 (dorun
196 (for [row (range 4) col (range 3)]
197 (do
198 (.set mat col row (.get (vertices row)col))
199 (.set mat 3 row 1))))
200 mat))
201
202 (defn triangle-transformation
203 "Returns the affine transformation that converts each vertex in the
204 first triangle into the corresponding vertex in the second
205 triangle."
206 [#^Triangle tri-1 #^Triangle tri-2]
207 (.mult
208 (triangle->matrix4f tri-2)
209 (.invert (triangle->matrix4f tri-1))))
210 #+end_src
211
212 * Triangle Boundaries
213
214 For efficiency's sake I will divide the UV-image into small squares
215 which inscribe each UV-triangle, then extract the points which lie
216 inside the triangle and map them to 3D-space using
217 =(triangle-transform)= above. To do this I need a function,
218 =(inside-triangle?)=, which determines whether a point is inside a
219 triangle in 2D UV-space.
220
221 #+name: triangles-4
222 #+begin_src clojure
223 (defn convex-bounds
224 "Returns the smallest square containing the given vertices, as a
225 vector of integers [left top width height]."
226 [uv-verts]
227 (let [xs (map first uv-verts)
228 ys (map second uv-verts)
229 x0 (Math/floor (apply min xs))
230 y0 (Math/floor (apply min ys))
231 x1 (Math/ceil (apply max xs))
232 y1 (Math/ceil (apply max ys))]
233 [x0 y0 (- x1 x0) (- y1 y0)]))
234
235 (defn same-side?
236 "Given the points p1 and p2 and the reference point ref, is point p
237 on the same side of the line that goes through p1 and p2 as ref is?"
238 [p1 p2 ref p]
239 (<=
240 0
241 (.dot
242 (.cross (.subtract p2 p1) (.subtract p p1))
243 (.cross (.subtract p2 p1) (.subtract ref p1)))))
244
245 (defn inside-triangle?
246 "Is the point inside the triangle?"
247 {:author "Dylan Holmes"}
248 [#^Triangle tri #^Vector3f p]
249 (let [[vert-1 vert-2 vert-3] (triangle-seq tri)]
250 (and
251 (same-side? vert-1 vert-2 vert-3 p)
252 (same-side? vert-2 vert-3 vert-1 p)
253 (same-side? vert-3 vert-1 vert-2 p))))
254 #+end_src
255
256
257
258 * Sensor Related Functions
259
260 These functions analyze the touch-sensor-profile image convert the
261 location of each touch sensor from pixel coordinates to UV-coordinates
262 and XYZ-coordinates.
263
264 #+name: sensors
265 #+begin_src clojure
266 (defn sensors-in-triangle
267 "Locate the touch sensors in the triangle, returning a map of their
268 UV and geometry-relative coordinates."
269 [image mesh tri-index]
270 (let [width (.getWidth image)
271 height (.getHeight image)
272 UV-vertex-coords (triangle-UV-coord mesh width height tri-index)
273 bounds (convex-bounds UV-vertex-coords)
274
275 cutout-triangle (points->triangle UV-vertex-coords)
276 UV-sensor-coords
277 (filter (comp (partial inside-triangle? cutout-triangle)
278 (fn [[u v]] (Vector3f. u v 0)))
279 (white-coordinates image bounds))
280 UV->geometry (triangle-transformation
281 cutout-triangle
282 (mesh-triangle mesh tri-index))
283 geometry-sensor-coords
284 (map (fn [[u v]] (.mult UV->geometry (Vector3f. u v 0)))
285 UV-sensor-coords)]
286 {:UV UV-sensor-coords :geometry geometry-sensor-coords}))
287
288 (defn-memo locate-feelers
289 "Search the geometry's tactile UV profile for touch sensors,
290 returning their positions in geometry-relative coordinates."
291 [#^Geometry geo]
292 (let [mesh (.getMesh geo)
293 num-triangles (.getTriangleCount mesh)]
294 (if-let [image (tactile-sensor-profile geo)]
295 (map
296 (partial sensors-in-triangle image mesh)
297 (range num-triangles))
298 (repeat (.getTriangleCount mesh) {:UV nil :geometry nil}))))
299
300 (defn-memo touch-topology
301 "Return a sequence of vectors of the form [x y] describing the
302 \"topology\" of the tactile sensors. Points that are close together
303 in the touch-topology are generally close together in the simulation."
304 [#^Gemoetry geo]
305 (vec (collapse (reduce concat (map :UV (locate-feelers geo))))))
306
307 (defn-memo feeler-coordinates
308 "The location of the touch sensors in world-space coordinates."
309 [#^Geometry geo]
310 (vec (map :geometry (locate-feelers geo))))
311 #+end_src
312
313 * Physics Collision Objects
314
315 The "hairs" are actually rays which extend from a point on a
316 =Triangle= in the =Mesh= normal to the =Triangle's= surface.
317
318 #+name: rays
319 #+begin_src clojure
320 (defn get-ray-origin
321 "Return the origin which a Ray would have to have to be in the exact
322 center of a particular Triangle in the Geometry in World
323 Coordinates."
324 [geom tri]
325 (let [new (Vector3f.)]
326 (.calculateCenter tri)
327 (.localToWorld geom (.getCenter tri) new) new))
328
329 (defn get-ray-direction
330 "Return the direction which a Ray would have to have to be to point
331 normal to the Triangle, in coordinates relative to the center of the
332 Triangle."
333 [geom tri]
334 (let [n+c (Vector3f.)]
335 (.calculateNormal tri)
336 (.calculateCenter tri)
337 (.localToWorld
338 geom
339 (.add (.getCenter tri) (.getNormal tri)) n+c)
340 (.subtract n+c (get-ray-origin geom tri))))
341 #+end_src
342
343
344 * Skin Creation 77 * Skin Creation
345 #+name: kernel 78 #+name: kernel
346 #+begin_src clojure 79 #+begin_src clojure
347 (defn touch-fn 80 (in-ns 'cortex.touch)
81
82 (defn touch-kernel
348 "Returns a function which returns tactile sensory data when called 83 "Returns a function which returns tactile sensory data when called
349 inside a running simulation." 84 inside a running simulation."
350 [#^Geometry geo] 85 [#^Geometry geo]
351 (let [feeler-coords (feeler-coordinates geo) 86 (let [feeler-coords (feeler-coordinates geo)
352 tris (triangles geo) 87 tris (triangles geo)
353 limit 0.1 88 limit (tactile-scale geo)]
354 ;;results (CollisionResults.)
355 ]
356 (if (empty? (touch-topology geo)) 89 (if (empty? (touch-topology geo))
357 nil 90 nil
358 (fn [node] 91 (fn [node]
359 (let [sensor-origins 92 (let [sensor-origins
360 (map 93 (map
377 (let [results (CollisionResults.)] 110 (let [results (CollisionResults.)]
378 (.collideWith node ray results) 111 (.collideWith node ray results)
379 (let [touch-objects 112 (let [touch-objects
380 (filter #(not (= geo (.getGeometry %))) 113 (filter #(not (= geo (.getGeometry %)))
381 results)] 114 results)]
382 (- 255 115 [(if (empty? touch-objects)
383 (if (empty? touch-objects) 255 116 limit (.getDistance (first touch-objects)))
384 (rem 117 limit])))))))))))
385 (int 118
386 (* 255 (/ (.getDistance
387 (first touch-objects)) limit)))
388 256))))))))))))))
389
390 (defn touch! 119 (defn touch!
391 "Endow the creature with the sense of touch. Returns a sequence of 120 "Endow the creature with the sense of touch. Returns a sequence of
392 functions, one for each body part with a tactile-sensor-proile, 121 functions, one for each body part with a tactile-sensor-proile,
393 each of which when called returns sensory data for that body part." 122 each of which when called returns sensory data for that body part."
394 [#^Node creature] 123 [#^Node creature]
395 (filter 124 (filter
396 (comp not nil?) 125 (comp not nil?)
397 (map touch-fn 126 (map touch-kernel
398 (filter #(isa? (class %) Geometry) 127 (filter #(isa? (class %) Geometry)
399 (node-seq creature))))) 128 (node-seq creature)))))
400 #+end_src 129 #+end_src
401 130
402 * Visualizing Touch 131 * Visualizing Touch
403 #+name: visualization 132 #+name: visualization
404 #+begin_src clojure 133 #+begin_src clojure
134 (in-ns 'cortex.touch)
135
136 (defn touch->gray
137 "Convert a pair of [distance, max-distance] into a grayscale pixel"
138 [distance max-distance]
139 (gray
140 (- 255
141 (rem
142 (int
143 (* 255 (/ distance max-distance)))
144 256))))
145
405 (defn view-touch 146 (defn view-touch
406 "Creates a function which accepts a list of touch sensor-data and 147 "Creates a function which accepts a list of touch sensor-data and
407 displays each element to the screen." 148 displays each element to the screen."
408 [] 149 []
409 (view-sense 150 (view-sense
411 [[coords sensor-data]] 152 [[coords sensor-data]]
412 (let [image (points->image coords)] 153 (let [image (points->image coords)]
413 (dorun 154 (dorun
414 (for [i (range (count coords))] 155 (for [i (range (count coords))]
415 (.setRGB image ((coords i) 0) ((coords i) 1) 156 (.setRGB image ((coords i) 0) ((coords i) 1)
416 (gray (sensor-data i))))) 157 (apply touch->gray (sensor-data i)))))
417 image)))) 158 image))))
418 #+end_src 159 #+end_src
160
161
162
163 * Triangle Manipulation Functions
164
165 The rigid bodies which make up a creature have an underlying
166 =Geometry=, which is a =Mesh= plus a =Material= and other important
167 data involved with displaying the body.
168
169 A =Mesh= is composed of =Triangles=, and each =Triangle= has three
170 verticies which have coordinates in XYZ space and UV space.
171
172 Here, =(triangles)= gets all the triangles which compose a mesh, and
173 =(triangle-UV-coord)= returns the the UV coordinates of the verticies
174 of a triangle.
175
176 #+name: triangles-1
177 #+begin_src clojure
178 (defn triangles
179 "Return a sequence of all the Triangles which compose a given
180 Geometry."
181 [#^Geometry geom]
182 (let
183 [mesh (.getMesh geom)
184 triangles (transient [])]
185 (dorun
186 (for [n (range (.getTriangleCount mesh))]
187 (let [tri (Triangle.)]
188 (.getTriangle mesh n tri)
189 ;; (.calculateNormal tri)
190 ;; (.calculateCenter tri)
191 (conj! triangles tri))))
192 (persistent! triangles)))
193
194 (defn mesh-triangle
195 "Get the triangle specified by triangle-index from the mesh within
196 bounds."
197 [#^Mesh mesh triangle-index]
198 (let [scratch (Triangle.)]
199 (.getTriangle mesh triangle-index scratch)
200 scratch))
201
202 (defn triangle-vertex-indices
203 "Get the triangle vertex indices of a given triangle from a given
204 mesh."
205 [#^Mesh mesh triangle-index]
206 (let [indices (int-array 3)]
207 (.getTriangle mesh triangle-index indices)
208 (vec indices)))
209
210 (defn vertex-UV-coord
211 "Get the UV-coordinates of the vertex named by vertex-index"
212 [#^Mesh mesh vertex-index]
213 (let [UV-buffer
214 (.getData
215 (.getBuffer
216 mesh
217 VertexBuffer$Type/TexCoord))]
218 [(.get UV-buffer (* vertex-index 2))
219 (.get UV-buffer (+ 1 (* vertex-index 2)))]))
220
221 (defn triangle-UV-coord
222 "Get the UV-cooridnates of the triangle's verticies."
223 [#^Mesh mesh width height triangle-index]
224 (map (fn [[u v]] (vector (* width u) (* height v)))
225 (map (partial vertex-UV-coord mesh)
226 (triangle-vertex-indices mesh triangle-index))))
227 #+end_src
228
229 * Schrapnel Conversion Functions
230
231 It is convienent to treat a =Triangle= as a sequence of verticies, and
232 a =Vector2f= and =Vector3f= as a sequence of floats. These conversion
233 functions make this easy. If these classes implemented =Iterable= then
234 this code would not be necessary. Hopefully they will in the future.
235
236 #+name: triangles-2
237 #+begin_src clojure
238 (defn triangle-seq [#^Triangle tri]
239 [(.get1 tri) (.get2 tri) (.get3 tri)])
240
241 (defn vector3f-seq [#^Vector3f v]
242 [(.getX v) (.getY v) (.getZ v)])
243
244 (defn point->vector2f [[u v]]
245 (Vector2f. u v))
246
247 (defn vector2f->vector3f [v]
248 (Vector3f. (.getX v) (.getY v) 0))
249
250 (defn map-triangle [f #^Triangle tri]
251 (Triangle.
252 (f 0 (.get1 tri))
253 (f 1 (.get2 tri))
254 (f 2 (.get3 tri))))
255
256 (defn points->triangle
257 "Convert a list of points into a triangle."
258 [points]
259 (apply #(Triangle. %1 %2 %3)
260 (map (fn [point]
261 (let [point (vec point)]
262 (Vector3f. (get point 0 0)
263 (get point 1 0)
264 (get point 2 0))))
265 (take 3 points))))
266 #+end_src
267
268 * Triangle Affine Transforms
269
270 The position of each hair is stored in a 2D image in UV
271 coordinates. To place the hair in 3D space we must convert from UV
272 coordinates to XYZ coordinates. Each =Triangle= has coordinates in
273 both UV-space and XYZ-space, which defines a unique [[http://mathworld.wolfram.com/AffineTransformation.html ][Affine Transform]]
274 for translating any coordinate within the UV triangle to the
275 cooresponding coordinate in the XYZ triangle.
276
277 #+name: triangles-3
278 #+begin_src clojure
279 (defn triangle->matrix4f
280 "Converts the triangle into a 4x4 matrix: The first three columns
281 contain the vertices of the triangle; the last contains the unit
282 normal of the triangle. The bottom row is filled with 1s."
283 [#^Triangle t]
284 (let [mat (Matrix4f.)
285 [vert-1 vert-2 vert-3]
286 ((comp vec map) #(.get t %) (range 3))
287 unit-normal (do (.calculateNormal t)(.getNormal t))
288 vertices [vert-1 vert-2 vert-3 unit-normal]]
289 (dorun
290 (for [row (range 4) col (range 3)]
291 (do
292 (.set mat col row (.get (vertices row)col))
293 (.set mat 3 row 1))))
294 mat))
295
296 (defn triangle-transformation
297 "Returns the affine transformation that converts each vertex in the
298 first triangle into the corresponding vertex in the second
299 triangle."
300 [#^Triangle tri-1 #^Triangle tri-2]
301 (.mult
302 (triangle->matrix4f tri-2)
303 (.invert (triangle->matrix4f tri-1))))
304 #+end_src
305
306 * Triangle Boundaries
307
308 For efficiency's sake I will divide the UV-image into small squares
309 which inscribe each UV-triangle, then extract the points which lie
310 inside the triangle and map them to 3D-space using
311 =(triangle-transform)= above. To do this I need a function,
312 =(inside-triangle?)=, which determines whether a point is inside a
313 triangle in 2D UV-space.
314
315 #+name: triangles-4
316 #+begin_src clojure
317 (defn convex-bounds
318 "Returns the smallest square containing the given vertices, as a
319 vector of integers [left top width height]."
320 [uv-verts]
321 (let [xs (map first uv-verts)
322 ys (map second uv-verts)
323 x0 (Math/floor (apply min xs))
324 y0 (Math/floor (apply min ys))
325 x1 (Math/ceil (apply max xs))
326 y1 (Math/ceil (apply max ys))]
327 [x0 y0 (- x1 x0) (- y1 y0)]))
328
329 (defn same-side?
330 "Given the points p1 and p2 and the reference point ref, is point p
331 on the same side of the line that goes through p1 and p2 as ref is?"
332 [p1 p2 ref p]
333 (<=
334 0
335 (.dot
336 (.cross (.subtract p2 p1) (.subtract p p1))
337 (.cross (.subtract p2 p1) (.subtract ref p1)))))
338
339 (defn inside-triangle?
340 "Is the point inside the triangle?"
341 {:author "Dylan Holmes"}
342 [#^Triangle tri #^Vector3f p]
343 (let [[vert-1 vert-2 vert-3] (triangle-seq tri)]
344 (and
345 (same-side? vert-1 vert-2 vert-3 p)
346 (same-side? vert-2 vert-3 vert-1 p)
347 (same-side? vert-3 vert-1 vert-2 p))))
348 #+end_src
349
350
351
352 * Sensor Related Functions
353
354 These functions analyze the touch-sensor-profile image convert the
355 location of each touch sensor from pixel coordinates to UV-coordinates
356 and XYZ-coordinates.
357
358 #+name: sensors
359 #+begin_src clojure
360 (defn sensors-in-triangle
361 "Locate the touch sensors in the triangle, returning a map of their
362 UV and geometry-relative coordinates."
363 [image mesh tri-index]
364 (let [width (.getWidth image)
365 height (.getHeight image)
366 UV-vertex-coords (triangle-UV-coord mesh width height tri-index)
367 bounds (convex-bounds UV-vertex-coords)
368
369 cutout-triangle (points->triangle UV-vertex-coords)
370 UV-sensor-coords
371 (filter (comp (partial inside-triangle? cutout-triangle)
372 (fn [[u v]] (Vector3f. u v 0)))
373 (white-coordinates image bounds))
374 UV->geometry (triangle-transformation
375 cutout-triangle
376 (mesh-triangle mesh tri-index))
377 geometry-sensor-coords
378 (map (fn [[u v]] (.mult UV->geometry (Vector3f. u v 0)))
379 UV-sensor-coords)]
380 {:UV UV-sensor-coords :geometry geometry-sensor-coords}))
381
382 (defn-memo locate-feelers
383 "Search the geometry's tactile UV profile for touch sensors,
384 returning their positions in geometry-relative coordinates."
385 [#^Geometry geo]
386 (let [mesh (.getMesh geo)
387 num-triangles (.getTriangleCount mesh)]
388 (if-let [image (tactile-sensor-profile geo)]
389 (map
390 (partial sensors-in-triangle image mesh)
391 (range num-triangles))
392 (repeat (.getTriangleCount mesh) {:UV nil :geometry nil}))))
393
394 (defn-memo touch-topology
395 "Return a sequence of vectors of the form [x y] describing the
396 \"topology\" of the tactile sensors. Points that are close together
397 in the touch-topology are generally close together in the simulation."
398 [#^Gemoetry geo]
399 (vec (collapse (reduce concat (map :UV (locate-feelers geo))))))
400
401 (defn-memo feeler-coordinates
402 "The location of the touch sensors in world-space coordinates."
403 [#^Geometry geo]
404 (vec (map :geometry (locate-feelers geo))))
405 #+end_src
406
407 * Physics Collision Objects
408
409 The "hairs" are actually rays which extend from a point on a
410 =Triangle= in the =Mesh= normal to the =Triangle's= surface.
411
412 #+name: rays
413 #+begin_src clojure
414 (defn get-ray-origin
415 "Return the origin which a Ray would have to have to be in the exact
416 center of a particular Triangle in the Geometry in World
417 Coordinates."
418 [geom tri]
419 (let [new (Vector3f.)]
420 (.calculateCenter tri)
421 (.localToWorld geom (.getCenter tri) new) new))
422
423 (defn get-ray-direction
424 "Return the direction which a Ray would have to have to be to point
425 normal to the Triangle, in coordinates relative to the center of the
426 Triangle."
427 [geom tri]
428 (let [n+c (Vector3f.)]
429 (.calculateNormal tri)
430 (.calculateCenter tri)
431 (.localToWorld
432 geom
433 (.add (.getCenter tri) (.getNormal tri)) n+c)
434 (.subtract n+c (get-ray-origin geom tri))))
435 #+end_src
436
437
419 438
420 * Headers 439 * Headers
421 440
422 #+name: touch-header 441 #+name: touch-header
423 #+begin_src clojure 442 #+begin_src clojure
456 (fn [world] 475 (fn [world]
457 (light-up-everything world)) 476 (light-up-everything world))
458 477
459 (fn [world tpf] 478 (fn [world tpf]
460 (touch-display (map #(% (.getRootNode world)) touch)))))) 479 (touch-display (map #(% (.getRootNode world)) touch))))))
461
462 #+end_src 480 #+end_src
463 481
464 * Source Listing 482 * Source Listing
465 * Next 483 * Next
466 484