comparison org/touch.org @ 228:0589c35f04f2

wrote intro for touch.org
author Robert McIntyre <rlm@mit.edu>
date Sat, 11 Feb 2012 18:42:27 -0700
parents 2a7f57e7efdb
children 6f1be9525e40
comparison
equal deleted inserted replaced
227:2a7f57e7efdb 228:0589c35f04f2
9 * Touch 9 * Touch
10 10
11 Touch is critical to navigation and spatial reasoning and as such I 11 Touch is critical to navigation and spatial reasoning and as such I
12 need a simulated version of it to give to my AI creatures. 12 need a simulated version of it to give to my AI creatures.
13 13
14 #+name: skin-main 14 However, touch in my virtual can not exactly correspond to human touch
15 #+begin_src clojure 15 because my creatures are made out of completely rigid segments that
16 (in-ns 'cortex.touch) 16 don't deform like human skin.
17 17
18 (defn triangles 18 Human skin has a wide array of touch sensors, each of which speciliaze
19 "Return a sequence of all the Triangles which compose a given 19 in detecting different vibrational modes and pressures. These sensors
20 Geometry." 20 can integrate a vast expanse of skin (i.e. your entire palm), or a
21 [#^Geometry geom] 21 tiny patch of skin at the tip of your finger. The hairs of the skin
22 (let 22 help detect objects before they even come into contact with the skin
23 [mesh (.getMesh geom) 23 proper.
24 triangles (transient [])] 24
25 (dorun 25 Instead of measuring deformation or vibration, I surround each rigid
26 (for [n (range (.getTriangleCount mesh))] 26 part with a plenitude of hair-like objects which do not interact with
27 (let [tri (Triangle.)] 27 the physical world. Physical objects can pass through them with no
28 (.getTriangle mesh n tri) 28 effect. The hairs are able to measure contact with other objects, and
29 ;; (.calculateNormal tri) 29 constantly report how much of their extent is covered. So, even though
30 ;; (.calculateCenter tri) 30 the creature's body parts do not deform, the hairs create a margin
31 (conj! triangles tri)))) 31 around those body parts which achieves a sense of touch which is a
32 (persistent! triangles))) 32 hybrid between a human's sense of deformation and sense from hairs.
33 33
34 (defn get-ray-origin 34 Implementing touch in jMonkeyEngine follows a different techinal route
35 "Return the origin which a Ray would have to have to be in the exact 35 than vision and hearing. Those two senses piggybacked off
36 center of a particular Triangle in the Geometry in World 36 jMonkeyEngine's 3D audio and video rendering subsystems. To simulate
37 Coordinates." 37 Touch, I use jMonkeyEngine's physics system to execute many small
38 [geom tri] 38 collision detections, one for each "hair".
39 (let [new (Vector3f.)] 39
40 (.calculateCenter tri) 40 * Sensor Related Functions
41 (.localToWorld geom (.getCenter tri) new) new)) 41 #+begin_src clojure
42
43 (defn get-ray-direction
44 "Return the direction which a Ray would have to have to be to point
45 normal to the Triangle, in coordinates relative to the center of the
46 Triangle."
47 [geom tri]
48 (let [n+c (Vector3f.)]
49 (.calculateNormal tri)
50 (.calculateCenter tri)
51 (.localToWorld
52 geom
53 (.add (.getCenter tri) (.getNormal tri)) n+c)
54 (.subtract n+c (get-ray-origin geom tri))))
55
56 ;; Every Mesh has many triangles, each with its own index.
57 ;; Every vertex has its own index as well.
58
59 (defn tactile-sensor-profile
60 "Return the touch-sensor distribution image in BufferedImage format,
61 or nil if it does not exist."
62 [#^Geometry obj]
63 (if-let [image-path (meta-data obj "touch")]
64 (load-image image-path)))
65
66 (defn mesh-triangle
67 "Get the triangle specified by triangle-index from the mesh within
68 bounds."
69 [#^Mesh mesh triangle-index]
70 (let [scratch (Triangle.)]
71 (.getTriangle mesh triangle-index scratch)
72 scratch))
73
74 (defn triangle-vertex-indices
75 "Get the triangle vertex indices of a given triangle from a given
76 mesh."
77 [#^Mesh mesh triangle-index]
78 (let [indices (int-array 3)]
79 (.getTriangle mesh triangle-index indices)
80 (vec indices)))
81
82 (defn vertex-UV-coord
83 "Get the UV-coordinates of the vertex named by vertex-index"
84 [#^Mesh mesh vertex-index]
85 (let [UV-buffer
86 (.getData
87 (.getBuffer
88 mesh
89 VertexBuffer$Type/TexCoord))]
90 [(.get UV-buffer (* vertex-index 2))
91 (.get UV-buffer (+ 1 (* vertex-index 2)))]))
92
93 (defn triangle-UV-coord
94 "Get the UV-cooridnates of the triangle's verticies."
95 [#^Mesh mesh width height triangle-index]
96 (map (fn [[u v]] (vector (* width u) (* height v)))
97 (map (partial vertex-UV-coord mesh)
98 (triangle-vertex-indices mesh triangle-index))))
99
100 (defn same-side?
101 "Given the points p1 and p2 and the reference point ref, is point p
102 on the same side of the line that goes through p1 and p2 as ref is?"
103 [p1 p2 ref p]
104 (<=
105 0
106 (.dot
107 (.cross (.subtract p2 p1) (.subtract p p1))
108 (.cross (.subtract p2 p1) (.subtract ref p1)))))
109
110 (defn triangle-seq [#^Triangle tri]
111 [(.get1 tri) (.get2 tri) (.get3 tri)])
112
113 (defn vector3f-seq [#^Vector3f v]
114 [(.getX v) (.getY v) (.getZ v)])
115
116 (defn inside-triangle?
117 "Is the point inside the triangle?"
118 {:author "Dylan Holmes"}
119 [#^Triangle tri #^Vector3f p]
120 (let [[vert-1 vert-2 vert-3] (triangle-seq tri)]
121 (and
122 (same-side? vert-1 vert-2 vert-3 p)
123 (same-side? vert-2 vert-3 vert-1 p)
124 (same-side? vert-3 vert-1 vert-2 p))))
125
126 (defn triangle->matrix4f
127 "Converts the triangle into a 4x4 matrix: The first three columns
128 contain the vertices of the triangle; the last contains the unit
129 normal of the triangle. The bottom row is filled with 1s."
130 [#^Triangle t]
131 (let [mat (Matrix4f.)
132 [vert-1 vert-2 vert-3]
133 ((comp vec map) #(.get t %) (range 3))
134 unit-normal (do (.calculateNormal t)(.getNormal t))
135 vertices [vert-1 vert-2 vert-3 unit-normal]]
136 (dorun
137 (for [row (range 4) col (range 3)]
138 (do
139 (.set mat col row (.get (vertices row)col))
140 (.set mat 3 row 1))))
141 mat))
142
143 (defn triangle-transformation
144 "Returns the affine transformation that converts each vertex in the
145 first triangle into the corresponding vertex in the second
146 triangle."
147 [#^Triangle tri-1 #^Triangle tri-2]
148 (.mult
149 (triangle->matrix4f tri-2)
150 (.invert (triangle->matrix4f tri-1))))
151
152 (defn point->vector2f [[u v]]
153 (Vector2f. u v))
154
155 (defn vector2f->vector3f [v]
156 (Vector3f. (.getX v) (.getY v) 0))
157
158 (defn map-triangle [f #^Triangle tri]
159 (Triangle.
160 (f 0 (.get1 tri))
161 (f 1 (.get2 tri))
162 (f 2 (.get3 tri))))
163
164 (defn points->triangle
165 "Convert a list of points into a triangle."
166 [points]
167 (apply #(Triangle. %1 %2 %3)
168 (map (fn [point]
169 (let [point (vec point)]
170 (Vector3f. (get point 0 0)
171 (get point 1 0)
172 (get point 2 0))))
173 (take 3 points))))
174
175 (defn convex-bounds
176 "Returns the smallest square containing the given vertices, as a
177 vector of integers [left top width height]."
178 [uv-verts]
179 (let [xs (map first uv-verts)
180 ys (map second uv-verts)
181 x0 (Math/floor (apply min xs))
182 y0 (Math/floor (apply min ys))
183 x1 (Math/ceil (apply max xs))
184 y1 (Math/ceil (apply max ys))]
185 [x0 y0 (- x1 x0) (- y1 y0)]))
186
187 (defn sensors-in-triangle 42 (defn sensors-in-triangle
188 "Locate the touch sensors in the triangle, returning a map of their 43 "Locate the touch sensors in the triangle, returning a map of their
189 UV and geometry-relative coordinates." 44 UV and geometry-relative coordinates."
190 [image mesh tri-index] 45 [image mesh tri-index]
191 (let [width (.getWidth image) 46 (let [width (.getWidth image)
227 82
228 (defn-memo feeler-coordinates 83 (defn-memo feeler-coordinates
229 "The location of the touch sensors in world-space coordinates." 84 "The location of the touch sensors in world-space coordinates."
230 [#^Geometry geo] 85 [#^Geometry geo]
231 (vec (map :geometry (locate-feelers geo)))) 86 (vec (map :geometry (locate-feelers geo))))
232 87 #+end_src
88
89 * Triangle Manipulation Functions
90
91 #+begin_src clojure
92 (defn triangles
93 "Return a sequence of all the Triangles which compose a given
94 Geometry."
95 [#^Geometry geom]
96 (let
97 [mesh (.getMesh geom)
98 triangles (transient [])]
99 (dorun
100 (for [n (range (.getTriangleCount mesh))]
101 (let [tri (Triangle.)]
102 (.getTriangle mesh n tri)
103 ;; (.calculateNormal tri)
104 ;; (.calculateCenter tri)
105 (conj! triangles tri))))
106 (persistent! triangles)))
107
108 (defn mesh-triangle
109 "Get the triangle specified by triangle-index from the mesh within
110 bounds."
111 [#^Mesh mesh triangle-index]
112 (let [scratch (Triangle.)]
113 (.getTriangle mesh triangle-index scratch)
114 scratch))
115
116 (defn triangle-vertex-indices
117 "Get the triangle vertex indices of a given triangle from a given
118 mesh."
119 [#^Mesh mesh triangle-index]
120 (let [indices (int-array 3)]
121 (.getTriangle mesh triangle-index indices)
122 (vec indices)))
123
124 (defn vertex-UV-coord
125 "Get the UV-coordinates of the vertex named by vertex-index"
126 [#^Mesh mesh vertex-index]
127 (let [UV-buffer
128 (.getData
129 (.getBuffer
130 mesh
131 VertexBuffer$Type/TexCoord))]
132 [(.get UV-buffer (* vertex-index 2))
133 (.get UV-buffer (+ 1 (* vertex-index 2)))]))
134
135 (defn triangle-UV-coord
136 "Get the UV-cooridnates of the triangle's verticies."
137 [#^Mesh mesh width height triangle-index]
138 (map (fn [[u v]] (vector (* width u) (* height v)))
139 (map (partial vertex-UV-coord mesh)
140 (triangle-vertex-indices mesh triangle-index))))
141 #+end_src
142
143 * Schrapnel Conversion Functions
144 #+begin_src clojure
145 (defn triangle-seq [#^Triangle tri]
146 [(.get1 tri) (.get2 tri) (.get3 tri)])
147
148 (defn vector3f-seq [#^Vector3f v]
149 [(.getX v) (.getY v) (.getZ v)])
150
151 (defn point->vector2f [[u v]]
152 (Vector2f. u v))
153
154 (defn vector2f->vector3f [v]
155 (Vector3f. (.getX v) (.getY v) 0))
156
157 (defn map-triangle [f #^Triangle tri]
158 (Triangle.
159 (f 0 (.get1 tri))
160 (f 1 (.get2 tri))
161 (f 2 (.get3 tri))))
162
163 (defn points->triangle
164 "Convert a list of points into a triangle."
165 [points]
166 (apply #(Triangle. %1 %2 %3)
167 (map (fn [point]
168 (let [point (vec point)]
169 (Vector3f. (get point 0 0)
170 (get point 1 0)
171 (get point 2 0))))
172 (take 3 points))))
173 #+end_src
174
175 * Triangle Affine Transforms
176
177 #+begin_src clojure
178 (defn triangle->matrix4f
179 "Converts the triangle into a 4x4 matrix: The first three columns
180 contain the vertices of the triangle; the last contains the unit
181 normal of the triangle. The bottom row is filled with 1s."
182 [#^Triangle t]
183 (let [mat (Matrix4f.)
184 [vert-1 vert-2 vert-3]
185 ((comp vec map) #(.get t %) (range 3))
186 unit-normal (do (.calculateNormal t)(.getNormal t))
187 vertices [vert-1 vert-2 vert-3 unit-normal]]
188 (dorun
189 (for [row (range 4) col (range 3)]
190 (do
191 (.set mat col row (.get (vertices row)col))
192 (.set mat 3 row 1))))
193 mat))
194
195 (defn triangle-transformation
196 "Returns the affine transformation that converts each vertex in the
197 first triangle into the corresponding vertex in the second
198 triangle."
199 [#^Triangle tri-1 #^Triangle tri-2]
200 (.mult
201 (triangle->matrix4f tri-2)
202 (.invert (triangle->matrix4f tri-1))))
203 #+end_src
204
205 * Blender Meta-Data
206
207 #+begin_src clojure
208 (defn tactile-sensor-profile
209 "Return the touch-sensor distribution image in BufferedImage format,
210 or nil if it does not exist."
211 [#^Geometry obj]
212 (if-let [image-path (meta-data obj "touch")]
213 (load-image image-path)))
214 #+end_src
215
216 * Physics Collision Objects
217 #+begin_src clojure
218 (defn get-ray-origin
219 "Return the origin which a Ray would have to have to be in the exact
220 center of a particular Triangle in the Geometry in World
221 Coordinates."
222 [geom tri]
223 (let [new (Vector3f.)]
224 (.calculateCenter tri)
225 (.localToWorld geom (.getCenter tri) new) new))
226
227 (defn get-ray-direction
228 "Return the direction which a Ray would have to have to be to point
229 normal to the Triangle, in coordinates relative to the center of the
230 Triangle."
231 [geom tri]
232 (let [n+c (Vector3f.)]
233 (.calculateNormal tri)
234 (.calculateCenter tri)
235 (.localToWorld
236 geom
237 (.add (.getCenter tri) (.getNormal tri)) n+c)
238 (.subtract n+c (get-ray-origin geom tri))))
239 #+end_src
240
241 * Triangle Boundaries
242 #+begin_src clojure
243 (defn same-side?
244 "Given the points p1 and p2 and the reference point ref, is point p
245 on the same side of the line that goes through p1 and p2 as ref is?"
246 [p1 p2 ref p]
247 (<=
248 0
249 (.dot
250 (.cross (.subtract p2 p1) (.subtract p p1))
251 (.cross (.subtract p2 p1) (.subtract ref p1)))))
252
253 (defn inside-triangle?
254 "Is the point inside the triangle?"
255 {:author "Dylan Holmes"}
256 [#^Triangle tri #^Vector3f p]
257 (let [[vert-1 vert-2 vert-3] (triangle-seq tri)]
258 (and
259 (same-side? vert-1 vert-2 vert-3 p)
260 (same-side? vert-2 vert-3 vert-1 p)
261 (same-side? vert-3 vert-1 vert-2 p))))
262
263 (defn convex-bounds
264 "Returns the smallest square containing the given vertices, as a
265 vector of integers [left top width height]."
266 [uv-verts]
267 (let [xs (map first uv-verts)
268 ys (map second uv-verts)
269 x0 (Math/floor (apply min xs))
270 y0 (Math/floor (apply min ys))
271 x1 (Math/ceil (apply max xs))
272 y1 (Math/ceil (apply max ys))]
273 [x0 y0 (- x1 x0) (- y1 y0)]))
274 #+end_src
275
276 * Skin Creation
277
278 #+begin_src clojure
233 (defn touch-fn 279 (defn touch-fn
234 "Returns a function which returns tactile sensory data when called 280 "Returns a function which returns tactile sensory data when called
235 inside a running simulation." 281 inside a running simulation."
236 [#^Geometry geo] 282 [#^Geometry geo]
237 (let [feeler-coords (feeler-coordinates geo) 283 (let [feeler-coords (feeler-coordinates geo)
281 (filter 327 (filter
282 (comp not nil?) 328 (comp not nil?)
283 (map touch-fn 329 (map touch-fn
284 (filter #(isa? (class %) Geometry) 330 (filter #(isa? (class %) Geometry)
285 (node-seq creature))))) 331 (node-seq creature)))))
286 332 #+end_src
333
334 * Visualizing Touch
335
336 #+begin_src clojure
287 (defn view-touch 337 (defn view-touch
288 "Creates a function which accepts a list of touch sensor-data and 338 "Creates a function which accepts a list of touch sensor-data and
289 displays each element to the screen." 339 displays each element to the screen."
290 [] 340 []
291 (view-sense 341 (view-sense
314 (:import com.jme3.collision.CollisionResults) 364 (:import com.jme3.collision.CollisionResults)
315 (:import com.jme3.scene.VertexBuffer$Type) 365 (:import com.jme3.scene.VertexBuffer$Type)
316 (:import (com.jme3.math Triangle Vector3f Vector2f Ray Matrix4f))) 366 (:import (com.jme3.math Triangle Vector3f Vector2f Ray Matrix4f)))
317 #+end_src 367 #+end_src
318 368
369 ;; Every Mesh has many triangles, each with its own index.
370 ;; Every vertex has its own index as well.
371
372 * Source Listing
373 * Next
374
375
319 * COMMENT Code Generation 376 * COMMENT Code Generation
320 #+begin_src clojure :tangle ../src/cortex/touch.clj 377 #+begin_src clojure :tangle ../src/cortex/touch.clj
321 <<skin-main>> 378 <<skin-main>>
322 #+end_src 379 #+end_src
323 380