diff org/test-creature.org @ 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
line wrap: on
line diff
     1.1 --- a/org/test-creature.org	Tue Jan 10 21:26:41 2012 -0700
     1.2 +++ b/org/test-creature.org	Wed Jan 11 00:06:33 2012 -0700
     1.3 @@ -350,19 +350,22 @@
     1.4         (triangle-indices mesh (.getIndex triangle))))
     1.5  
     1.6  (defn touch-receptor-image
     1.7 -  "Return the touch-sensor distribution image in ImagePlus format."
     1.8 +  "Return the touch-sensor distribution image in ImagePlus format, or
     1.9 +   nil if it does not exist."
    1.10    [#^Geometry obj]
    1.11 -  (let
    1.12 -      [mat (.getMaterial obj)
    1.13 -       texture
    1.14 -       (.getTextureValue
    1.15 -        (.getTextureParam
    1.16 -         mat
    1.17 -         MaterialHelper/TEXTURE_TYPE_DIFFUSE))
    1.18 -       im (.getImage texture)]
    1.19 -       (ImagePlus.
    1.20 -        "UV-map"
    1.21 -        (ImageToAwt/convert im false false 0))))
    1.22 +  (let [mat (.getMaterial obj)]
    1.23 +    (if-let [texture-param
    1.24 +             (.getTextureParam
    1.25 +              mat
    1.26 +              MaterialHelper/TEXTURE_TYPE_DIFFUSE)]
    1.27 +      (let
    1.28 +          [texture
    1.29 +           (.getTextureValue texture-param)
    1.30 +           im (.getImage texture)]
    1.31 +        (ImagePlus.
    1.32 +         "UV-map"
    1.33 +         (ImageToAwt/convert im false false 0))))))
    1.34 +      
    1.35  
    1.36  
    1.37  (import ij.process.ImageProcessor)
    1.38 @@ -533,200 +536,84 @@
    1.39       ]))
    1.40    
    1.41  
    1.42 -(defn locate-tactile-sensors
    1.43 +(defn locate-feelers
    1.44    "Search the geometry's tactile UV image for touch sensors, returning
    1.45    their positions in geometry-relative coordinates."
    1.46    [#^Geometry geo]
    1.47 -  (let [mesh (.getMesh geo)
    1.48 +  (if-let [image (touch-receptor-image geo)]
    1.49 +    (let [mesh (.getMesh geo)
    1.50 +          tris (triangles geo)
    1.51 +          
    1.52 +          
    1.53 +          width (.getWidth image)
    1.54 +          height (.getHeight image)
    1.55 +          
    1.56 +          ;; for each triangle
    1.57 +          sensor-coords
    1.58 +          (fn [tri]
    1.59 +            ;; translate triangle to uv-pixel-space
    1.60 +            (let [uv-tri
    1.61 +                  (pixel-triangle mesh tri width height)
    1.62 +                  bounds (vec (triangle-bounds uv-tri))]
    1.63 +              
    1.64 +              ;; get that part of the picture
    1.65 +              
    1.66 +              (apply #(.setRoi image %1 %2 %3 %4) bounds)
    1.67 +              (let [cutout (.crop (.getProcessor image))
    1.68 +                    ;; extract white pixels inside triangle
    1.69 +                    cutout-tri
    1.70 +                    (map-triangle
    1.71 +                     (fn [_ v]
    1.72 +                       (.subtract
    1.73 +                        v
    1.74 +                        (Vector3f. (bounds 0) (bounds 1) (float 0))))
    1.75 +                     uv-tri)
    1.76 +                    whites (filter (partial inside-triangle? cutout-tri)
    1.77 +                                   (map vector2f->vector3f
    1.78 +                                        (white-coordinates cutout)))
    1.79 +                    ;; translate pixel coordinates to world-space
    1.80 +                    transform (triangle-transformation cutout-tri tri)]
    1.81 +                (map #(.mult transform %) whites))))]
    1.82 +      (vec (map sensor-coords tris)))
    1.83 +    (repeat (count (triangles geo)) [])))
    1.84 +  
    1.85 +(defn enable-touch [#^Geometry geo]
    1.86 +  (let [feeler-coords (locate-feelers geo)
    1.87          tris (triangles geo)
    1.88 -        
    1.89 -        image (touch-receptor-image geo)
    1.90 -        width (.getWidth image)
    1.91 -        height (.getHeight image)
    1.92 -        
    1.93 +        limit 0.1]
    1.94 +    (fn [node]
    1.95 +      (let [sensor-origins 
    1.96 +            (map
    1.97 +             #(map (partial local-to-world geo) %)
    1.98 +             feeler-coords)
    1.99 +            triangle-normals 
   1.100 +            (map (partial get-ray-direction geo)
   1.101 +                 tris)
   1.102 +            rays
   1.103 +             (flatten
   1.104 +              (map (fn [origins norm]
   1.105 +                     (map #(doto (Ray. % norm)
   1.106 +                              (.setLimit limit)) origins))
   1.107 +                   sensor-origins triangle-normals))]
   1.108 +        (for [ray rays]
   1.109 +          (do
   1.110 +            (let [results (CollisionResults.)]
   1.111 +              (.collideWith node ray results)
   1.112 +              (let [touch-objects
   1.113 +                    (set
   1.114 +                     (filter #(not (= geo %))
   1.115 +                             (map #(.getGeometry %) results)))]
   1.116 +                (count touch-objects)))))))))
   1.117  
   1.118 -        ;; for each triangle
   1.119 -        sensor-coords
   1.120 -        (fn [tri]
   1.121 -          ;; translate triangle to uv-pixel-space
   1.122 -          (let [uv-tri
   1.123 -                (pixel-triangle mesh tri width height)
   1.124 -                bounds (vec (triangle-bounds uv-tri))]
   1.125 -            
   1.126 -            ;; get that part of the picture
   1.127 -            
   1.128 -            (apply #(.setRoi image %1 %2 %3 %4) bounds)
   1.129 -            (let [cutout (.crop (.getProcessor image))
   1.130 -                  ;; extract white pixels inside triangle
   1.131 -                  cutout-tri
   1.132 -                  (map-triangle
   1.133 -                   (fn [_ v]
   1.134 -                     (.subtract
   1.135 -                      v
   1.136 -                      (Vector3f. (bounds 0) (bounds 1) (float 0))))
   1.137 -                   uv-tri)
   1.138 -                  whites (filter (partial inside-triangle? cutout-tri)
   1.139 -                                 (map vector2f->vector3f
   1.140 -                                      (white-coordinates cutout)))
   1.141 -                  ;; translate pixel coordinates to world-space
   1.142 -                  transform (triangle-transformation cutout-tri tri)]
   1.143 -              (map #(.mult transform %) whites))))]
   1.144 -
   1.145 -
   1.146 +(defn touch [#^Node pieces]
   1.147 +  (let [touch-components
   1.148 +        (map enable-touch
   1.149 +             (filter #(isa? (class %) Geometry)
   1.150 +                     (node-seq pieces)))]
   1.151 +    (fn [node]
   1.152 +      (reduce into [] (map #(% node) touch-components))))) 
   1.153      
   1.154 -    (vec (map sensor-coords tris))))
   1.155 -
   1.156 -(defn locate-tactile-sensors*
   1.157 -  "Search the geometry's tactile UV image for touch sensors, returning
   1.158 -  their positions in geometry-relative coordinates."
   1.159 -  [#^Geometry geo]
   1.160 -  (let [uv-image (touch-receptor-image geo)
   1.161 -        width (.getWidth uv-image)
   1.162 -        height (.getHeight uv-image)
   1.163 -
   1.164 -        mesh (.getMesh geo)
   1.165 -        mesh-tris (triangles geo)
   1.166 -
   1.167 -        ;; for each triangle
   1.168 -        sensor-coords
   1.169 -        (fn [tri]
   1.170 -          ;; translate triangle to uv-pixel-space
   1.171 -          (let [uv-tri
   1.172 -                (rasterize mesh tri width height)
   1.173 -                bounds (vec (triangle-bounds uv-tri))]
   1.174 -            
   1.175 -            ;; get that part of the picture
   1.176 -            
   1.177 -            (apply (partial (memfn setRoi) uv-image) bounds)
   1.178 -            (let [cutout (.crop (.getProcessor uv-image))
   1.179 -                  ;; extract white pixels inside triangle
   1.180 -                  cutout-tri
   1.181 -                  (map-triangle
   1.182 -                   (fn [_ v]
   1.183 -                     (.subtract
   1.184 -                      v
   1.185 -                      (Vector3f. (bounds 0) (bounds 1) (float 0))))
   1.186 -                   uv-tri)
   1.187 -                  whites (filter (partial inside-triangle? cutout-tri)
   1.188 -                                 (map vector2f->vector3f
   1.189 -                                      (white-coordinates cutout)))
   1.190 -                  ;; translate pixel coordinates to world-space
   1.191 -                  transform (triangle-transformation cutout-tri tri)]
   1.192 -              (map #(.mult transform %) whites))))]
   1.193 -
   1.194 -
   1.195 -      
   1.196 -    (for [mesh-tri mesh-tris]
   1.197 -     
   1.198 -      (let [uv-tri (rasterize mesh mesh-tri width height)
   1.199 -            bounding-box (vec (triangle-bounds uv-tri))]
   1.200 -        (apply (partial (memfn setRoi) uv-image) bounding-box)
   1.201 -
   1.202 -        
   1.203 -        
   1.204 -        
   1.205 -        ))   
   1.206 -    (vec (map sensor-coords mesh-tris))))
   1.207 -
   1.208 -
   1.209 -
   1.210 -(defn measure-touchies [#^Geometry geo]
   1.211 -  (let [tactile-sensor-coords (locate-tactile-sensors geo)
   1.212 -        tris (triangles geo)]
   1.213 -    (fn [world]
   1.214 -      (let [sensor-origins (vec
   1.215 -                         (map
   1.216 -                          #(map (partial local-to-world geo) %)
   1.217 -                          tactile-sensor-coords))
   1.218 -            triangle-normals (vec
   1.219 -                         (map (partial get-ray-direction geo)
   1.220 -                              tris))
   1.221 -            rays (flatten
   1.222 -                  (map
   1.223 -                   (fn [origins normals]
   1.224 -                     (map
   1.225 -                      #(Ray. %1 %2)
   1.226 -                      origins
   1.227 -                      normals))
   1.228 -                   sensor-origins
   1.229 -                   (map repeat triangle-normals)))
   1.230 -
   1.231 -            
   1.232 -            ]
   1.233 -        rays))))
   1.234 -                 
   1.235 -              
   1.236 -                   
   1.237 -            
   1.238 -                   
   1.239 -        
   1.240 -        
   1.241 -      
   1.242 -      
   1.243 -      
   1.244 -          
   1.245 -        
   1.246 -        
   1.247 - 
   1.248 -
   1.249 -
   1.250 -
   1.251 -
   1.252 -
   1.253 -;; for each triangle in the mesh,
   1.254 -;; get the normal to the triangle,
   1.255 -;; look at the UV touch map, restricted to that triangle,
   1.256 -;; get the positions of those touch sensors in geometry-relative
   1.257 -;; coordinates.
   1.258 -(defn tactile-coords [#^Geometry obj]
   1.259 -  (let [mesh (.getMesh obj)
   1.260 -        num-triangles (.getTriangleCount mesh)
   1.261 -        num-verticies (.getVertexCount mesh)
   1.262 -        uv-coord (partial uv-coord mesh)
   1.263 -        triangle-indices (partial triangle-indices mesh)
   1.264 -        receptors (touch-receptor-image obj)
   1.265 -        tris (triangles obj)
   1.266 -        ]
   1.267 -    (map
   1.268 -     (fn [[tri-1 tri-2 tri-3]]
   1.269 -       (let [width (.getWidth receptors)
   1.270 -             height (.getHeight receptors)
   1.271 -             uv-1 (uv-coord tri-1)
   1.272 -             uv-2 (uv-coord tri-2)
   1.273 -             uv-3 (uv-coord tri-3)
   1.274 -             x-coords (map #(.getX %) [uv-1 uv-2 uv-3])
   1.275 -             y-coords (map #(.getY %) [uv-1 uv-2 uv-3])
   1.276 -             max-x (Math/ceil (* width (apply max x-coords)))
   1.277 -             min-x (Math/floor (* width (apply min x-coords)))
   1.278 -             max-y (Math/ceil (* height (apply max y-coords)))
   1.279 -             min-y (Math/floor (* height (apply min y-coords)))
   1.280 -
   1.281 -             image-1 (Vector2f. (* width (.getX uv-1))
   1.282 -                                (* height (.getY uv-1)))
   1.283 -             image-2 (Vector2f. (* width (.getX uv-2))
   1.284 -                                (* height (.getY uv-2)))
   1.285 -             image-3 (Vector2f. (* width (.getX uv-3))
   1.286 -                                (* height (.getY uv-3)))
   1.287 -             left-corner
   1.288 -             (Vector2f. min-x min-y)
   1.289 -             ]
   1.290 -
   1.291 -         (.setRoi receptors min-x min-y (- max-x min-x) (- max-y min-y))
   1.292 -         (let [processor  (.crop (.getProcessor receptors))]
   1.293 -           (map
   1.294 -            #(.add left-corner %)
   1.295 -            
   1.296 -            (filter 
   1.297 -             (partial
   1.298 -              inside-triangle?
   1.299 -              (.subtract image-1 left-corner)
   1.300 -              (.subtract image-2 left-corner)
   1.301 -              (.subtract image-3 left-corner))
   1.302 -             (white-coordinates processor))))
   1.303 -         )) (map triangle-indices (range num-triangles)))))
   1.304 -
   1.305 -
   1.306 -
   1.307 +  
   1.308  
   1.309  
   1.310  
   1.311 @@ -874,6 +761,101 @@
   1.312                                (Vector3f. 1 0 0))))))))
   1.313  
   1.314  
   1.315 +(defn locate-feelers*
   1.316 +  "Search the geometry's tactile UV image for touch sensors, returning
   1.317 +  their positions in geometry-relative coordinates."
   1.318 +  [#^Geometry geo]
   1.319 +  (let [uv-image (touch-receptor-image geo)
   1.320 +        width (.getWidth uv-image)
   1.321 +        height (.getHeight uv-image)
   1.322 +
   1.323 +        mesh (.getMesh geo)
   1.324 +        mesh-tris (triangles geo)
   1.325 +
   1.326 +        ;; for each triangle
   1.327 +        sensor-coords
   1.328 +        (fn [tri]
   1.329 +          ;; translate triangle to uv-pixel-space
   1.330 +          (let [uv-tri
   1.331 +                (rasterize mesh tri width height)
   1.332 +                bounds (vec (triangle-bounds uv-tri))]
   1.333 +            
   1.334 +            ;; get that part of the picture
   1.335 +            
   1.336 +            (apply (partial (memfn setRoi) uv-image) bounds)
   1.337 +            (let [cutout (.crop (.getProcessor uv-image))
   1.338 +                  ;; extract white pixels inside triangle
   1.339 +                  cutout-tri
   1.340 +                  (map-triangle
   1.341 +                   (fn [_ v]
   1.342 +                     (.subtract
   1.343 +                      v
   1.344 +                      (Vector3f. (bounds 0) (bounds 1) (float 0))))
   1.345 +                   uv-tri)
   1.346 +                  whites (filter (partial inside-triangle? cutout-tri)
   1.347 +                                 (map vector2f->vector3f
   1.348 +                                      (white-coordinates cutout)))
   1.349 +                  ;; translate pixel coordinates to world-space
   1.350 +                  transform (triangle-transformation cutout-tri tri)]
   1.351 +              (map #(.mult transform %) whites))))]
   1.352 +
   1.353 +
   1.354 +      
   1.355 +    (for [mesh-tri mesh-tris]
   1.356 +     
   1.357 +      (let [uv-tri (rasterize mesh mesh-tri width height)
   1.358 +            bounding-box (vec (triangle-bounds uv-tri))]
   1.359 +        (apply (partial (memfn setRoi) uv-image) bounding-box)
   1.360 +        ))   
   1.361 +    (vec (map sensor-coords mesh-tris))))
   1.362 +
   1.363 +
   1.364 +(defn tactile-coords [#^Geometry obj]
   1.365 +  (let [mesh (.getMesh obj)
   1.366 +        num-triangles (.getTriangleCount mesh)
   1.367 +        num-verticies (.getVertexCount mesh)
   1.368 +        uv-coord (partial uv-coord mesh)
   1.369 +        triangle-indices (partial triangle-indices mesh)
   1.370 +        receptors (touch-receptor-image obj)
   1.371 +        tris (triangles obj)
   1.372 +        ]
   1.373 +    (map
   1.374 +     (fn [[tri-1 tri-2 tri-3]]
   1.375 +       (let [width (.getWidth receptors)
   1.376 +             height (.getHeight receptors)
   1.377 +             uv-1 (uv-coord tri-1)
   1.378 +             uv-2 (uv-coord tri-2)
   1.379 +             uv-3 (uv-coord tri-3)
   1.380 +             x-coords (map #(.getX %) [uv-1 uv-2 uv-3])
   1.381 +             y-coords (map #(.getY %) [uv-1 uv-2 uv-3])
   1.382 +             max-x (Math/ceil (* width (apply max x-coords)))
   1.383 +             min-x (Math/floor (* width (apply min x-coords)))
   1.384 +             max-y (Math/ceil (* height (apply max y-coords)))
   1.385 +             min-y (Math/floor (* height (apply min y-coords)))
   1.386 +
   1.387 +             image-1 (Vector2f. (* width (.getX uv-1))
   1.388 +                                (* height (.getY uv-1)))
   1.389 +             image-2 (Vector2f. (* width (.getX uv-2))
   1.390 +                                (* height (.getY uv-2)))
   1.391 +             image-3 (Vector2f. (* width (.getX uv-3))
   1.392 +                                (* height (.getY uv-3)))
   1.393 +             left-corner
   1.394 +             (Vector2f. min-x min-y)
   1.395 +             ]
   1.396 +
   1.397 +         (.setRoi receptors min-x min-y (- max-x min-x) (- max-y min-y))
   1.398 +         (let [processor  (.crop (.getProcessor receptors))]
   1.399 +           (map
   1.400 +            #(.add left-corner %)
   1.401 +            
   1.402 +            (filter 
   1.403 +             (partial
   1.404 +              inside-triangle?
   1.405 +              (.subtract image-1 left-corner)
   1.406 +              (.subtract image-2 left-corner)
   1.407 +              (.subtract image-3 left-corner))
   1.408 +             (white-coordinates processor))))
   1.409 +         )) (map triangle-indices (range num-triangles)))))
   1.410  
   1.411  #+end_src
   1.412