rlm@37
|
1 #+title: Simulated Sense of Touch
|
rlm@0
|
2 #+author: Robert McIntyre
|
rlm@0
|
3 #+email: rlm@mit.edu
|
rlm@37
|
4 #+description: Simulated touch for AI research using JMonkeyEngine and clojure.
|
rlm@37
|
5 #+keywords: simulation, tactile sense, jMonkeyEngine3, clojure
|
rlm@4
|
6 #+SETUPFILE: ../../aurellem/org/setup.org
|
rlm@4
|
7 #+INCLUDE: ../../aurellem/org/level-0.org
|
rlm@0
|
8
|
rlm@37
|
9 * Touch
|
rlm@0
|
10
|
rlm@37
|
11 My creatures need to be able to feel their environments. The idea here
|
rlm@43
|
12 is to create thousands of small /touch receptors/ along the geometries
|
rlm@43
|
13 which make up the creature's body. The number of touch receptors in a
|
rlm@43
|
14 given area is determined by how complicated that area is, as
|
rlm@43
|
15 determined by the total number of triangles in that region. This way,
|
rlm@43
|
16 complicated regions like the hands/face, etc. get more touch receptors
|
rlm@43
|
17 than simpler areas of the body.
|
rlm@0
|
18
|
rlm@66
|
19 #+name: skin-main
|
rlm@0
|
20 #+begin_src clojure
|
rlm@37
|
21 (ns cortex.touch
|
rlm@37
|
22 "Simulate the sense of touch in jMonkeyEngine3. Enables any Geometry
|
rlm@37
|
23 to be outfitted with touch sensors with density proportional to the
|
rlm@37
|
24 density of triangles along the surface of the Geometry. Enables a
|
rlm@37
|
25 Geometry to know what parts of itself are touching nearby objects."
|
rlm@37
|
26 {:author "Robert McIntyre"}
|
rlm@156
|
27 (:use (cortex world util sense))
|
rlm@178
|
28 (:use clojure.contrib.def)
|
rlm@179
|
29 (:import (com.jme3.scene Geometry Node Mesh))
|
rlm@39
|
30 (:import com.jme3.collision.CollisionResults)
|
rlm@179
|
31 (:import com.jme3.scene.VertexBuffer$Type)
|
rlm@179
|
32 (:import (com.jme3.math Triangle Vector3f Vector2f Ray Matrix4f)))
|
rlm@37
|
33
|
rlm@37
|
34 (defn triangles
|
rlm@37
|
35 "Return a sequence of all the Triangles which compose a given
|
rlm@37
|
36 Geometry."
|
rlm@37
|
37 [#^Geometry geom]
|
rlm@6
|
38 (let
|
rlm@6
|
39 [mesh (.getMesh geom)
|
rlm@6
|
40 triangles (transient [])]
|
rlm@6
|
41 (dorun
|
rlm@6
|
42 (for [n (range (.getTriangleCount mesh))]
|
rlm@6
|
43 (let [tri (Triangle.)]
|
rlm@6
|
44 (.getTriangle mesh n tri)
|
rlm@37
|
45 ;; (.calculateNormal tri)
|
rlm@37
|
46 ;; (.calculateCenter tri)
|
rlm@6
|
47 (conj! triangles tri))))
|
rlm@6
|
48 (persistent! triangles)))
|
rlm@6
|
49
|
rlm@7
|
50 (defn get-ray-origin
|
rlm@37
|
51 "Return the origin which a Ray would have to have to be in the exact
|
rlm@37
|
52 center of a particular Triangle in the Geometry in World
|
rlm@37
|
53 Coordinates."
|
rlm@7
|
54 [geom tri]
|
rlm@7
|
55 (let [new (Vector3f.)]
|
rlm@7
|
56 (.calculateCenter tri)
|
rlm@37
|
57 (.localToWorld geom (.getCenter tri) new) new))
|
rlm@6
|
58
|
rlm@7
|
59 (defn get-ray-direction
|
rlm@156
|
60 "Return the direction which a Ray would have to have to be to point
|
rlm@37
|
61 normal to the Triangle, in coordinates relative to the center of the
|
rlm@37
|
62 Triangle."
|
rlm@7
|
63 [geom tri]
|
rlm@9
|
64 (let [n+c (Vector3f.)]
|
rlm@7
|
65 (.calculateNormal tri)
|
rlm@9
|
66 (.calculateCenter tri)
|
rlm@37
|
67 (.localToWorld
|
rlm@37
|
68 geom
|
rlm@37
|
69 (.add (.getCenter tri) (.getNormal tri)) n+c)
|
rlm@37
|
70 (.subtract n+c (get-ray-origin geom tri))))
|
rlm@37
|
71
|
rlm@156
|
72 ;; Every Mesh has many triangles, each with its own index.
|
rlm@156
|
73 ;; Every vertex has its own index as well.
|
rlm@37
|
74
|
rlm@178
|
75 (defn tactile-sensor-profile
|
rlm@156
|
76 "Return the touch-sensor distribution image in BufferedImage format,
|
rlm@156
|
77 or nil if it does not exist."
|
rlm@156
|
78 [#^Geometry obj]
|
rlm@156
|
79 (if-let [image-path (meta-data obj "touch")]
|
rlm@178
|
80 (load-image image-path)))
|
rlm@156
|
81
|
rlm@156
|
82 (defn triangle
|
rlm@156
|
83 "Get the triangle specified by triangle-index from the mesh within
|
rlm@156
|
84 bounds."
|
rlm@156
|
85 [#^Mesh mesh triangle-index]
|
rlm@156
|
86 (let [scratch (Triangle.)]
|
rlm@156
|
87 (.getTriangle mesh triangle-index scratch)
|
rlm@156
|
88 scratch))
|
rlm@156
|
89
|
rlm@156
|
90 (defn triangle-vertex-indices
|
rlm@156
|
91 "Get the triangle vertex indices of a given triangle from a given
|
rlm@156
|
92 mesh."
|
rlm@156
|
93 [#^Mesh mesh triangle-index]
|
rlm@156
|
94 (let [indices (int-array 3)]
|
rlm@156
|
95 (.getTriangle mesh triangle-index indices)
|
rlm@156
|
96 (vec indices)))
|
rlm@156
|
97
|
rlm@156
|
98 (defn vertex-UV-coord
|
rlm@156
|
99 "Get the uv-coordinates of the vertex named by vertex-index"
|
rlm@156
|
100 [#^Mesh mesh vertex-index]
|
rlm@156
|
101 (let [UV-buffer
|
rlm@156
|
102 (.getData
|
rlm@156
|
103 (.getBuffer
|
rlm@156
|
104 mesh
|
rlm@156
|
105 VertexBuffer$Type/TexCoord))]
|
rlm@156
|
106 [(.get UV-buffer (* vertex-index 2))
|
rlm@156
|
107 (.get UV-buffer (+ 1 (* vertex-index 2)))]))
|
rlm@156
|
108
|
rlm@156
|
109 (defn triangle-UV-coord
|
rlm@156
|
110 "Get the uv-cooridnates of the triangle's verticies."
|
rlm@156
|
111 [#^Mesh mesh width height triangle-index]
|
rlm@156
|
112 (map (fn [[u v]] (vector (* width u) (* height v)))
|
rlm@156
|
113 (map (partial vertex-UV-coord mesh)
|
rlm@156
|
114 (triangle-vertex-indices mesh triangle-index))))
|
rlm@156
|
115
|
rlm@156
|
116 (defn same-side?
|
rlm@156
|
117 "Given the points p1 and p2 and the reference point ref, is point p
|
rlm@156
|
118 on the same side of the line that goes through p1 and p2 as ref is?"
|
rlm@156
|
119 [p1 p2 ref p]
|
rlm@156
|
120 (<=
|
rlm@156
|
121 0
|
rlm@156
|
122 (.dot
|
rlm@156
|
123 (.cross (.subtract p2 p1) (.subtract p p1))
|
rlm@156
|
124 (.cross (.subtract p2 p1) (.subtract ref p1)))))
|
rlm@156
|
125
|
rlm@156
|
126 (defn triangle-seq [#^Triangle tri]
|
rlm@156
|
127 [(.get1 tri) (.get2 tri) (.get3 tri)])
|
rlm@156
|
128
|
rlm@156
|
129 (defn vector3f-seq [#^Vector3f v]
|
rlm@156
|
130 [(.getX v) (.getY v) (.getZ v)])
|
rlm@156
|
131
|
rlm@156
|
132 (defn inside-triangle?
|
rlm@156
|
133 "Is the point inside the triangle?"
|
rlm@156
|
134 {:author "Dylan Holmes"}
|
rlm@156
|
135 [#^Triangle tri #^Vector3f p]
|
rlm@156
|
136 (let [[vert-1 vert-2 vert-3] (triangle-seq tri)]
|
rlm@156
|
137 (and
|
rlm@156
|
138 (same-side? vert-1 vert-2 vert-3 p)
|
rlm@156
|
139 (same-side? vert-2 vert-3 vert-1 p)
|
rlm@156
|
140 (same-side? vert-3 vert-1 vert-2 p))))
|
rlm@156
|
141
|
rlm@156
|
142 (defn triangle->matrix4f
|
rlm@156
|
143 "Converts the triangle into a 4x4 matrix: The first three columns
|
rlm@156
|
144 contain the vertices of the triangle; the last contains the unit
|
rlm@156
|
145 normal of the triangle. The bottom row is filled with 1s."
|
rlm@156
|
146 [#^Triangle t]
|
rlm@156
|
147 (let [mat (Matrix4f.)
|
rlm@156
|
148 [vert-1 vert-2 vert-3]
|
rlm@156
|
149 ((comp vec map) #(.get t %) (range 3))
|
rlm@156
|
150 unit-normal (do (.calculateNormal t)(.getNormal t))
|
rlm@156
|
151 vertices [vert-1 vert-2 vert-3 unit-normal]]
|
rlm@156
|
152 (dorun
|
rlm@156
|
153 (for [row (range 4) col (range 3)]
|
rlm@37
|
154 (do
|
rlm@156
|
155 (.set mat col row (.get (vertices row)col))
|
rlm@156
|
156 (.set mat 3 row 1))))
|
rlm@156
|
157 mat))
|
rlm@156
|
158
|
rlm@156
|
159 (defn triangle-transformation
|
rlm@156
|
160 "Returns the affine transformation that converts each vertex in the
|
rlm@156
|
161 first triangle into the corresponding vertex in the second
|
rlm@156
|
162 triangle."
|
rlm@156
|
163 [#^Triangle tri-1 #^Triangle tri-2]
|
rlm@156
|
164 (.mult
|
rlm@156
|
165 (triangle->matrix4f tri-2)
|
rlm@156
|
166 (.invert (triangle->matrix4f tri-1))))
|
rlm@156
|
167
|
rlm@156
|
168 (defn point->vector2f [[u v]]
|
rlm@156
|
169 (Vector2f. u v))
|
rlm@156
|
170
|
rlm@156
|
171 (defn vector2f->vector3f [v]
|
rlm@156
|
172 (Vector3f. (.getX v) (.getY v) 0))
|
rlm@156
|
173
|
rlm@156
|
174 (defn map-triangle [f #^Triangle tri]
|
rlm@156
|
175 (Triangle.
|
rlm@156
|
176 (f 0 (.get1 tri))
|
rlm@156
|
177 (f 1 (.get2 tri))
|
rlm@156
|
178 (f 2 (.get3 tri))))
|
rlm@156
|
179
|
rlm@156
|
180 (defn points->triangle
|
rlm@156
|
181 "Convert a list of points into a triangle."
|
rlm@156
|
182 [points]
|
rlm@156
|
183 (apply #(Triangle. %1 %2 %3)
|
rlm@156
|
184 (map (fn [point]
|
rlm@156
|
185 (let [point (vec point)]
|
rlm@156
|
186 (Vector3f. (get point 0 0)
|
rlm@156
|
187 (get point 1 0)
|
rlm@156
|
188 (get point 2 0))))
|
rlm@156
|
189 (take 3 points))))
|
rlm@156
|
190
|
rlm@156
|
191 (defn convex-bounds
|
rlm@178
|
192 "Returns the smallest square containing the given vertices, as a
|
rlm@178
|
193 vector of integers [left top width height]."
|
rlm@156
|
194 [uv-verts]
|
rlm@156
|
195 (let [xs (map first uv-verts)
|
rlm@156
|
196 ys (map second uv-verts)
|
rlm@156
|
197 x0 (Math/floor (apply min xs))
|
rlm@156
|
198 y0 (Math/floor (apply min ys))
|
rlm@156
|
199 x1 (Math/ceil (apply max xs))
|
rlm@156
|
200 y1 (Math/ceil (apply max ys))]
|
rlm@156
|
201 [x0 y0 (- x1 x0) (- y1 y0)]))
|
rlm@156
|
202
|
rlm@156
|
203 (defn sensors-in-triangle
|
rlm@178
|
204 "Locate the touch sensors in the triangle, returning a map of their
|
rlm@178
|
205 UV and geometry-relative coordinates."
|
rlm@156
|
206 [image mesh tri-index]
|
rlm@156
|
207 (let [width (.getWidth image)
|
rlm@156
|
208 height (.getHeight image)
|
rlm@156
|
209 UV-vertex-coords (triangle-UV-coord mesh width height tri-index)
|
rlm@156
|
210 bounds (convex-bounds UV-vertex-coords)
|
rlm@156
|
211
|
rlm@156
|
212 cutout-triangle (points->triangle UV-vertex-coords)
|
rlm@156
|
213 UV-sensor-coords
|
rlm@156
|
214 (filter (comp (partial inside-triangle? cutout-triangle)
|
rlm@156
|
215 (fn [[u v]] (Vector3f. u v 0)))
|
rlm@156
|
216 (white-coordinates image bounds))
|
rlm@156
|
217 UV->geometry (triangle-transformation
|
rlm@156
|
218 cutout-triangle
|
rlm@156
|
219 (triangle mesh tri-index))
|
rlm@156
|
220 geometry-sensor-coords
|
rlm@156
|
221 (map (fn [[u v]] (.mult UV->geometry (Vector3f. u v 0)))
|
rlm@156
|
222 UV-sensor-coords)]
|
rlm@156
|
223 {:UV UV-sensor-coords :geometry geometry-sensor-coords}))
|
rlm@156
|
224
|
rlm@156
|
225 (defn-memo locate-feelers
|
rlm@178
|
226 "Search the geometry's tactile UV profile for touch sensors,
|
rlm@178
|
227 returning their positions in geometry-relative coordinates."
|
rlm@156
|
228 [#^Geometry geo]
|
rlm@156
|
229 (let [mesh (.getMesh geo)
|
rlm@156
|
230 num-triangles (.getTriangleCount mesh)]
|
rlm@178
|
231 (if-let [image (tactile-sensor-profile geo)]
|
rlm@156
|
232 (map
|
rlm@156
|
233 (partial sensors-in-triangle image mesh)
|
rlm@156
|
234 (range num-triangles))
|
rlm@156
|
235 (repeat (.getTriangleCount mesh) {:UV nil :geometry nil}))))
|
rlm@156
|
236
|
rlm@178
|
237 (defn-memo touch-topology
|
rlm@178
|
238 "Return a sequence of vectors of the form [x y] describing the
|
rlm@178
|
239 \"topology\" of the tactile sensors. Points that are close together
|
rlm@178
|
240 in the touch-topology are generally close together in the simulation."
|
rlm@178
|
241 [#^Gemoetry geo]
|
rlm@156
|
242 (vec (collapse (reduce concat (map :UV (locate-feelers geo))))))
|
rlm@156
|
243
|
rlm@178
|
244 (defn-memo feeler-coordinates
|
rlm@178
|
245 "The location of the touch sensors in world-space coordinates."
|
rlm@178
|
246 [#^Geometry geo]
|
rlm@156
|
247 (vec (map :geometry (locate-feelers geo))))
|
rlm@156
|
248
|
rlm@178
|
249 (defn touch-fn
|
rlm@178
|
250 "Returns a function which returns tactile sensory data when called
|
rlm@178
|
251 inside a running simulation."
|
rlm@178
|
252 [#^Geometry geo]
|
rlm@156
|
253 (let [feeler-coords (feeler-coordinates geo)
|
rlm@156
|
254 tris (triangles geo)
|
rlm@156
|
255 limit 0.1
|
rlm@156
|
256 ;;results (CollisionResults.)
|
rlm@156
|
257 ]
|
rlm@156
|
258 (if (empty? (touch-topology geo))
|
rlm@156
|
259 nil
|
rlm@156
|
260 (fn [node]
|
rlm@156
|
261 (let [sensor-origins
|
rlm@156
|
262 (map
|
rlm@156
|
263 #(map (partial local-to-world geo) %)
|
rlm@156
|
264 feeler-coords)
|
rlm@156
|
265 triangle-normals
|
rlm@156
|
266 (map (partial get-ray-direction geo)
|
rlm@156
|
267 tris)
|
rlm@156
|
268 rays
|
rlm@156
|
269 (flatten
|
rlm@156
|
270 (map (fn [origins norm]
|
rlm@156
|
271 (map #(doto (Ray. % norm)
|
rlm@156
|
272 (.setLimit limit)) origins))
|
rlm@156
|
273 sensor-origins triangle-normals))]
|
rlm@156
|
274 (vector
|
rlm@156
|
275 (touch-topology geo)
|
rlm@156
|
276 (vec
|
rlm@156
|
277 (for [ray rays]
|
rlm@156
|
278 (do
|
rlm@156
|
279 (let [results (CollisionResults.)]
|
rlm@156
|
280 (.collideWith node ray results)
|
rlm@156
|
281 (let [touch-objects
|
rlm@156
|
282 (filter #(not (= geo (.getGeometry %)))
|
rlm@156
|
283 results)]
|
rlm@156
|
284 (- 255
|
rlm@156
|
285 (if (empty? touch-objects) 255
|
rlm@156
|
286 (rem
|
rlm@156
|
287 (int
|
rlm@156
|
288 (* 255 (/ (.getDistance
|
rlm@156
|
289 (first touch-objects)) limit)))
|
rlm@156
|
290 256))))))))))))))
|
rlm@156
|
291
|
rlm@178
|
292 (defn touch!
|
rlm@178
|
293 "Endow the creature with the sense of touch. Returns a sequence of
|
rlm@178
|
294 functions, one for each body part with a tactile-sensor-proile,
|
rlm@178
|
295 each of which when called returns sensory data for that body part."
|
rlm@178
|
296 [#^Node creature]
|
rlm@178
|
297 (filter
|
rlm@178
|
298 (comp not nil?)
|
rlm@178
|
299 (map touch-fn
|
rlm@178
|
300 (filter #(isa? (class %) Geometry)
|
rlm@178
|
301 (node-seq creature)))))
|
rlm@156
|
302
|
rlm@185
|
303 (defn gray-scale
|
rlm@185
|
304 "Create a gray RGB pixel with R, G, and B set to 'num"
|
rlm@185
|
305 [num]
|
rlm@185
|
306 (+ num
|
rlm@185
|
307 (bit-shift-left num 8)
|
rlm@185
|
308 (bit-shift-left num 16)))
|
rlm@185
|
309
|
rlm@185
|
310 (defn view-touch
|
rlm@185
|
311 "Creates a function which accepts touch sensor-data and displays it
|
rlm@185
|
312 as BufferedImages in JFrames."
|
rlm@185
|
313 []
|
rlm@185
|
314 (let
|
rlm@185
|
315 [windows (atom [])
|
rlm@185
|
316 display-single-touch
|
rlm@185
|
317 (fn
|
rlm@185
|
318 [[coords sensor-data] display]
|
rlm@185
|
319 (let [image (points->image coords)]
|
rlm@185
|
320 (dorun
|
rlm@185
|
321 (for [i (range (count coords))]
|
rlm@185
|
322 (.setRGB image ((coords i) 0) ((coords i) 1)
|
rlm@185
|
323 (gray-scale (sensor-data i)))))
|
rlm@185
|
324 (display image)))]
|
rlm@185
|
325 (fn [data]
|
rlm@185
|
326 (if (> (count data) (count @windows))
|
rlm@185
|
327 (reset! windows (map (fn [_] (view-image))
|
rlm@185
|
328 (range (count data)))))
|
rlm@185
|
329 (dorun (map display-single-touch data @windows)))))
|
rlm@185
|
330
|
rlm@185
|
331
|
rlm@156
|
332
|
rlm@37
|
333 #+end_src
|
rlm@37
|
334
|
rlm@37
|
335
|
rlm@37
|
336 * Example
|
rlm@37
|
337
|
rlm@66
|
338 #+name: touch-test
|
rlm@37
|
339 #+begin_src clojure
|
rlm@68
|
340 (ns cortex.test.touch
|
rlm@59
|
341 (:use (cortex world util touch))
|
rlm@59
|
342 (:import
|
rlm@59
|
343 com.jme3.scene.shape.Sphere
|
rlm@59
|
344 com.jme3.math.ColorRGBA
|
rlm@59
|
345 com.jme3.math.Vector3f
|
rlm@59
|
346 com.jme3.material.RenderState$BlendMode
|
rlm@59
|
347 com.jme3.renderer.queue.RenderQueue$Bucket
|
rlm@59
|
348 com.jme3.scene.shape.Box
|
rlm@68
|
349 com.jme3.scene.Node))
|
rlm@39
|
350
|
rlm@7
|
351 (defn ray-origin-debug
|
rlm@9
|
352 [ray color]
|
rlm@7
|
353 (make-shape
|
rlm@20
|
354 (assoc base-shape
|
rlm@20
|
355 :shape (Sphere. 5 5 0.05)
|
rlm@20
|
356 :name "arrow"
|
rlm@20
|
357 :color color
|
rlm@20
|
358 :texture false
|
rlm@20
|
359 :physical? false
|
rlm@20
|
360 :position
|
rlm@20
|
361 (.getOrigin ray))))
|
rlm@6
|
362
|
rlm@9
|
363 (defn ray-debug [ray color]
|
rlm@6
|
364 (make-shape
|
rlm@6
|
365 (assoc
|
rlm@6
|
366 base-shape
|
rlm@6
|
367 :name "debug-ray"
|
rlm@6
|
368 :physical? false
|
rlm@6
|
369 :shape (com.jme3.scene.shape.Line.
|
rlm@6
|
370 (.getOrigin ray)
|
rlm@6
|
371 (.add
|
rlm@6
|
372 (.getOrigin ray)
|
rlm@6
|
373 (.mult (.getDirection ray)
|
rlm@6
|
374 (float (.getLimit ray))))))))
|
rlm@6
|
375
|
rlm@6
|
376
|
rlm@10
|
377 (defn contact-color [contacts]
|
rlm@10
|
378 (case contacts
|
rlm@10
|
379 0 ColorRGBA/Gray
|
rlm@37
|
380 1 ColorRGBA/Red
|
rlm@10
|
381 2 ColorRGBA/Green
|
rlm@10
|
382 3 ColorRGBA/Yellow
|
rlm@10
|
383 4 ColorRGBA/Orange
|
rlm@10
|
384 5 ColorRGBA/Red
|
rlm@10
|
385 6 ColorRGBA/Magenta
|
rlm@10
|
386 7 ColorRGBA/Pink
|
rlm@10
|
387 8 ColorRGBA/White))
|
rlm@6
|
388
|
rlm@14
|
389 (defn update-ray-debug [node ray contacts]
|
rlm@14
|
390 (let [origin (.getChild node 0)]
|
rlm@14
|
391 (.setLocalTranslation origin (.getOrigin ray))
|
rlm@14
|
392 (.setColor (.getMaterial origin) "Color" (contact-color contacts))))
|
rlm@14
|
393
|
rlm@13
|
394 (defn init-node
|
rlm@13
|
395 [debug-node rays]
|
rlm@12
|
396 (.detachAllChildren debug-node)
|
rlm@13
|
397 (dorun
|
rlm@13
|
398 (for [ray rays]
|
rlm@13
|
399 (do
|
rlm@13
|
400 (.attachChild
|
rlm@13
|
401 debug-node
|
rlm@13
|
402 (doto (Node.)
|
rlm@14
|
403 (.attachChild (ray-origin-debug ray ColorRGBA/Gray))
|
rlm@20
|
404 (.attachChild (ray-debug ray ColorRGBA/Gray))
|
rlm@14
|
405 ))))))
|
rlm@14
|
406
|
rlm@13
|
407 (defn manage-ray-debug-node [debug-node geom touch-data limit]
|
rlm@13
|
408 (let [rays (normal-rays limit geom)]
|
rlm@13
|
409 (if (not= (count (.getChildren debug-node)) (count touch-data))
|
rlm@13
|
410 (init-node debug-node rays))
|
rlm@13
|
411 (dorun
|
rlm@13
|
412 (for [n (range (count touch-data))]
|
rlm@14
|
413 (update-ray-debug
|
rlm@14
|
414 (.getChild debug-node n) (nth rays n) (nth touch-data n))))))
|
rlm@12
|
415
|
rlm@0
|
416 (defn transparent-sphere []
|
rlm@0
|
417 (doto
|
rlm@0
|
418 (make-shape
|
rlm@0
|
419 (merge base-shape
|
rlm@0
|
420 {:position (Vector3f. 0 2 0)
|
rlm@0
|
421 :name "the blob."
|
rlm@0
|
422 :material "Common/MatDefs/Misc/Unshaded.j3md"
|
rlm@0
|
423 :texture "Textures/purpleWisp.png"
|
rlm@0
|
424 :physical? true
|
rlm@0
|
425 :mass 70
|
rlm@0
|
426 :color ColorRGBA/Blue
|
rlm@0
|
427 :shape (Sphere. 10 10 1)}))
|
rlm@0
|
428 (-> (.getMaterial)
|
rlm@0
|
429 (.getAdditionalRenderState)
|
rlm@0
|
430 (.setBlendMode RenderState$BlendMode/Alpha))
|
rlm@0
|
431 (.setQueueBucket RenderQueue$Bucket/Transparent)))
|
rlm@0
|
432
|
rlm@0
|
433 (defn transparent-box []
|
rlm@0
|
434 (doto
|
rlm@0
|
435 (make-shape
|
rlm@0
|
436 (merge base-shape
|
rlm@0
|
437 {:position (Vector3f. 0 2 0)
|
rlm@10
|
438 :name "box"
|
rlm@0
|
439 :material "Common/MatDefs/Misc/Unshaded.j3md"
|
rlm@0
|
440 :texture "Textures/purpleWisp.png"
|
rlm@0
|
441 :physical? true
|
rlm@0
|
442 :mass 70
|
rlm@0
|
443 :color ColorRGBA/Blue
|
rlm@0
|
444 :shape (Box. 1 1 1)}))
|
rlm@0
|
445 (-> (.getMaterial)
|
rlm@0
|
446 (.getAdditionalRenderState)
|
rlm@0
|
447 (.setBlendMode RenderState$BlendMode/Alpha))
|
rlm@0
|
448 (.setQueueBucket RenderQueue$Bucket/Transparent)))
|
rlm@0
|
449
|
rlm@6
|
450 (defn transparent-floor []
|
rlm@6
|
451 (doto
|
rlm@6
|
452 (box 5 0.2 5 :mass 0 :position (Vector3f. 0 -2 0)
|
rlm@6
|
453 :material "Common/MatDefs/Misc/Unshaded.j3md"
|
rlm@10
|
454 :texture "Textures/redWisp.png"
|
rlm@10
|
455 :name "floor")
|
rlm@6
|
456 (-> (.getMaterial)
|
rlm@6
|
457 (.getAdditionalRenderState)
|
rlm@6
|
458 (.setBlendMode RenderState$BlendMode/Alpha))
|
rlm@6
|
459 (.setQueueBucket RenderQueue$Bucket/Transparent)))
|
rlm@6
|
460
|
rlm@69
|
461 (defn test-skin
|
rlm@69
|
462 "Testing touch:
|
rlm@69
|
463 you should see a ball which responds to the table
|
rlm@69
|
464 and whatever balls hit it."
|
rlm@69
|
465 []
|
rlm@0
|
466 (let [b
|
rlm@58
|
467 ;;(transparent-box)
|
rlm@58
|
468 (transparent-sphere)
|
rlm@10
|
469 ;;(sphere)
|
rlm@58
|
470 f (transparent-floor)
|
rlm@6
|
471 debug-node (Node.)
|
rlm@12
|
472 node (doto (Node.) (.attachChild b) (.attachChild f))
|
rlm@12
|
473 root-node (doto (Node.) (.attachChild node)
|
rlm@12
|
474 (.attachChild debug-node))
|
rlm@12
|
475 ]
|
rlm@0
|
476
|
rlm@0
|
477 (world
|
rlm@12
|
478 root-node
|
rlm@15
|
479 {"key-return" (fire-cannon-ball node)}
|
rlm@0
|
480 (fn [world]
|
rlm@20
|
481 ;; (Capture/SimpleCaptureVideo
|
rlm@20
|
482 ;; world
|
rlm@20
|
483 ;; (file-str "/home/r/proj/cortex/tmp/blob.avi"))
|
rlm@20
|
484 ;; (no-logging)
|
rlm@20
|
485 ;;(enable-debug world)
|
rlm@20
|
486 ;; (set-accuracy world (/ 1 60))
|
rlm@58
|
487 )
|
rlm@58
|
488
|
rlm@0
|
489 (fn [& _]
|
rlm@19
|
490 (let [sensitivity 0.2
|
rlm@18
|
491 touch-data (touch-percieve sensitivity b node)]
|
rlm@68
|
492 (manage-ray-debug-node debug-node b touch-data sensitivity))
|
rlm@0
|
493 ))))
|
rlm@0
|
494
|
rlm@37
|
495
|
rlm@0
|
496 #+end_src
|
rlm@0
|
497
|
rlm@0
|
498
|
rlm@10
|
499
|
rlm@10
|
500
|
rlm@6
|
501
|
rlm@0
|
502 * COMMENT code generation
|
rlm@39
|
503 #+begin_src clojure :tangle ../src/cortex/touch.clj
|
rlm@0
|
504 <<skin-main>>
|
rlm@0
|
505 #+end_src
|
rlm@0
|
506
|
rlm@68
|
507 #+begin_src clojure :tangle ../src/cortex/test/touch.clj
|
rlm@39
|
508 <<touch-test>>
|
rlm@39
|
509 #+end_src
|
rlm@39
|
510
|
rlm@0
|
511
|
rlm@0
|
512
|
rlm@0
|
513
|
rlm@32
|
514
|
rlm@32
|
515
|