changeset 156:e8df6e76c3e5

refactored touch
author Robert McIntyre <rlm@mit.edu>
date Fri, 03 Feb 2012 06:15:34 -0700
parents 95bf55614211
children 84c67be00abe
files org/sense-util.org org/skin.org org/test-creature.org
diffstat 3 files changed, 250 insertions(+), 277 deletions(-) [+]
line wrap: on
line diff
     1.1 --- a/org/sense-util.org	Fri Feb 03 06:04:30 2012 -0700
     1.2 +++ b/org/sense-util.org	Fri Feb 03 06:15:34 2012 -0700
     1.3 @@ -161,6 +161,19 @@
     1.4                    squeezed))]
     1.5          relocate)))
     1.6  
     1.7 +(defn world-to-local
     1.8 +   "Convert the world coordinates into coordinates relative to the 
     1.9 +   object (i.e. local coordinates), taking into account the rotation
    1.10 +   of object."
    1.11 +   [#^Spatial object world-coordinate]
    1.12 +   (.worldToLocal object world-coordinate nil))
    1.13 +
    1.14 +(defn local-to-world
    1.15 +   "Convert the local coordinates into coordinates into world relative
    1.16 +    coordinates" 
    1.17 +   [#^Spatial object local-coordinate]
    1.18 +   (.localToWorld object local-coordinate nil))
    1.19 +
    1.20  #+end_src
    1.21  
    1.22  #+results: sense-util
     2.1 --- a/org/skin.org	Fri Feb 03 06:04:30 2012 -0700
     2.2 +++ b/org/skin.org	Fri Feb 03 06:15:34 2012 -0700
     2.3 @@ -25,11 +25,15 @@
     2.4    density of triangles along the surface of the Geometry. Enables a
     2.5    Geometry to know what parts of itself are touching nearby objects."
     2.6    {:author "Robert McIntyre"}
     2.7 -  (:use (cortex world util))
     2.8 +  (:use (cortex world util sense))
     2.9    (:import com.jme3.scene.Geometry)
    2.10    (:import com.jme3.collision.CollisionResults)
    2.11 +  (:import jme3tools.converters.ImageToAwt)
    2.12    (:import (com.jme3.math Triangle Vector3f Ray)))
    2.13     
    2.14 +(use 'clojure.contrib.def)
    2.15 +(cortex.import/mega-import-jme3)
    2.16 +
    2.17  (defn triangles
    2.18    "Return a sequence of all the Triangles which compose a given
    2.19    Geometry." 
    2.20 @@ -56,8 +60,7 @@
    2.21      (.localToWorld geom (.getCenter tri) new) new))
    2.22  
    2.23  (defn get-ray-direction
    2.24 -  "Return the direction which a Ray would have to have to be in the
    2.25 -  exact center of a particular Triangle in the Geometry, pointing
    2.26 +  "Return the direction which a Ray would have to have to be to point
    2.27    normal to the Triangle, in coordinates relative to the center of the
    2.28    Triangle."
    2.29    [geom tri]
    2.30 @@ -69,37 +72,239 @@
    2.31       (.add (.getCenter tri) (.getNormal tri)) n+c)
    2.32      (.subtract n+c (get-ray-origin geom tri))))
    2.33  
    2.34 -(defn normal-rays
    2.35 -  "For each Triangle which comprises the Geometry, returns a Ray which
    2.36 -  is centered on that Triangle, points outward in a normal direction,
    2.37 -  and extends for =limit= distance."
    2.38 -  [limit #^Geometry geom]
    2.39 -  (vec
    2.40 -   (map 
    2.41 -    (fn [tri]
    2.42 -      (doto 
    2.43 -          (Ray. (get-ray-origin geom tri)
    2.44 -                (get-ray-direction geom tri))
    2.45 -        (.setLimit limit)))
    2.46 -    (triangles geom))))
    2.47 +;; Every Mesh has many triangles, each with its own index.
    2.48 +;; Every vertex has its own index as well.
    2.49  
    2.50 -(defn touch-percieve
    2.51 -  "Augment a Geometry with the sense of touch. Returns a sequence of
    2.52 -  non-negative integers, one for each triangle, with the value of the
    2.53 -  integer describing how many objects a ray of length =limit=, normal
    2.54 -  to the triangle and originating from its center, encountered. The
    2.55 -  Geometry itself is not counted among the results."
    2.56 -  [limit geom node]
    2.57 -  (let [normals  (normal-rays limit geom)]
    2.58 -    (doall
    2.59 -     (for [ray normals]
    2.60 +(defn tactile-sensor-image
    2.61 +  "Return the touch-sensor distribution image in BufferedImage format,
    2.62 +   or nil if it does not exist."
    2.63 +  [#^Geometry obj]
    2.64 +  (if-let [image-path (meta-data obj "touch")]
    2.65 +    (ImageToAwt/convert
    2.66 +     (.getImage
    2.67 +      (.loadTexture
    2.68 +       (asset-manager)
    2.69 +       image-path))
    2.70 +    false false 0)))
    2.71 +     
    2.72 +
    2.73 +
    2.74 +(defn triangle
    2.75 +  "Get the triangle specified by triangle-index from the mesh within
    2.76 +  bounds."
    2.77 +  [#^Mesh mesh triangle-index]
    2.78 +  (let [scratch (Triangle.)]
    2.79 +    (.getTriangle mesh triangle-index scratch)
    2.80 +    scratch))
    2.81 +
    2.82 +(defn triangle-vertex-indices
    2.83 +  "Get the triangle vertex indices of a given triangle from a given
    2.84 +   mesh."
    2.85 +  [#^Mesh mesh triangle-index]
    2.86 +  (let [indices (int-array 3)]
    2.87 +    (.getTriangle mesh triangle-index indices)
    2.88 +    (vec indices)))
    2.89 +
    2.90 +(defn vertex-UV-coord
    2.91 +  "Get the uv-coordinates of the vertex named by vertex-index"
    2.92 +  [#^Mesh mesh vertex-index]
    2.93 +  (let [UV-buffer
    2.94 +        (.getData
    2.95 +         (.getBuffer
    2.96 +          mesh
    2.97 +          VertexBuffer$Type/TexCoord))]
    2.98 +    [(.get UV-buffer (* vertex-index 2))
    2.99 +     (.get UV-buffer (+ 1 (* vertex-index 2)))]))
   2.100 +
   2.101 +(defn triangle-UV-coord
   2.102 +  "Get the uv-cooridnates of the triangle's verticies."
   2.103 +  [#^Mesh mesh width height triangle-index]
   2.104 +  (map (fn [[u v]] (vector (* width u) (* height v)))
   2.105 +       (map (partial vertex-UV-coord mesh)
   2.106 +            (triangle-vertex-indices mesh triangle-index))))
   2.107 +  
   2.108 +(defn same-side?
   2.109 +  "Given the points p1 and p2 and the reference point ref, is point p
   2.110 +  on the same side of the line that goes through p1 and p2 as ref is?" 
   2.111 +  [p1 p2 ref p]
   2.112 +  (<=
   2.113 +   0
   2.114 +   (.dot 
   2.115 +    (.cross (.subtract p2 p1) (.subtract p p1))
   2.116 +    (.cross (.subtract p2 p1) (.subtract ref p1)))))
   2.117 +
   2.118 +(defn triangle-seq [#^Triangle tri]
   2.119 +  [(.get1 tri) (.get2 tri) (.get3 tri)])
   2.120 +
   2.121 +(defn vector3f-seq [#^Vector3f v]
   2.122 +  [(.getX v) (.getY v) (.getZ v)])
   2.123 +
   2.124 +(defn inside-triangle?
   2.125 +  "Is the point inside the triangle?"
   2.126 +  {:author "Dylan Holmes"}
   2.127 +  [#^Triangle tri #^Vector3f p]
   2.128 +  (let [[vert-1 vert-2 vert-3] (triangle-seq tri)]
   2.129 +    (and
   2.130 +     (same-side? vert-1 vert-2 vert-3 p)
   2.131 +     (same-side? vert-2 vert-3 vert-1 p)
   2.132 +     (same-side? vert-3 vert-1 vert-2 p))))
   2.133 +
   2.134 +(defn triangle->matrix4f
   2.135 +  "Converts the triangle into a 4x4 matrix: The first three columns
   2.136 +   contain the vertices of the triangle; the last contains the unit
   2.137 +   normal of the triangle. The bottom row is filled with 1s."
   2.138 +  [#^Triangle t]
   2.139 +  (let [mat (Matrix4f.)
   2.140 +        [vert-1 vert-2 vert-3]
   2.141 +        ((comp vec map) #(.get t %) (range 3))
   2.142 +        unit-normal (do (.calculateNormal t)(.getNormal t))
   2.143 +        vertices [vert-1 vert-2 vert-3 unit-normal]]
   2.144 +    (dorun 
   2.145 +     (for [row (range 4) col (range 3)]
   2.146         (do
   2.147 -         (let [results (CollisionResults.)]
   2.148 -           (.collideWith node ray results)
   2.149 -           (let [touch-objects
   2.150 -                 (set (filter #(not (= geom %))
   2.151 -                              (map #(.getGeometry %) results)))]
   2.152 -             (count touch-objects))))))))
   2.153 +         (.set mat col row (.get (vertices row)col))
   2.154 +         (.set mat 3 row 1))))
   2.155 +    mat))
   2.156 +
   2.157 +(defn triangle-transformation
   2.158 +  "Returns the affine transformation that converts each vertex in the
   2.159 +   first triangle into the corresponding vertex in the second
   2.160 +   triangle."
   2.161 +  [#^Triangle tri-1 #^Triangle tri-2]
   2.162 +  (.mult 
   2.163 +   (triangle->matrix4f tri-2)
   2.164 +   (.invert (triangle->matrix4f tri-1))))
   2.165 +
   2.166 +(defn point->vector2f [[u v]]
   2.167 +  (Vector2f. u v))
   2.168 +
   2.169 +(defn vector2f->vector3f [v]
   2.170 +  (Vector3f. (.getX v) (.getY v) 0))
   2.171 +
   2.172 +(defn map-triangle [f #^Triangle tri]
   2.173 +  (Triangle.
   2.174 +   (f 0 (.get1 tri))
   2.175 +   (f 1 (.get2 tri))
   2.176 +   (f 2 (.get3 tri))))
   2.177 +
   2.178 +(defn points->triangle
   2.179 +  "Convert a list of points into a triangle."
   2.180 +  [points]
   2.181 +  (apply #(Triangle. %1 %2 %3)
   2.182 +         (map (fn [point]
   2.183 +                (let [point (vec point)]
   2.184 +                  (Vector3f. (get point 0 0)
   2.185 +                             (get point 1 0)
   2.186 +                             (get point 2 0))))
   2.187 +              (take 3 points))))
   2.188 +
   2.189 +(defn convex-bounds
   2.190 +  ;;dylan
   2.191 +  "Returns the smallest square containing the given
   2.192 +vertices, as a vector of integers [left top width height]."
   2.193 + ;; "Dimensions of the smallest integer bounding square of the list of
   2.194 + ;;  2D verticies in the form: [x y width height]."
   2.195 +  [uv-verts]
   2.196 +  (let [xs (map first uv-verts)
   2.197 +        ys (map second uv-verts)
   2.198 +        x0 (Math/floor (apply min xs))
   2.199 +        y0 (Math/floor (apply min ys))
   2.200 +        x1 (Math/ceil (apply max xs))
   2.201 +        y1 (Math/ceil (apply max ys))]
   2.202 +    [x0 y0 (- x1 x0) (- y1 y0)]))
   2.203 +
   2.204 +(defn sensors-in-triangle
   2.205 +  ;;dylan
   2.206 +  "Locate the touch sensors in the triangle, returning a map of their UV and geometry-relative coordinates."
   2.207 +  ;;"Find the locations of the touch sensors within a triangle in both
   2.208 +  ;; UV and gemoetry relative coordinates."
   2.209 +  [image mesh tri-index]
   2.210 +  (let [width (.getWidth image)
   2.211 +        height (.getHeight image)
   2.212 +        UV-vertex-coords (triangle-UV-coord mesh width height tri-index)
   2.213 +        bounds (convex-bounds UV-vertex-coords)
   2.214 +        
   2.215 +        cutout-triangle (points->triangle UV-vertex-coords)
   2.216 +        UV-sensor-coords
   2.217 +        (filter (comp (partial inside-triangle? cutout-triangle)
   2.218 +                      (fn [[u v]] (Vector3f. u v 0)))
   2.219 +                (white-coordinates image bounds))
   2.220 +        UV->geometry (triangle-transformation
   2.221 +                      cutout-triangle
   2.222 +                      (triangle mesh tri-index))
   2.223 +        geometry-sensor-coords
   2.224 +        (map (fn [[u v]] (.mult UV->geometry (Vector3f. u v 0)))
   2.225 +             UV-sensor-coords)]
   2.226 +  {:UV UV-sensor-coords :geometry geometry-sensor-coords}))
   2.227 +
   2.228 +(defn-memo locate-feelers
   2.229 +  "Search the geometry's tactile UV image for touch sensors, returning
   2.230 +  their positions in geometry-relative coordinates."
   2.231 +  [#^Geometry geo]
   2.232 +  (let [mesh (.getMesh geo)
   2.233 +        num-triangles (.getTriangleCount mesh)]
   2.234 +    (if-let [image (tactile-sensor-image geo)]
   2.235 +      (map
   2.236 +       (partial sensors-in-triangle image mesh)
   2.237 +       (range num-triangles))
   2.238 +      (repeat (.getTriangleCount mesh) {:UV nil :geometry nil}))))
   2.239 +
   2.240 +
   2.241 +
   2.242 +(defn-memo touch-topology [#^Gemoetry geo]
   2.243 +  (vec (collapse (reduce concat (map :UV (locate-feelers geo))))))
   2.244 +
   2.245 +(defn-memo feeler-coordinates [#^Geometry geo]
   2.246 +  (vec (map :geometry (locate-feelers geo))))
   2.247 +
   2.248 +(defn enable-touch [#^Geometry geo]
   2.249 +  (let [feeler-coords (feeler-coordinates geo)
   2.250 +        tris (triangles geo)
   2.251 +        limit 0.1
   2.252 +        ;;results (CollisionResults.)
   2.253 +        ]
   2.254 +    (if (empty? (touch-topology geo))
   2.255 +      nil
   2.256 +      (fn [node]
   2.257 +        (let [sensor-origins 
   2.258 +              (map
   2.259 +               #(map (partial local-to-world geo) %)
   2.260 +               feeler-coords)
   2.261 +              triangle-normals 
   2.262 +              (map (partial get-ray-direction geo)
   2.263 +                   tris)
   2.264 +              rays
   2.265 +              (flatten
   2.266 +               (map (fn [origins norm]
   2.267 +                      (map #(doto (Ray. % norm)
   2.268 +                              (.setLimit limit)) origins))
   2.269 +                    sensor-origins triangle-normals))]
   2.270 +          (vector
   2.271 +           (touch-topology geo)
   2.272 +           (vec
   2.273 +            (for [ray rays]
   2.274 +              (do
   2.275 +                (let [results (CollisionResults.)]
   2.276 +                  (.collideWith node ray results)
   2.277 +                  (let [touch-objects
   2.278 +                        (filter #(not (= geo (.getGeometry %)))
   2.279 +                                results)]
   2.280 +                    (- 255
   2.281 +                       (if (empty? touch-objects) 255
   2.282 +                           (rem 
   2.283 +                            (int
   2.284 +                             (* 255 (/ (.getDistance
   2.285 +                                        (first touch-objects)) limit)))
   2.286 +                            256))))))))))))))
   2.287 +                         
   2.288 +  
   2.289 +(defn touch [#^Node pieces]
   2.290 +  (filter (comp not nil?)
   2.291 +          (map enable-touch
   2.292 +               (filter #(isa? (class %) Geometry)
   2.293 +                       (node-seq pieces)))))
   2.294 +
   2.295 +
   2.296  #+end_src
   2.297  
   2.298  
     3.1 --- a/org/test-creature.org	Fri Feb 03 06:04:30 2012 -0700
     3.2 +++ b/org/test-creature.org	Fri Feb 03 06:15:34 2012 -0700
     3.3 @@ -77,18 +77,6 @@
     3.4               (.getZ in)
     3.5               (- (.getY in))))
     3.6  
     3.7 -(defn world-to-local
     3.8 -   "Convert the world coordinates into coordinates relative to the 
     3.9 -   object (i.e. local coordinates), taking into account the rotation
    3.10 -   of object."
    3.11 -   [#^Spatial object world-coordinate]
    3.12 -   (.worldToLocal object world-coordinate nil))
    3.13 -
    3.14 -(defn local-to-world
    3.15 -   "Convert the local coordinates into coordinates into world relative
    3.16 -    coordinates" 
    3.17 -   [#^Spatial object local-coordinate]
    3.18 -   (.localToWorld object local-coordinate nil))
    3.19  
    3.20  (defmulti joint-dispatch
    3.21    "Translate blender pseudo-joints into real JME joints."
    3.22 @@ -245,8 +233,6 @@
    3.23  
    3.24  (def worm "Models/creature1/try-again.blend")
    3.25  
    3.26 -(def touch "Models/creature1/touch.blend")
    3.27 -
    3.28  (defn worm-model [] (load-blender-model worm))
    3.29  
    3.30  (defn x-ray [#^ColorRGBA color]
    3.31 @@ -263,237 +249,6 @@
    3.32  
    3.33  (import ij.ImagePlus)
    3.34  
    3.35 -;; Every Mesh has many triangles, each with its own index.
    3.36 -;; Every vertex has its own index as well.
    3.37 -
    3.38 -(defn tactile-sensor-image
    3.39 -  "Return the touch-sensor distribution image in BufferedImage format,
    3.40 -   or nil if it does not exist."
    3.41 -  [#^Geometry obj]
    3.42 -  (if-let [image-path (meta-data obj "touch")]
    3.43 -    (ImageToAwt/convert
    3.44 -     (.getImage
    3.45 -      (.loadTexture
    3.46 -       (asset-manager)
    3.47 -       image-path))
    3.48 -    false false 0)))
    3.49 -     
    3.50 -
    3.51 -
    3.52 -(defn triangle
    3.53 -  "Get the triangle specified by triangle-index from the mesh within
    3.54 -  bounds."
    3.55 -  [#^Mesh mesh triangle-index]
    3.56 -  (let [scratch (Triangle.)]
    3.57 -    (.getTriangle mesh triangle-index scratch)
    3.58 -    scratch))
    3.59 -
    3.60 -(defn triangle-vertex-indices
    3.61 -  "Get the triangle vertex indices of a given triangle from a given
    3.62 -   mesh."
    3.63 -  [#^Mesh mesh triangle-index]
    3.64 -  (let [indices (int-array 3)]
    3.65 -    (.getTriangle mesh triangle-index indices)
    3.66 -    (vec indices)))
    3.67 -
    3.68 -(defn vertex-UV-coord
    3.69 -  "Get the uv-coordinates of the vertex named by vertex-index"
    3.70 -  [#^Mesh mesh vertex-index]
    3.71 -  (let [UV-buffer
    3.72 -        (.getData
    3.73 -         (.getBuffer
    3.74 -          mesh
    3.75 -          VertexBuffer$Type/TexCoord))]
    3.76 -    [(.get UV-buffer (* vertex-index 2))
    3.77 -     (.get UV-buffer (+ 1 (* vertex-index 2)))]))
    3.78 -
    3.79 -(defn triangle-UV-coord
    3.80 -  "Get the uv-cooridnates of the triangle's verticies."
    3.81 -  [#^Mesh mesh width height triangle-index]
    3.82 -  (map (fn [[u v]] (vector (* width u) (* height v)))
    3.83 -       (map (partial vertex-UV-coord mesh)
    3.84 -            (triangle-vertex-indices mesh triangle-index))))
    3.85 -  
    3.86 -(defn same-side?
    3.87 -  "Given the points p1 and p2 and the reference point ref, is point p
    3.88 -  on the same side of the line that goes through p1 and p2 as ref is?" 
    3.89 -  [p1 p2 ref p]
    3.90 -  (<=
    3.91 -   0
    3.92 -   (.dot 
    3.93 -    (.cross (.subtract p2 p1) (.subtract p p1))
    3.94 -    (.cross (.subtract p2 p1) (.subtract ref p1)))))
    3.95 -
    3.96 -(defn triangle-seq [#^Triangle tri]
    3.97 -  [(.get1 tri) (.get2 tri) (.get3 tri)])
    3.98 -
    3.99 -(defn vector3f-seq [#^Vector3f v]
   3.100 -  [(.getX v) (.getY v) (.getZ v)])
   3.101 -
   3.102 -(defn inside-triangle?
   3.103 -  "Is the point inside the triangle?"
   3.104 -  {:author "Dylan Holmes"}
   3.105 -  [#^Triangle tri #^Vector3f p]
   3.106 -  (let [[vert-1 vert-2 vert-3] (triangle-seq tri)]
   3.107 -    (and
   3.108 -     (same-side? vert-1 vert-2 vert-3 p)
   3.109 -     (same-side? vert-2 vert-3 vert-1 p)
   3.110 -     (same-side? vert-3 vert-1 vert-2 p))))
   3.111 -
   3.112 -(defn triangle->matrix4f
   3.113 -  "Converts the triangle into a 4x4 matrix: The first three columns
   3.114 -   contain the vertices of the triangle; the last contains the unit
   3.115 -   normal of the triangle. The bottom row is filled with 1s."
   3.116 -  [#^Triangle t]
   3.117 -  (let [mat (Matrix4f.)
   3.118 -        [vert-1 vert-2 vert-3]
   3.119 -        ((comp vec map) #(.get t %) (range 3))
   3.120 -        unit-normal (do (.calculateNormal t)(.getNormal t))
   3.121 -        vertices [vert-1 vert-2 vert-3 unit-normal]]
   3.122 -    (dorun 
   3.123 -     (for [row (range 4) col (range 3)]
   3.124 -       (do
   3.125 -         (.set mat col row (.get (vertices row)col))
   3.126 -         (.set mat 3 row 1))))
   3.127 -    mat))
   3.128 -
   3.129 -(defn triangle-transformation
   3.130 -  "Returns the affine transformation that converts each vertex in the
   3.131 -   first triangle into the corresponding vertex in the second
   3.132 -   triangle."
   3.133 -  [#^Triangle tri-1 #^Triangle tri-2]
   3.134 -  (.mult 
   3.135 -   (triangle->matrix4f tri-2)
   3.136 -   (.invert (triangle->matrix4f tri-1))))
   3.137 -
   3.138 -(defn point->vector2f [[u v]]
   3.139 -  (Vector2f. u v))
   3.140 -
   3.141 -(defn vector2f->vector3f [v]
   3.142 -  (Vector3f. (.getX v) (.getY v) 0))
   3.143 -
   3.144 -(defn map-triangle [f #^Triangle tri]
   3.145 -  (Triangle.
   3.146 -   (f 0 (.get1 tri))
   3.147 -   (f 1 (.get2 tri))
   3.148 -   (f 2 (.get3 tri))))
   3.149 -
   3.150 -(defn points->triangle
   3.151 -  "Convert a list of points into a triangle."
   3.152 -  [points]
   3.153 -  (apply #(Triangle. %1 %2 %3)
   3.154 -         (map (fn [point]
   3.155 -                (let [point (vec point)]
   3.156 -                  (Vector3f. (get point 0 0)
   3.157 -                             (get point 1 0)
   3.158 -                             (get point 2 0))))
   3.159 -              (take 3 points))))
   3.160 -
   3.161 -(defn convex-bounds
   3.162 -  ;;dylan
   3.163 -  "Returns the smallest square containing the given
   3.164 -vertices, as a vector of integers [left top width height]."
   3.165 - ;; "Dimensions of the smallest integer bounding square of the list of
   3.166 - ;;  2D verticies in the form: [x y width height]."
   3.167 -  [uv-verts]
   3.168 -  (let [xs (map first uv-verts)
   3.169 -        ys (map second uv-verts)
   3.170 -        x0 (Math/floor (apply min xs))
   3.171 -        y0 (Math/floor (apply min ys))
   3.172 -        x1 (Math/ceil (apply max xs))
   3.173 -        y1 (Math/ceil (apply max ys))]
   3.174 -    [x0 y0 (- x1 x0) (- y1 y0)]))
   3.175 -
   3.176 -(defn sensors-in-triangle
   3.177 -  ;;dylan
   3.178 -  "Locate the touch sensors in the triangle, returning a map of their UV and geometry-relative coordinates."
   3.179 -  ;;"Find the locations of the touch sensors within a triangle in both
   3.180 -  ;; UV and gemoetry relative coordinates."
   3.181 -  [image mesh tri-index]
   3.182 -  (let [width (.getWidth image)
   3.183 -        height (.getHeight image)
   3.184 -        UV-vertex-coords (triangle-UV-coord mesh width height tri-index)
   3.185 -        bounds (convex-bounds UV-vertex-coords)
   3.186 -        
   3.187 -        cutout-triangle (points->triangle UV-vertex-coords)
   3.188 -        UV-sensor-coords
   3.189 -        (filter (comp (partial inside-triangle? cutout-triangle)
   3.190 -                      (fn [[u v]] (Vector3f. u v 0)))
   3.191 -                (white-coordinates image bounds))
   3.192 -        UV->geometry (triangle-transformation
   3.193 -                      cutout-triangle
   3.194 -                      (triangle mesh tri-index))
   3.195 -        geometry-sensor-coords
   3.196 -        (map (fn [[u v]] (.mult UV->geometry (Vector3f. u v 0)))
   3.197 -             UV-sensor-coords)]
   3.198 -  {:UV UV-sensor-coords :geometry geometry-sensor-coords}))
   3.199 -
   3.200 -(defn-memo locate-feelers
   3.201 -  "Search the geometry's tactile UV image for touch sensors, returning
   3.202 -  their positions in geometry-relative coordinates."
   3.203 -  [#^Geometry geo]
   3.204 -  (let [mesh (.getMesh geo)
   3.205 -        num-triangles (.getTriangleCount mesh)]
   3.206 -    (if-let [image (tactile-sensor-image geo)]
   3.207 -      (map
   3.208 -       (partial sensors-in-triangle image mesh)
   3.209 -       (range num-triangles))
   3.210 -      (repeat (.getTriangleCount mesh) {:UV nil :geometry nil}))))
   3.211 -
   3.212 -(use 'clojure.contrib.def)
   3.213 -
   3.214 -(defn-memo touch-topology [#^Gemoetry geo]
   3.215 -  (vec (collapse (reduce concat (map :UV (locate-feelers geo))))))
   3.216 -
   3.217 -(defn-memo feeler-coordinates [#^Geometry geo]
   3.218 -  (vec (map :geometry (locate-feelers geo))))
   3.219 -
   3.220 -(defn enable-touch [#^Geometry geo]
   3.221 -  (let [feeler-coords (feeler-coordinates geo)
   3.222 -        tris (triangles geo)
   3.223 -        limit 0.1
   3.224 -        ;;results (CollisionResults.)
   3.225 -        ]
   3.226 -    (if (empty? (touch-topology geo))
   3.227 -      nil
   3.228 -      (fn [node]
   3.229 -        (let [sensor-origins 
   3.230 -              (map
   3.231 -               #(map (partial local-to-world geo) %)
   3.232 -               feeler-coords)
   3.233 -              triangle-normals 
   3.234 -              (map (partial get-ray-direction geo)
   3.235 -                   tris)
   3.236 -              rays
   3.237 -              (flatten
   3.238 -               (map (fn [origins norm]
   3.239 -                      (map #(doto (Ray. % norm)
   3.240 -                              (.setLimit limit)) origins))
   3.241 -                    sensor-origins triangle-normals))]
   3.242 -          (vector
   3.243 -           (touch-topology geo)
   3.244 -           (vec
   3.245 -            (for [ray rays]
   3.246 -              (do
   3.247 -                (let [results (CollisionResults.)]
   3.248 -                  (.collideWith node ray results)
   3.249 -                  (let [touch-objects
   3.250 -                        (filter #(not (= geo (.getGeometry %)))
   3.251 -                                results)]
   3.252 -                    (- 255
   3.253 -                       (if (empty? touch-objects) 255
   3.254 -                           (rem 
   3.255 -                            (int
   3.256 -                             (* 255 (/ (.getDistance
   3.257 -                                        (first touch-objects)) limit)))
   3.258 -                            256))))))))))))))
   3.259 -                         
   3.260 -  
   3.261 -(defn touch [#^Node pieces]
   3.262 -  (filter (comp not nil?)
   3.263 -          (map enable-touch
   3.264 -               (filter #(isa? (class %) Geometry)
   3.265 -                       (node-seq pieces)))))
   3.266  
   3.267  
   3.268  (defn test-eye  []