changeset 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
files org/touch.org
diffstat 1 files changed, 40 insertions(+), 190 deletions(-) [+]
line wrap: on
line diff
     1.1 --- a/org/touch.org	Sun Feb 12 13:48:28 2012 -0700
     1.2 +++ b/org/touch.org	Sun Feb 12 14:14:57 2012 -0700
     1.3 @@ -77,15 +77,7 @@
     1.4  
     1.5  
     1.6  * Skin Creation
     1.7 -* TODO get the actual lengths for each hair
     1.8 -
     1.9 -#+begin_src clojure
    1.10 -pixel-triangles
    1.11 -        xyz-triangles
    1.12 -        conversions (map triangles->affine-transform pixel-triangles
    1.13 -                         xyz-triangles)
    1.14 -
    1.15 -#+end_src
    1.16 +* TODO get the actual lengths for each feeler
    1.17  
    1.18  
    1.19  =(touch-kernel)= generates the functions which implement the sense of
    1.20 @@ -119,14 +111,6 @@
    1.21    - Generate some sort of topology for the sensors.
    1.22      =(touch-topology)=
    1.23  
    1.24 -#+begin_src clojure
    1.25 -
    1.26 -
    1.27 -
    1.28 -
    1.29 -#+end_src
    1.30 -
    1.31 -
    1.32  
    1.33  #+name: kernel
    1.34  #+begin_src clojure
    1.35 @@ -134,77 +118,38 @@
    1.36  
    1.37  (declare touch-topology feelers set-ray)
    1.38  
    1.39 -(defn set-ray [#^Ray ray #^Matrix4f transform
    1.40 -               #^Vector3f origin #^Vector3f tip
    1.41 -               length]
    1.42 -  (.setOrigin ray (.mult transform origin))
    1.43 -  (.setDirection  ray (.subtract
    1.44 -                       (.mult transform tip)
    1.45 -                       (.getOrigin ray)))
    1.46 -  (.setLimit ray length)
    1.47 -  ray)
    1.48 -
    1.49 +(defn set-ray [#^Ray ray #^Matrix4f transform #^Vector3f origin
    1.50 +               #^Vector3f tip length]
    1.51 +  ;; Doing everything locally recduces garbage collection by enough to
    1.52 +  ;; be worth it.
    1.53 +  (.mult transform origin (.getOrigin ray))
    1.54 +  
    1.55 +  (.mult transform tip (.getDirection ray))
    1.56 +  (.subtractLocal (.getDirection ray) (.getOrigin ray))
    1.57 +  (.setLimit ray length))
    1.58  
    1.59  (defn touch-kernel
    1.60    "Constructs a function which will return tactile sensory data from
    1.61     'geo when called from inside a running simulation"
    1.62    [#^Geometry geo]
    1.63 -  (let [profile (tactile-sensor-profile geo)
    1.64 -        ray-reference-origins (feeler-origins geo profile)
    1.65 -        ray-reference-tips (feeler-tips geo profile)
    1.66 -        ray-lengths (repeat 9000 0.1)
    1.67 -        current-rays (map (fn [] (Ray.)) ray-reference-origins)
    1.68 -        topology (touch-topology geo profile)]
    1.69 -    (if (empty? ray-reference-origins) nil
    1.70 -        (fn [node]
    1.71 -          (let [transform (.getWorldMatrix geo)]
    1.72 -            (dorun
    1.73 -             (map (fn [ray ref-origin ref-tip length]
    1.74 -                    (set-ray ray transform ref-origin ref-tip length))
    1.75 -                  current-rays ray-reference-origins
    1.76 -                  ray-reference-tips ray-lengths))
    1.77 -            (vector
    1.78 -             topology
    1.79 -             (vec
    1.80 -              (for [ray current-rays]
    1.81 -                (do
    1.82 -                  (let [results (CollisionResults.)]
    1.83 -                    (.collideWith node ray results)
    1.84 -                    (let [touch-objects
    1.85 -                          (filter #(not (= geo (.getGeometry %)))
    1.86 -                                  results)]
    1.87 -                      [(if (empty? touch-objects)
    1.88 -                         (.getLimit ray)
    1.89 -                         (.getDistance (first touch-objects)))
    1.90 -                       (.getLimit ray)])))))))))))
    1.91 -
    1.92 -(defn touch-kernel*
    1.93 -  "Returns a function which returns tactile sensory data when called
    1.94 -   inside a running simulation."
    1.95 -  [#^Geometry geo]
    1.96 -  (let [feeler-coords (feeler-coordinates geo)
    1.97 -        tris (triangles geo)
    1.98 -        limit (tactile-scale geo)]
    1.99 -    (if (empty? (touch-topology geo))
   1.100 -      nil
   1.101 +  (if-let
   1.102 +      [profile (tactile-sensor-profile geo)]
   1.103 +    (let [ray-reference-origins (feeler-origins geo profile)
   1.104 +          ray-reference-tips (feeler-tips geo profile)
   1.105 +          ray-lengths (repeat 9000 0.1)
   1.106 +          current-rays (map (fn [_] (Ray.)) ray-reference-origins)
   1.107 +          topology (touch-topology geo profile)]
   1.108        (fn [node]
   1.109 -        (let [sensor-origins 
   1.110 -              (map
   1.111 -               #(map (partial local-to-world geo) %)
   1.112 -               feeler-coords)
   1.113 -              triangle-normals 
   1.114 -              (map (partial get-ray-direction geo)
   1.115 -                   tris)
   1.116 -              rays
   1.117 -              (flatten
   1.118 -               (map (fn [origins norm]
   1.119 -                      (map #(doto (Ray. % norm)
   1.120 -                              (.setLimit limit)) origins))
   1.121 -                    sensor-origins triangle-normals))]
   1.122 +        (let [transform (.getWorldMatrix geo)]
   1.123 +          (dorun
   1.124 +           (map (fn [ray ref-origin ref-tip length]
   1.125 +                  (set-ray ray transform ref-origin ref-tip length))
   1.126 +                current-rays ray-reference-origins
   1.127 +                ray-reference-tips ray-lengths))
   1.128            (vector
   1.129 -           (touch-topology geo)
   1.130 +           topology
   1.131             (vec
   1.132 -            (for [ray rays]
   1.133 +            (for [ray current-rays]
   1.134                (do
   1.135                  (let [results (CollisionResults.)]
   1.136                    (.collideWith node ray results)
   1.137 @@ -212,8 +157,9 @@
   1.138                          (filter #(not (= geo (.getGeometry %)))
   1.139                                  results)]
   1.140                      [(if (empty? touch-objects)
   1.141 -                       limit (.getDistance (first touch-objects)))
   1.142 -                     limit])))))))))))
   1.143 +                       (.getLimit ray)
   1.144 +                       (.getDistance (first touch-objects)))
   1.145 +                     (.getLimit ray)])))))))))))
   1.146  
   1.147  (defn touch! 
   1.148    "Endow the creature with the sense of touch. Returns a sequence of
   1.149 @@ -227,6 +173,9 @@
   1.150                  (node-seq creature)))))
   1.151  #+end_src
   1.152  
   1.153 +#+results: kernel
   1.154 +: #'cortex.touch/touch!
   1.155 +
   1.156  * Sensor Related Functions
   1.157  
   1.158  These functions analyze the touch-sensor-profile image convert the
   1.159 @@ -279,59 +228,9 @@
   1.160      
   1.161  
   1.162  (defn touch-topology [#^Geometry geo image]
   1.163 -  (collapse (feeler-pixel-coords geo image)))
   1.164 -  
   1.165 -
   1.166 -(defn sensors-in-triangle
   1.167 -  "Locate the touch sensors in the triangle, returning a map of their
   1.168 -   UV and geometry-relative coordinates."
   1.169 -  [image mesh tri-index]
   1.170 -  (let [width (.getWidth image)
   1.171 -        height (.getHeight image)
   1.172 -        UV-vertex-coords (triangle-UV-coord mesh width height tri-index)
   1.173 -        bounds (convex-bounds UV-vertex-coords)
   1.174 -        
   1.175 -        cutout-triangle (points->triangle UV-vertex-coords)
   1.176 -        UV-sensor-coords
   1.177 -        (filter (comp (partial inside-triangle? cutout-triangle)
   1.178 -                      (fn [[u v]] (Vector3f. u v 0)))
   1.179 -                (white-coordinates image bounds))
   1.180 -        UV->geometry (triangle-transformation
   1.181 -                      cutout-triangle
   1.182 -                      (mesh-triangle mesh tri-index))
   1.183 -        geometry-sensor-coords
   1.184 -        (map (fn [[u v]] (.mult UV->geometry (Vector3f. u v 0)))
   1.185 -             UV-sensor-coords)]
   1.186 -  {:UV UV-sensor-coords :geometry geometry-sensor-coords}))
   1.187 -
   1.188 -(defn-memo locate-feelers
   1.189 -  "Search the geometry's tactile UV profile for touch sensors,
   1.190 -   returning their positions in geometry-relative coordinates."
   1.191 -  [#^Geometry geo]
   1.192 -  (let [mesh (.getMesh geo)
   1.193 -        num-triangles (.getTriangleCount mesh)]
   1.194 -    (if-let [image (tactile-sensor-profile geo)]
   1.195 -      (map
   1.196 -       (partial sensors-in-triangle image mesh)
   1.197 -       (range num-triangles))
   1.198 -      (repeat (.getTriangleCount mesh) {:UV nil :geometry nil}))))
   1.199 -
   1.200 -(defn-memo touch-topology
   1.201 -  "Return a sequence of vectors of the form [x y] describing the
   1.202 -   \"topology\" of the tactile sensors. Points that are close together
   1.203 -   in the touch-topology are generally close together in the simulation."
   1.204 -  [#^Gemoetry geo]
   1.205 -  (vec (collapse (reduce concat (map :UV (locate-feelers geo))))))
   1.206 -
   1.207 -(defn-memo feeler-coordinates
   1.208 -  "The location of the touch sensors in world-space coordinates."
   1.209 -  [#^Geometry geo]
   1.210 -  (vec (map :geometry (locate-feelers geo))))
   1.211 +  (collapse (reduce concat (feeler-pixel-coords geo image))))
   1.212  #+end_src
   1.213  
   1.214 -
   1.215 -
   1.216 -
   1.217  * Visualizing Touch
   1.218  #+name: visualization
   1.219  #+begin_src clojure
   1.220 @@ -457,6 +356,8 @@
   1.221  
   1.222  #+name: triangles-3
   1.223  #+begin_src clojure
   1.224 +(in-ns 'cortex.touch)
   1.225 +
   1.226  (defn triangle->matrix4f
   1.227    "Converts the triangle into a 4x4 matrix: The first three columns
   1.228     contain the vertices of the triangle; the last contains the unit
   1.229 @@ -492,32 +393,6 @@
   1.230  functions make this easy. If these classes implemented =Iterable= then
   1.231  this code would not be necessary. Hopefully they will in the future.
   1.232  
   1.233 -#+name: triangles-2
   1.234 -#+begin_src clojure
   1.235 -(defn point->vector2f [[u v]]
   1.236 -  (Vector2f. u v))
   1.237 -
   1.238 -(defn vector2f->vector3f [v]
   1.239 -  (Vector3f. (.getX v) (.getY v) 0))
   1.240 -
   1.241 -(defn map-triangle [f #^Triangle tri]
   1.242 -  (Triangle.
   1.243 -   (f 0 (.get1 tri))
   1.244 -   (f 1 (.get2 tri))
   1.245 -   (f 2 (.get3 tri))))
   1.246 -
   1.247 -(defn points->triangle
   1.248 -  "Convert a list of points into a triangle."
   1.249 -  [points]
   1.250 -  (apply #(Triangle. %1 %2 %3)
   1.251 -         (map (fn [point]
   1.252 -                (let [point (vec point)]
   1.253 -                  (Vector3f. (get point 0 0)
   1.254 -                             (get point 1 0)
   1.255 -                             (get point 2 0))))
   1.256 -              (take 3 points))))
   1.257 -#+end_src
   1.258 -
   1.259  
   1.260  * Triangle Boundaries
   1.261    
   1.262 @@ -563,39 +438,11 @@
   1.263       (same-side? vert-3 vert-1 vert-2 p))))
   1.264  #+end_src
   1.265  
   1.266 -#+results: triangles-4
   1.267 -: #'cortex.touch/inside-triangle?
   1.268 -
   1.269 -
   1.270  * Physics Collision Objects
   1.271  
   1.272  The "hairs" are actually =Rays= which extend  from a point on a
   1.273  =Triangle= in the =Mesh= normal to the =Triangle's= surface.
   1.274  
   1.275 -#+name: rays
   1.276 -#+begin_src clojure
   1.277 -(defn get-ray-origin
   1.278 -  "Return the origin which a Ray would have to have to be in the exact
   1.279 -  center of a particular Triangle in the Geometry in World
   1.280 -  Coordinates."
   1.281 -  [geom tri]
   1.282 -  (let [new (Vector3f.)]
   1.283 -    (.calculateCenter tri)
   1.284 -    (.localToWorld geom (.getCenter tri) new) new))
   1.285 -
   1.286 -(defn get-ray-direction
   1.287 -  "Return the direction which a Ray would have to have to be to point
   1.288 -  normal to the Triangle, in coordinates relative to the center of the
   1.289 -  Triangle."
   1.290 -  [geom tri]
   1.291 -  (let [n+c (Vector3f.)]
   1.292 -    (.calculateNormal tri)
   1.293 -    (.calculateCenter tri)
   1.294 -    (.localToWorld
   1.295 -     geom
   1.296 -     (.add (.getCenter tri) (.getNormal tri)) n+c)
   1.297 -    (.subtract n+c (get-ray-origin geom tri))))
   1.298 -#+end_src
   1.299  * Headers 
   1.300  
   1.301  #+name: touch-header
   1.302 @@ -636,7 +483,12 @@
   1.303               (light-up-everything world))
   1.304  
   1.305             (fn [world tpf]
   1.306 -             (touch-display (map #(% (.getRootNode world)) touch))))))
   1.307 +
   1.308 +             
   1.309 +             (dorun (map #(% (.getRootNode world)) touch))
   1.310 +
   1.311 +
   1.312 +             ))))
   1.313  #+end_src
   1.314  * Source Listing
   1.315  * Next
   1.316 @@ -647,11 +499,9 @@
   1.317  <<touch-header>>
   1.318  <<meta-data>>
   1.319  <<triangles-1>>
   1.320 -<<triangles-2>>
   1.321  <<triangles-3>>
   1.322  <<triangles-4>>
   1.323  <<sensors>>
   1.324 -<<rays>>
   1.325  <<kernel>>
   1.326  <<visualization>>
   1.327  #+end_src