changeset 97:2ff8c7c4e64d

have function for creating touch for a blender creature
author Robert McIntyre <rlm@mit.edu>
date Wed, 11 Jan 2012 00:06:33 -0700
parents 4a9096f31017
children 5b23961433e3
files assets/Models/creature1/tip.png org/test-creature.org
diffstat 2 files changed, 182 insertions(+), 200 deletions(-) [+]
line wrap: on
line diff
     1.1 Binary file assets/Models/creature1/tip.png has changed
     2.1 --- a/org/test-creature.org	Tue Jan 10 21:26:41 2012 -0700
     2.2 +++ b/org/test-creature.org	Wed Jan 11 00:06:33 2012 -0700
     2.3 @@ -350,19 +350,22 @@
     2.4         (triangle-indices mesh (.getIndex triangle))))
     2.5  
     2.6  (defn touch-receptor-image
     2.7 -  "Return the touch-sensor distribution image in ImagePlus format."
     2.8 +  "Return the touch-sensor distribution image in ImagePlus format, or
     2.9 +   nil if it does not exist."
    2.10    [#^Geometry obj]
    2.11 -  (let
    2.12 -      [mat (.getMaterial obj)
    2.13 -       texture
    2.14 -       (.getTextureValue
    2.15 -        (.getTextureParam
    2.16 -         mat
    2.17 -         MaterialHelper/TEXTURE_TYPE_DIFFUSE))
    2.18 -       im (.getImage texture)]
    2.19 -       (ImagePlus.
    2.20 -        "UV-map"
    2.21 -        (ImageToAwt/convert im false false 0))))
    2.22 +  (let [mat (.getMaterial obj)]
    2.23 +    (if-let [texture-param
    2.24 +             (.getTextureParam
    2.25 +              mat
    2.26 +              MaterialHelper/TEXTURE_TYPE_DIFFUSE)]
    2.27 +      (let
    2.28 +          [texture
    2.29 +           (.getTextureValue texture-param)
    2.30 +           im (.getImage texture)]
    2.31 +        (ImagePlus.
    2.32 +         "UV-map"
    2.33 +         (ImageToAwt/convert im false false 0))))))
    2.34 +      
    2.35  
    2.36  
    2.37  (import ij.process.ImageProcessor)
    2.38 @@ -533,200 +536,84 @@
    2.39       ]))
    2.40    
    2.41  
    2.42 -(defn locate-tactile-sensors
    2.43 +(defn locate-feelers
    2.44    "Search the geometry's tactile UV image for touch sensors, returning
    2.45    their positions in geometry-relative coordinates."
    2.46    [#^Geometry geo]
    2.47 -  (let [mesh (.getMesh geo)
    2.48 +  (if-let [image (touch-receptor-image geo)]
    2.49 +    (let [mesh (.getMesh geo)
    2.50 +          tris (triangles geo)
    2.51 +          
    2.52 +          
    2.53 +          width (.getWidth image)
    2.54 +          height (.getHeight image)
    2.55 +          
    2.56 +          ;; for each triangle
    2.57 +          sensor-coords
    2.58 +          (fn [tri]
    2.59 +            ;; translate triangle to uv-pixel-space
    2.60 +            (let [uv-tri
    2.61 +                  (pixel-triangle mesh tri width height)
    2.62 +                  bounds (vec (triangle-bounds uv-tri))]
    2.63 +              
    2.64 +              ;; get that part of the picture
    2.65 +              
    2.66 +              (apply #(.setRoi image %1 %2 %3 %4) bounds)
    2.67 +              (let [cutout (.crop (.getProcessor image))
    2.68 +                    ;; extract white pixels inside triangle
    2.69 +                    cutout-tri
    2.70 +                    (map-triangle
    2.71 +                     (fn [_ v]
    2.72 +                       (.subtract
    2.73 +                        v
    2.74 +                        (Vector3f. (bounds 0) (bounds 1) (float 0))))
    2.75 +                     uv-tri)
    2.76 +                    whites (filter (partial inside-triangle? cutout-tri)
    2.77 +                                   (map vector2f->vector3f
    2.78 +                                        (white-coordinates cutout)))
    2.79 +                    ;; translate pixel coordinates to world-space
    2.80 +                    transform (triangle-transformation cutout-tri tri)]
    2.81 +                (map #(.mult transform %) whites))))]
    2.82 +      (vec (map sensor-coords tris)))
    2.83 +    (repeat (count (triangles geo)) [])))
    2.84 +  
    2.85 +(defn enable-touch [#^Geometry geo]
    2.86 +  (let [feeler-coords (locate-feelers geo)
    2.87          tris (triangles geo)
    2.88 -        
    2.89 -        image (touch-receptor-image geo)
    2.90 -        width (.getWidth image)
    2.91 -        height (.getHeight image)
    2.92 -        
    2.93 +        limit 0.1]
    2.94 +    (fn [node]
    2.95 +      (let [sensor-origins 
    2.96 +            (map
    2.97 +             #(map (partial local-to-world geo) %)
    2.98 +             feeler-coords)
    2.99 +            triangle-normals 
   2.100 +            (map (partial get-ray-direction geo)
   2.101 +                 tris)
   2.102 +            rays
   2.103 +             (flatten
   2.104 +              (map (fn [origins norm]
   2.105 +                     (map #(doto (Ray. % norm)
   2.106 +                              (.setLimit limit)) origins))
   2.107 +                   sensor-origins triangle-normals))]
   2.108 +        (for [ray rays]
   2.109 +          (do
   2.110 +            (let [results (CollisionResults.)]
   2.111 +              (.collideWith node ray results)
   2.112 +              (let [touch-objects
   2.113 +                    (set
   2.114 +                     (filter #(not (= geo %))
   2.115 +                             (map #(.getGeometry %) results)))]
   2.116 +                (count touch-objects)))))))))
   2.117  
   2.118 -        ;; for each triangle
   2.119 -        sensor-coords
   2.120 -        (fn [tri]
   2.121 -          ;; translate triangle to uv-pixel-space
   2.122 -          (let [uv-tri
   2.123 -                (pixel-triangle mesh tri width height)
   2.124 -                bounds (vec (triangle-bounds uv-tri))]
   2.125 -            
   2.126 -            ;; get that part of the picture
   2.127 -            
   2.128 -            (apply #(.setRoi image %1 %2 %3 %4) bounds)
   2.129 -            (let [cutout (.crop (.getProcessor image))
   2.130 -                  ;; extract white pixels inside triangle
   2.131 -                  cutout-tri
   2.132 -                  (map-triangle
   2.133 -                   (fn [_ v]
   2.134 -                     (.subtract
   2.135 -                      v
   2.136 -                      (Vector3f. (bounds 0) (bounds 1) (float 0))))
   2.137 -                   uv-tri)
   2.138 -                  whites (filter (partial inside-triangle? cutout-tri)
   2.139 -                                 (map vector2f->vector3f
   2.140 -                                      (white-coordinates cutout)))
   2.141 -                  ;; translate pixel coordinates to world-space
   2.142 -                  transform (triangle-transformation cutout-tri tri)]
   2.143 -              (map #(.mult transform %) whites))))]
   2.144 -
   2.145 -
   2.146 +(defn touch [#^Node pieces]
   2.147 +  (let [touch-components
   2.148 +        (map enable-touch
   2.149 +             (filter #(isa? (class %) Geometry)
   2.150 +                     (node-seq pieces)))]
   2.151 +    (fn [node]
   2.152 +      (reduce into [] (map #(% node) touch-components))))) 
   2.153      
   2.154 -    (vec (map sensor-coords tris))))
   2.155 -
   2.156 -(defn locate-tactile-sensors*
   2.157 -  "Search the geometry's tactile UV image for touch sensors, returning
   2.158 -  their positions in geometry-relative coordinates."
   2.159 -  [#^Geometry geo]
   2.160 -  (let [uv-image (touch-receptor-image geo)
   2.161 -        width (.getWidth uv-image)
   2.162 -        height (.getHeight uv-image)
   2.163 -
   2.164 -        mesh (.getMesh geo)
   2.165 -        mesh-tris (triangles geo)
   2.166 -
   2.167 -        ;; for each triangle
   2.168 -        sensor-coords
   2.169 -        (fn [tri]
   2.170 -          ;; translate triangle to uv-pixel-space
   2.171 -          (let [uv-tri
   2.172 -                (rasterize mesh tri width height)
   2.173 -                bounds (vec (triangle-bounds uv-tri))]
   2.174 -            
   2.175 -            ;; get that part of the picture
   2.176 -            
   2.177 -            (apply (partial (memfn setRoi) uv-image) bounds)
   2.178 -            (let [cutout (.crop (.getProcessor uv-image))
   2.179 -                  ;; extract white pixels inside triangle
   2.180 -                  cutout-tri
   2.181 -                  (map-triangle
   2.182 -                   (fn [_ v]
   2.183 -                     (.subtract
   2.184 -                      v
   2.185 -                      (Vector3f. (bounds 0) (bounds 1) (float 0))))
   2.186 -                   uv-tri)
   2.187 -                  whites (filter (partial inside-triangle? cutout-tri)
   2.188 -                                 (map vector2f->vector3f
   2.189 -                                      (white-coordinates cutout)))
   2.190 -                  ;; translate pixel coordinates to world-space
   2.191 -                  transform (triangle-transformation cutout-tri tri)]
   2.192 -              (map #(.mult transform %) whites))))]
   2.193 -
   2.194 -
   2.195 -      
   2.196 -    (for [mesh-tri mesh-tris]
   2.197 -     
   2.198 -      (let [uv-tri (rasterize mesh mesh-tri width height)
   2.199 -            bounding-box (vec (triangle-bounds uv-tri))]
   2.200 -        (apply (partial (memfn setRoi) uv-image) bounding-box)
   2.201 -
   2.202 -        
   2.203 -        
   2.204 -        
   2.205 -        ))   
   2.206 -    (vec (map sensor-coords mesh-tris))))
   2.207 -
   2.208 -
   2.209 -
   2.210 -(defn measure-touchies [#^Geometry geo]
   2.211 -  (let [tactile-sensor-coords (locate-tactile-sensors geo)
   2.212 -        tris (triangles geo)]
   2.213 -    (fn [world]
   2.214 -      (let [sensor-origins (vec
   2.215 -                         (map
   2.216 -                          #(map (partial local-to-world geo) %)
   2.217 -                          tactile-sensor-coords))
   2.218 -            triangle-normals (vec
   2.219 -                         (map (partial get-ray-direction geo)
   2.220 -                              tris))
   2.221 -            rays (flatten
   2.222 -                  (map
   2.223 -                   (fn [origins normals]
   2.224 -                     (map
   2.225 -                      #(Ray. %1 %2)
   2.226 -                      origins
   2.227 -                      normals))
   2.228 -                   sensor-origins
   2.229 -                   (map repeat triangle-normals)))
   2.230 -
   2.231 -            
   2.232 -            ]
   2.233 -        rays))))
   2.234 -                 
   2.235 -              
   2.236 -                   
   2.237 -            
   2.238 -                   
   2.239 -        
   2.240 -        
   2.241 -      
   2.242 -      
   2.243 -      
   2.244 -          
   2.245 -        
   2.246 -        
   2.247 - 
   2.248 -
   2.249 -
   2.250 -
   2.251 -
   2.252 -
   2.253 -;; for each triangle in the mesh,
   2.254 -;; get the normal to the triangle,
   2.255 -;; look at the UV touch map, restricted to that triangle,
   2.256 -;; get the positions of those touch sensors in geometry-relative
   2.257 -;; coordinates.
   2.258 -(defn tactile-coords [#^Geometry obj]
   2.259 -  (let [mesh (.getMesh obj)
   2.260 -        num-triangles (.getTriangleCount mesh)
   2.261 -        num-verticies (.getVertexCount mesh)
   2.262 -        uv-coord (partial uv-coord mesh)
   2.263 -        triangle-indices (partial triangle-indices mesh)
   2.264 -        receptors (touch-receptor-image obj)
   2.265 -        tris (triangles obj)
   2.266 -        ]
   2.267 -    (map
   2.268 -     (fn [[tri-1 tri-2 tri-3]]
   2.269 -       (let [width (.getWidth receptors)
   2.270 -             height (.getHeight receptors)
   2.271 -             uv-1 (uv-coord tri-1)
   2.272 -             uv-2 (uv-coord tri-2)
   2.273 -             uv-3 (uv-coord tri-3)
   2.274 -             x-coords (map #(.getX %) [uv-1 uv-2 uv-3])
   2.275 -             y-coords (map #(.getY %) [uv-1 uv-2 uv-3])
   2.276 -             max-x (Math/ceil (* width (apply max x-coords)))
   2.277 -             min-x (Math/floor (* width (apply min x-coords)))
   2.278 -             max-y (Math/ceil (* height (apply max y-coords)))
   2.279 -             min-y (Math/floor (* height (apply min y-coords)))
   2.280 -
   2.281 -             image-1 (Vector2f. (* width (.getX uv-1))
   2.282 -                                (* height (.getY uv-1)))
   2.283 -             image-2 (Vector2f. (* width (.getX uv-2))
   2.284 -                                (* height (.getY uv-2)))
   2.285 -             image-3 (Vector2f. (* width (.getX uv-3))
   2.286 -                                (* height (.getY uv-3)))
   2.287 -             left-corner
   2.288 -             (Vector2f. min-x min-y)
   2.289 -             ]
   2.290 -
   2.291 -         (.setRoi receptors min-x min-y (- max-x min-x) (- max-y min-y))
   2.292 -         (let [processor  (.crop (.getProcessor receptors))]
   2.293 -           (map
   2.294 -            #(.add left-corner %)
   2.295 -            
   2.296 -            (filter 
   2.297 -             (partial
   2.298 -              inside-triangle?
   2.299 -              (.subtract image-1 left-corner)
   2.300 -              (.subtract image-2 left-corner)
   2.301 -              (.subtract image-3 left-corner))
   2.302 -             (white-coordinates processor))))
   2.303 -         )) (map triangle-indices (range num-triangles)))))
   2.304 -
   2.305 -
   2.306 -
   2.307 +  
   2.308  
   2.309  
   2.310  
   2.311 @@ -874,6 +761,101 @@
   2.312                                (Vector3f. 1 0 0))))))))
   2.313  
   2.314  
   2.315 +(defn locate-feelers*
   2.316 +  "Search the geometry's tactile UV image for touch sensors, returning
   2.317 +  their positions in geometry-relative coordinates."
   2.318 +  [#^Geometry geo]
   2.319 +  (let [uv-image (touch-receptor-image geo)
   2.320 +        width (.getWidth uv-image)
   2.321 +        height (.getHeight uv-image)
   2.322 +
   2.323 +        mesh (.getMesh geo)
   2.324 +        mesh-tris (triangles geo)
   2.325 +
   2.326 +        ;; for each triangle
   2.327 +        sensor-coords
   2.328 +        (fn [tri]
   2.329 +          ;; translate triangle to uv-pixel-space
   2.330 +          (let [uv-tri
   2.331 +                (rasterize mesh tri width height)
   2.332 +                bounds (vec (triangle-bounds uv-tri))]
   2.333 +            
   2.334 +            ;; get that part of the picture
   2.335 +            
   2.336 +            (apply (partial (memfn setRoi) uv-image) bounds)
   2.337 +            (let [cutout (.crop (.getProcessor uv-image))
   2.338 +                  ;; extract white pixels inside triangle
   2.339 +                  cutout-tri
   2.340 +                  (map-triangle
   2.341 +                   (fn [_ v]
   2.342 +                     (.subtract
   2.343 +                      v
   2.344 +                      (Vector3f. (bounds 0) (bounds 1) (float 0))))
   2.345 +                   uv-tri)
   2.346 +                  whites (filter (partial inside-triangle? cutout-tri)
   2.347 +                                 (map vector2f->vector3f
   2.348 +                                      (white-coordinates cutout)))
   2.349 +                  ;; translate pixel coordinates to world-space
   2.350 +                  transform (triangle-transformation cutout-tri tri)]
   2.351 +              (map #(.mult transform %) whites))))]
   2.352 +
   2.353 +
   2.354 +      
   2.355 +    (for [mesh-tri mesh-tris]
   2.356 +     
   2.357 +      (let [uv-tri (rasterize mesh mesh-tri width height)
   2.358 +            bounding-box (vec (triangle-bounds uv-tri))]
   2.359 +        (apply (partial (memfn setRoi) uv-image) bounding-box)
   2.360 +        ))   
   2.361 +    (vec (map sensor-coords mesh-tris))))
   2.362 +
   2.363 +
   2.364 +(defn tactile-coords [#^Geometry obj]
   2.365 +  (let [mesh (.getMesh obj)
   2.366 +        num-triangles (.getTriangleCount mesh)
   2.367 +        num-verticies (.getVertexCount mesh)
   2.368 +        uv-coord (partial uv-coord mesh)
   2.369 +        triangle-indices (partial triangle-indices mesh)
   2.370 +        receptors (touch-receptor-image obj)
   2.371 +        tris (triangles obj)
   2.372 +        ]
   2.373 +    (map
   2.374 +     (fn [[tri-1 tri-2 tri-3]]
   2.375 +       (let [width (.getWidth receptors)
   2.376 +             height (.getHeight receptors)
   2.377 +             uv-1 (uv-coord tri-1)
   2.378 +             uv-2 (uv-coord tri-2)
   2.379 +             uv-3 (uv-coord tri-3)
   2.380 +             x-coords (map #(.getX %) [uv-1 uv-2 uv-3])
   2.381 +             y-coords (map #(.getY %) [uv-1 uv-2 uv-3])
   2.382 +             max-x (Math/ceil (* width (apply max x-coords)))
   2.383 +             min-x (Math/floor (* width (apply min x-coords)))
   2.384 +             max-y (Math/ceil (* height (apply max y-coords)))
   2.385 +             min-y (Math/floor (* height (apply min y-coords)))
   2.386 +
   2.387 +             image-1 (Vector2f. (* width (.getX uv-1))
   2.388 +                                (* height (.getY uv-1)))
   2.389 +             image-2 (Vector2f. (* width (.getX uv-2))
   2.390 +                                (* height (.getY uv-2)))
   2.391 +             image-3 (Vector2f. (* width (.getX uv-3))
   2.392 +                                (* height (.getY uv-3)))
   2.393 +             left-corner
   2.394 +             (Vector2f. min-x min-y)
   2.395 +             ]
   2.396 +
   2.397 +         (.setRoi receptors min-x min-y (- max-x min-x) (- max-y min-y))
   2.398 +         (let [processor  (.crop (.getProcessor receptors))]
   2.399 +           (map
   2.400 +            #(.add left-corner %)
   2.401 +            
   2.402 +            (filter 
   2.403 +             (partial
   2.404 +              inside-triangle?
   2.405 +              (.subtract image-1 left-corner)
   2.406 +              (.subtract image-2 left-corner)
   2.407 +              (.subtract image-3 left-corner))
   2.408 +             (white-coordinates processor))))
   2.409 +         )) (map triangle-indices (range num-triangles)))))
   2.410  
   2.411  #+end_src
   2.412