Mercurial > cortex
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 |