comparison org/touch.org @ 243:f33fec68f775

touch has been restored, with some very slight speed improvements, and now with much less code
author Robert McIntyre <rlm@mit.edu>
date Sun, 12 Feb 2012 14:14:57 -0700
parents a7f26a074071
children f23217324f72
comparison
equal deleted inserted replaced
242:a7f26a074071 243:f33fec68f775
75 ** TODO add image showing example touch-uv map 75 ** TODO add image showing example touch-uv map
76 ** TODO add metadata display for worm 76 ** TODO add metadata display for worm
77 77
78 78
79 * Skin Creation 79 * Skin Creation
80 * TODO get the actual lengths for each hair 80 * TODO get the actual lengths for each feeler
81
82 #+begin_src clojure
83 pixel-triangles
84 xyz-triangles
85 conversions (map triangles->affine-transform pixel-triangles
86 xyz-triangles)
87
88 #+end_src
89 81
90 82
91 =(touch-kernel)= generates the functions which implement the sense of 83 =(touch-kernel)= generates the functions which implement the sense of
92 touch for a creature. These functions must do 6 things to obtain touch 84 touch for a creature. These functions must do 6 things to obtain touch
93 data. 85 data.
117 For both of these, =(feeler-tips)= 109 For both of these, =(feeler-tips)=
118 110
119 - Generate some sort of topology for the sensors. 111 - Generate some sort of topology for the sensors.
120 =(touch-topology)= 112 =(touch-topology)=
121 113
122 #+begin_src clojure
123
124
125
126
127 #+end_src
128
129
130 114
131 #+name: kernel 115 #+name: kernel
132 #+begin_src clojure 116 #+begin_src clojure
133 (in-ns 'cortex.touch) 117 (in-ns 'cortex.touch)
134 118
135 (declare touch-topology feelers set-ray) 119 (declare touch-topology feelers set-ray)
136 120
137 (defn set-ray [#^Ray ray #^Matrix4f transform 121 (defn set-ray [#^Ray ray #^Matrix4f transform #^Vector3f origin
138 #^Vector3f origin #^Vector3f tip 122 #^Vector3f tip length]
139 length] 123 ;; Doing everything locally recduces garbage collection by enough to
140 (.setOrigin ray (.mult transform origin)) 124 ;; be worth it.
141 (.setDirection ray (.subtract 125 (.mult transform origin (.getOrigin ray))
142 (.mult transform tip) 126
143 (.getOrigin ray))) 127 (.mult transform tip (.getDirection ray))
144 (.setLimit ray length) 128 (.subtractLocal (.getDirection ray) (.getOrigin ray))
145 ray) 129 (.setLimit ray length))
146
147 130
148 (defn touch-kernel 131 (defn touch-kernel
149 "Constructs a function which will return tactile sensory data from 132 "Constructs a function which will return tactile sensory data from
150 'geo when called from inside a running simulation" 133 'geo when called from inside a running simulation"
151 [#^Geometry geo] 134 [#^Geometry geo]
152 (let [profile (tactile-sensor-profile geo) 135 (if-let
153 ray-reference-origins (feeler-origins geo profile) 136 [profile (tactile-sensor-profile geo)]
154 ray-reference-tips (feeler-tips geo profile) 137 (let [ray-reference-origins (feeler-origins geo profile)
155 ray-lengths (repeat 9000 0.1) 138 ray-reference-tips (feeler-tips geo profile)
156 current-rays (map (fn [] (Ray.)) ray-reference-origins) 139 ray-lengths (repeat 9000 0.1)
157 topology (touch-topology geo profile)] 140 current-rays (map (fn [_] (Ray.)) ray-reference-origins)
158 (if (empty? ray-reference-origins) nil 141 topology (touch-topology geo profile)]
159 (fn [node]
160 (let [transform (.getWorldMatrix geo)]
161 (dorun
162 (map (fn [ray ref-origin ref-tip length]
163 (set-ray ray transform ref-origin ref-tip length))
164 current-rays ray-reference-origins
165 ray-reference-tips ray-lengths))
166 (vector
167 topology
168 (vec
169 (for [ray current-rays]
170 (do
171 (let [results (CollisionResults.)]
172 (.collideWith node ray results)
173 (let [touch-objects
174 (filter #(not (= geo (.getGeometry %)))
175 results)]
176 [(if (empty? touch-objects)
177 (.getLimit ray)
178 (.getDistance (first touch-objects)))
179 (.getLimit ray)])))))))))))
180
181 (defn touch-kernel*
182 "Returns a function which returns tactile sensory data when called
183 inside a running simulation."
184 [#^Geometry geo]
185 (let [feeler-coords (feeler-coordinates geo)
186 tris (triangles geo)
187 limit (tactile-scale geo)]
188 (if (empty? (touch-topology geo))
189 nil
190 (fn [node] 142 (fn [node]
191 (let [sensor-origins 143 (let [transform (.getWorldMatrix geo)]
192 (map 144 (dorun
193 #(map (partial local-to-world geo) %) 145 (map (fn [ray ref-origin ref-tip length]
194 feeler-coords) 146 (set-ray ray transform ref-origin ref-tip length))
195 triangle-normals 147 current-rays ray-reference-origins
196 (map (partial get-ray-direction geo) 148 ray-reference-tips ray-lengths))
197 tris)
198 rays
199 (flatten
200 (map (fn [origins norm]
201 (map #(doto (Ray. % norm)
202 (.setLimit limit)) origins))
203 sensor-origins triangle-normals))]
204 (vector 149 (vector
205 (touch-topology geo) 150 topology
206 (vec 151 (vec
207 (for [ray rays] 152 (for [ray current-rays]
208 (do 153 (do
209 (let [results (CollisionResults.)] 154 (let [results (CollisionResults.)]
210 (.collideWith node ray results) 155 (.collideWith node ray results)
211 (let [touch-objects 156 (let [touch-objects
212 (filter #(not (= geo (.getGeometry %))) 157 (filter #(not (= geo (.getGeometry %)))
213 results)] 158 results)]
214 [(if (empty? touch-objects) 159 [(if (empty? touch-objects)
215 limit (.getDistance (first touch-objects))) 160 (.getLimit ray)
216 limit]))))))))))) 161 (.getDistance (first touch-objects)))
162 (.getLimit ray)])))))))))))
217 163
218 (defn touch! 164 (defn touch!
219 "Endow the creature with the sense of touch. Returns a sequence of 165 "Endow the creature with the sense of touch. Returns a sequence of
220 functions, one for each body part with a tactile-sensor-proile, 166 functions, one for each body part with a tactile-sensor-proile,
221 each of which when called returns sensory data for that body part." 167 each of which when called returns sensory data for that body part."
224 (comp not nil?) 170 (comp not nil?)
225 (map touch-kernel 171 (map touch-kernel
226 (filter #(isa? (class %) Geometry) 172 (filter #(isa? (class %) Geometry)
227 (node-seq creature))))) 173 (node-seq creature)))))
228 #+end_src 174 #+end_src
175
176 #+results: kernel
177 : #'cortex.touch/touch!
229 178
230 * Sensor Related Functions 179 * Sensor Related Functions
231 180
232 These functions analyze the touch-sensor-profile image convert the 181 These functions analyze the touch-sensor-profile image convert the
233 location of each touch sensor from pixel coordinates to UV-coordinates 182 location of each touch sensor from pixel coordinates to UV-coordinates
277 (map #(.add % normal) origins)) 226 (map #(.add % normal) origins))
278 world-coords normals))) 227 world-coords normals)))
279 228
280 229
281 (defn touch-topology [#^Geometry geo image] 230 (defn touch-topology [#^Geometry geo image]
282 (collapse (feeler-pixel-coords geo image))) 231 (collapse (reduce concat (feeler-pixel-coords geo image))))
283 232 #+end_src
284
285 (defn sensors-in-triangle
286 "Locate the touch sensors in the triangle, returning a map of their
287 UV and geometry-relative coordinates."
288 [image mesh tri-index]
289 (let [width (.getWidth image)
290 height (.getHeight image)
291 UV-vertex-coords (triangle-UV-coord mesh width height tri-index)
292 bounds (convex-bounds UV-vertex-coords)
293
294 cutout-triangle (points->triangle UV-vertex-coords)
295 UV-sensor-coords
296 (filter (comp (partial inside-triangle? cutout-triangle)
297 (fn [[u v]] (Vector3f. u v 0)))
298 (white-coordinates image bounds))
299 UV->geometry (triangle-transformation
300 cutout-triangle
301 (mesh-triangle mesh tri-index))
302 geometry-sensor-coords
303 (map (fn [[u v]] (.mult UV->geometry (Vector3f. u v 0)))
304 UV-sensor-coords)]
305 {:UV UV-sensor-coords :geometry geometry-sensor-coords}))
306
307 (defn-memo locate-feelers
308 "Search the geometry's tactile UV profile for touch sensors,
309 returning their positions in geometry-relative coordinates."
310 [#^Geometry geo]
311 (let [mesh (.getMesh geo)
312 num-triangles (.getTriangleCount mesh)]
313 (if-let [image (tactile-sensor-profile geo)]
314 (map
315 (partial sensors-in-triangle image mesh)
316 (range num-triangles))
317 (repeat (.getTriangleCount mesh) {:UV nil :geometry nil}))))
318
319 (defn-memo touch-topology
320 "Return a sequence of vectors of the form [x y] describing the
321 \"topology\" of the tactile sensors. Points that are close together
322 in the touch-topology are generally close together in the simulation."
323 [#^Gemoetry geo]
324 (vec (collapse (reduce concat (map :UV (locate-feelers geo))))))
325
326 (defn-memo feeler-coordinates
327 "The location of the touch sensors in world-space coordinates."
328 [#^Geometry geo]
329 (vec (map :geometry (locate-feelers geo))))
330 #+end_src
331
332
333
334 233
335 * Visualizing Touch 234 * Visualizing Touch
336 #+name: visualization 235 #+name: visualization
337 #+begin_src clojure 236 #+begin_src clojure
338 (in-ns 'cortex.touch) 237 (in-ns 'cortex.touch)
455 for translating any coordinate within the UV triangle to the 354 for translating any coordinate within the UV triangle to the
456 cooresponding coordinate in the XYZ triangle. 355 cooresponding coordinate in the XYZ triangle.
457 356
458 #+name: triangles-3 357 #+name: triangles-3
459 #+begin_src clojure 358 #+begin_src clojure
359 (in-ns 'cortex.touch)
360
460 (defn triangle->matrix4f 361 (defn triangle->matrix4f
461 "Converts the triangle into a 4x4 matrix: The first three columns 362 "Converts the triangle into a 4x4 matrix: The first three columns
462 contain the vertices of the triangle; the last contains the unit 363 contain the vertices of the triangle; the last contains the unit
463 normal of the triangle. The bottom row is filled with 1s." 364 normal of the triangle. The bottom row is filled with 1s."
464 [#^Triangle t] 365 [#^Triangle t]
490 It is convienent to treat a =Triangle= as a sequence of verticies, and 391 It is convienent to treat a =Triangle= as a sequence of verticies, and
491 a =Vector2f= and =Vector3f= as a sequence of floats. These conversion 392 a =Vector2f= and =Vector3f= as a sequence of floats. These conversion
492 functions make this easy. If these classes implemented =Iterable= then 393 functions make this easy. If these classes implemented =Iterable= then
493 this code would not be necessary. Hopefully they will in the future. 394 this code would not be necessary. Hopefully they will in the future.
494 395
495 #+name: triangles-2
496 #+begin_src clojure
497 (defn point->vector2f [[u v]]
498 (Vector2f. u v))
499
500 (defn vector2f->vector3f [v]
501 (Vector3f. (.getX v) (.getY v) 0))
502
503 (defn map-triangle [f #^Triangle tri]
504 (Triangle.
505 (f 0 (.get1 tri))
506 (f 1 (.get2 tri))
507 (f 2 (.get3 tri))))
508
509 (defn points->triangle
510 "Convert a list of points into a triangle."
511 [points]
512 (apply #(Triangle. %1 %2 %3)
513 (map (fn [point]
514 (let [point (vec point)]
515 (Vector3f. (get point 0 0)
516 (get point 1 0)
517 (get point 2 0))))
518 (take 3 points))))
519 #+end_src
520
521 396
522 * Triangle Boundaries 397 * Triangle Boundaries
523 398
524 For efficiency's sake I will divide the UV-image into small squares 399 For efficiency's sake I will divide the UV-image into small squares
525 which inscribe each UV-triangle, then extract the points which lie 400 which inscribe each UV-triangle, then extract the points which lie
561 (same-side? vert-1 vert-2 vert-3 p) 436 (same-side? vert-1 vert-2 vert-3 p)
562 (same-side? vert-2 vert-3 vert-1 p) 437 (same-side? vert-2 vert-3 vert-1 p)
563 (same-side? vert-3 vert-1 vert-2 p)))) 438 (same-side? vert-3 vert-1 vert-2 p))))
564 #+end_src 439 #+end_src
565 440
566 #+results: triangles-4
567 : #'cortex.touch/inside-triangle?
568
569
570 * Physics Collision Objects 441 * Physics Collision Objects
571 442
572 The "hairs" are actually =Rays= which extend from a point on a 443 The "hairs" are actually =Rays= which extend from a point on a
573 =Triangle= in the =Mesh= normal to the =Triangle's= surface. 444 =Triangle= in the =Mesh= normal to the =Triangle's= surface.
574 445
575 #+name: rays
576 #+begin_src clojure
577 (defn get-ray-origin
578 "Return the origin which a Ray would have to have to be in the exact
579 center of a particular Triangle in the Geometry in World
580 Coordinates."
581 [geom tri]
582 (let [new (Vector3f.)]
583 (.calculateCenter tri)
584 (.localToWorld geom (.getCenter tri) new) new))
585
586 (defn get-ray-direction
587 "Return the direction which a Ray would have to have to be to point
588 normal to the Triangle, in coordinates relative to the center of the
589 Triangle."
590 [geom tri]
591 (let [n+c (Vector3f.)]
592 (.calculateNormal tri)
593 (.calculateCenter tri)
594 (.localToWorld
595 geom
596 (.add (.getCenter tri) (.getNormal tri)) n+c)
597 (.subtract n+c (get-ray-origin geom tri))))
598 #+end_src
599 * Headers 446 * Headers
600 447
601 #+name: touch-header 448 #+name: touch-header
602 #+begin_src clojure 449 #+begin_src clojure
603 (ns cortex.touch 450 (ns cortex.touch
634 481
635 (fn [world] 482 (fn [world]
636 (light-up-everything world)) 483 (light-up-everything world))
637 484
638 (fn [world tpf] 485 (fn [world tpf]
639 (touch-display (map #(% (.getRootNode world)) touch)))))) 486
487
488 (dorun (map #(% (.getRootNode world)) touch))
489
490
491 ))))
640 #+end_src 492 #+end_src
641 * Source Listing 493 * Source Listing
642 * Next 494 * Next
643 495
644 496
645 * COMMENT Code Generation 497 * COMMENT Code Generation
646 #+begin_src clojure :tangle ../src/cortex/touch.clj 498 #+begin_src clojure :tangle ../src/cortex/touch.clj
647 <<touch-header>> 499 <<touch-header>>
648 <<meta-data>> 500 <<meta-data>>
649 <<triangles-1>> 501 <<triangles-1>>
650 <<triangles-2>>
651 <<triangles-3>> 502 <<triangles-3>>
652 <<triangles-4>> 503 <<triangles-4>>
653 <<sensors>> 504 <<sensors>>
654 <<rays>>
655 <<kernel>> 505 <<kernel>>
656 <<visualization>> 506 <<visualization>>
657 #+end_src 507 #+end_src
658 508
659 509