changeset 108:92b857b6145d

slow implementation of UV-mapped touch is complete
author Robert McIntyre <rlm@mit.edu>
date Sun, 15 Jan 2012 04:08:31 -0700
parents 53fb379ac678
children c05d8d222166
files assets/Models/creature1/tip.png assets/Models/creature1/try-again.blend org/test-creature.org org/util.org
diffstat 4 files changed, 168 insertions(+), 200 deletions(-) [+]
line wrap: on
line diff
     1.1 Binary file assets/Models/creature1/tip.png has changed
     2.1 Binary file assets/Models/creature1/try-again.blend has changed
     3.1 --- a/org/test-creature.org	Sun Jan 15 00:40:49 2012 -0700
     3.2 +++ b/org/test-creature.org	Sun Jan 15 04:08:31 2012 -0700
     3.3 @@ -65,6 +65,7 @@
     3.4  (import java.awt.Dimension)
     3.5  (import com.aurellem.capture.RatchetTimer)
     3.6  (declare joint-create)
     3.7 +(use 'clojure.contrib.def)
     3.8  
     3.9  (defn view-image
    3.10    "Initailizes a JPanel on which you may draw a BufferedImage.
    3.11 @@ -142,40 +143,41 @@
    3.12    "Take a set of pairs of integers and collapse them into a
    3.13     contigous bitmap."
    3.14    [points]
    3.15 -  (let
    3.16 -      [num-points (count points)
    3.17 -       center (vector
    3.18 -               (int (average (map first points)))
    3.19 -               (int (average (map first points))))
    3.20 -       flattened
    3.21 -       (reduce
    3.22 -        concat 
    3.23 -        (map
    3.24 -         (fn [column]
    3.25 -           (map vector
    3.26 -                (map first column)
    3.27 -                (collapse-1d (second center)
    3.28 -                             (map second column))))
    3.29 -         (partition-by first (sort-by first points))))
    3.30 -       squeezed
    3.31 -       (reduce
    3.32 -        concat 
    3.33 -        (map
    3.34 -         (fn [row]
    3.35 -           (map vector
    3.36 -                (collapse-1d (first center)
    3.37 -                             (map first row))
    3.38 -                (map second row)))
    3.39 -         (partition-by second (sort-by second flattened))))
    3.40 -       relocate
    3.41 -       (let [min-x (apply min (map first squeezed))
    3.42 -             min-y (apply min (map second squeezed))]
    3.43 -         (map (fn [[x y]]
    3.44 -                [(- x min-x)
    3.45 -                 (- y min-y)])
    3.46 -              squeezed))]
    3.47 -    relocate
    3.48 -   ))
    3.49 +  (if (empty? points) []
    3.50 +      (let
    3.51 +          [num-points (count points)
    3.52 +           center (vector
    3.53 +                   (int (average (map first points)))
    3.54 +                   (int (average (map first points))))
    3.55 +           flattened
    3.56 +           (reduce
    3.57 +            concat 
    3.58 +            (map
    3.59 +             (fn [column]
    3.60 +               (map vector
    3.61 +                    (map first column)
    3.62 +                    (collapse-1d (second center)
    3.63 +                                 (map second column))))
    3.64 +             (partition-by first (sort-by first points))))
    3.65 +           squeezed
    3.66 +           (reduce
    3.67 +            concat 
    3.68 +            (map
    3.69 +             (fn [row]
    3.70 +               (map vector
    3.71 +                    (collapse-1d (first center)
    3.72 +                                 (map first row))
    3.73 +                    (map second row)))
    3.74 +             (partition-by second (sort-by second flattened))))
    3.75 +           relocate
    3.76 +           (let [min-x (apply min (map first squeezed))
    3.77 +                 min-y (apply min (map second squeezed))]
    3.78 +             (map (fn [[x y]]
    3.79 +                    [(- x min-x)
    3.80 +                     (- y min-y)])
    3.81 +                  squeezed))]
    3.82 +        relocate
    3.83 +        )))
    3.84  
    3.85  (defn load-bullet []
    3.86    (let [sim (world (Node.) {} no-op no-op)]
    3.87 @@ -417,33 +419,10 @@
    3.88  
    3.89  (import ij.ImagePlus)
    3.90  
    3.91 -(defn triangle-indices
    3.92 -  "Get the triangle vertex indices of a given triangle from a given
    3.93 -   mesh."
    3.94 -  [#^Mesh mesh triangle-index]
    3.95 -  (let [indices (int-array 3)]
    3.96 -    (.getTriangle mesh triangle-index indices)
    3.97 -    (vec indices)))
    3.98 +;; Every Mesh has many triangles, each with its own index.
    3.99 +;; Every vertex has its own index as well.
   3.100  
   3.101 -(defn uv-coord
   3.102 -  "Get the uv-coordinates of the vertex named by vertex-index"
   3.103 -  [#^Mesh mesh vertex-index]
   3.104 -  (let [UV-buffer
   3.105 -        (.getData
   3.106 -         (.getBuffer
   3.107 -          mesh
   3.108 -          VertexBuffer$Type/TexCoord))]
   3.109 -    (Vector2f.
   3.110 -     (.get UV-buffer (* vertex-index 2))
   3.111 -     (.get UV-buffer (+ 1 (* vertex-index 2))))))
   3.112 -
   3.113 -(defn tri-uv-coord
   3.114 -  "Get the uv-cooridnates of the triangle's verticies."
   3.115 -  [#^Mesh mesh #^Triangle triangle]
   3.116 -  (map (partial uv-coord mesh)
   3.117 -       (triangle-indices mesh (.getIndex triangle))))
   3.118 -
   3.119 -(defn touch-receptor-image
   3.120 +(defn tactile-sensor-image
   3.121    "Return the touch-sensor distribution image in ImagePlus format, or
   3.122     nil if it does not exist."
   3.123    [#^Geometry obj]
   3.124 @@ -456,9 +435,7 @@
   3.125            [texture
   3.126             (.getTextureValue texture-param)
   3.127             im (.getImage texture)]
   3.128 -        (ImagePlus.
   3.129 -         "UV-map"
   3.130 -         (ImageToAwt/convert im false false 0))))))
   3.131 +        (ImageToAwt/convert im false false 0)))))
   3.132  
   3.133  (import ij.process.ImageProcessor)
   3.134  (import java.awt.image.BufferedImage)
   3.135 @@ -466,25 +443,58 @@
   3.136  (def white -1)
   3.137    
   3.138  (defn filter-pixels
   3.139 -  "List the coordinates of all pixels matching pred."
   3.140 +  "List the coordinates of all pixels matching pred, within the bounds
   3.141 +   provided. Bounds -> [x0 y0 width height]"
   3.142    {:author "Dylan Holmes"}
   3.143 -  [pred #^ImageProcessor ip]
   3.144 -  (let
   3.145 -      [width (.getWidth ip)
   3.146 -       height (.getHeight ip)]
   3.147 -    ((fn accumulate [x y matches]
   3.148 -       (cond
   3.149 -        (>= y height) matches
   3.150 -        (>= x width) (recur 0 (inc y) matches)
   3.151 -        (pred (.getPixel ip x y))
   3.152 -        (recur (inc x) y (conj matches (Vector2f. x y)))
   3.153 -        :else (recur (inc x) y matches)))
   3.154 -     0 0 [])))
   3.155 +  ([pred #^BufferedImage image]
   3.156 +     (filter-pixels pred image [0 0 (.getWidth image) (.getHeight image)]))
   3.157 +  ([pred #^BufferedImage image [x0 y0 width height]]
   3.158 +     ((fn accumulate [x y matches]
   3.159 +        (cond
   3.160 +         (>= y (+ height y0)) matches
   3.161 +         (>= x (+ width x0)) (recur 0 (inc y) matches)
   3.162 +         (pred (.getRGB image x y))
   3.163 +         (recur (inc x) y (conj matches [x y]))
   3.164 +         :else (recur (inc x) y matches)))
   3.165 +      x0 y0 [])))
   3.166  
   3.167  (defn white-coordinates
   3.168 -  "List the coordinates of all the white pixels in an image."
   3.169 -  [#^ImageProcessor ip]
   3.170 -  (filter-pixels #(= % white) ip))
   3.171 +  "Coordinates of all the white pixels in a subset of the image."
   3.172 +  [#^BufferedImage image bounds]
   3.173 +  (filter-pixels #(= % white) image bounds))
   3.174 +
   3.175 +(defn triangle
   3.176 +  "Get the triangle specified by triangle-index from the mesh"
   3.177 +  [#^Mesh mesh triangle-index]
   3.178 +  (let [scratch (Triangle.)]
   3.179 +    (.getTriangle mesh triangle-index scratch)
   3.180 +    scratch))
   3.181 +
   3.182 +(defn triangle-vertex-indices
   3.183 +  "Get the triangle vertex indices of a given triangle from a given
   3.184 +   mesh."
   3.185 +  [#^Mesh mesh triangle-index]
   3.186 +  (let [indices (int-array 3)]
   3.187 +    (.getTriangle mesh triangle-index indices)
   3.188 +    (vec indices)))
   3.189 +
   3.190 +(defn vertex-UV-coord
   3.191 +  "Get the uv-coordinates of the vertex named by vertex-index"
   3.192 +  [#^Mesh mesh vertex-index]
   3.193 +  (let [UV-buffer
   3.194 +        (.getData
   3.195 +         (.getBuffer
   3.196 +          mesh
   3.197 +          VertexBuffer$Type/TexCoord))]
   3.198 +    [(.get UV-buffer (* vertex-index 2))
   3.199 +     (.get UV-buffer (+ 1 (* vertex-index 2)))]))
   3.200 +
   3.201 +(defn triangle-UV-coord
   3.202 +  "Get the uv-cooridnates of the triangle's verticies."
   3.203 +  [#^Mesh mesh width height triangle-index]
   3.204 +  (map (fn [[u v]] (vector (* width u) (* height v)))
   3.205 +       (map (partial vertex-UV-coord mesh)
   3.206 +            (triangle-vertex-indices mesh triangle-index))))
   3.207    
   3.208  (defn same-side?
   3.209    "Given the points p1 and p2 and the reference point ref, is point p
   3.210 @@ -496,11 +506,26 @@
   3.211      (.cross (.subtract p2 p1) (.subtract p p1))
   3.212      (.cross (.subtract p2 p1) (.subtract ref p1)))))
   3.213  
   3.214 +(defn triangle-seq [#^Triangle tri]
   3.215 +  [(.get1 tri) (.get2 tri) (.get3 tri)])
   3.216 +
   3.217 +(defn vector3f-seq [#^Vector3f v]
   3.218 +  [(.getX v) (.getY v) (.getZ v)])
   3.219 +
   3.220 +(defn inside-triangle?
   3.221 +  "Is the point inside the triangle?"
   3.222 +  {:author "Dylan Holmes"}
   3.223 +  [#^Triangle tri #^Vector3f p]
   3.224 +  (let [[vert-1 vert-2 vert-3] (triangle-seq tri)]
   3.225 +    (and
   3.226 +     (same-side? vert-1 vert-2 vert-3 p)
   3.227 +     (same-side? vert-2 vert-3 vert-1 p)
   3.228 +     (same-side? vert-3 vert-1 vert-2 p))))
   3.229 +
   3.230  (defn triangle->matrix4f
   3.231 -  "Converts the triangle into a 4x4 matrix of vertices: The first
   3.232 -   three columns contain the vertices of the triangle; the last
   3.233 -   contains the unit normal of the triangle. The bottom row is filled
   3.234 -   with 1s."
   3.235 +  "Converts the triangle into a 4x4 matrix: The first three columns
   3.236 +   contain the vertices of the triangle; the last contains the unit
   3.237 +   normal of the triangle. The bottom row is filled with 1s."
   3.238    [#^Triangle t]
   3.239    (let [mat (Matrix4f.)
   3.240          [vert-1 vert-2 vert-3]
   3.241 @@ -523,150 +548,85 @@
   3.242     (triangle->matrix4f tri-2)
   3.243     (.invert (triangle->matrix4f tri-1))))
   3.244  
   3.245 -(def death (Triangle. 
   3.246 -            (Vector3f. 1 1 1)
   3.247 -            (Vector3f. 1 2 3)
   3.248 -            (Vector3f. 5 6 7)))
   3.249 -
   3.250 -(def death-2 (Triangle. 
   3.251 -             (Vector3f. 2 2 2)
   3.252 -             (Vector3f. 1 1 1)
   3.253 -             (Vector3f. 0 1 0)))
   3.254 +(defn point->vector2f [[u v]]
   3.255 +  (Vector2f. u v))
   3.256  
   3.257  (defn vector2f->vector3f [v]
   3.258    (Vector3f. (.getX v) (.getY v) 0))
   3.259  
   3.260 -(extend-type Triangle
   3.261 -  Textual
   3.262 -  (text [t]
   3.263 -    (println "Triangle: " \newline (.get1 t) \newline
   3.264 -             (.get2 t) \newline (.get3 t))))
   3.265 -
   3.266  (defn map-triangle [f #^Triangle tri]
   3.267    (Triangle.
   3.268     (f 0 (.get1 tri))
   3.269     (f 1 (.get2 tri))
   3.270     (f 2 (.get3 tri))))
   3.271  
   3.272 -(defn triangle-seq [#^Triangle tri]
   3.273 -  [(.get1 tri) (.get2 tri) (.get3 tri)])
   3.274 +(defn points->triangle
   3.275 +  "Convert a list of points into a triangle."
   3.276 +  [points]
   3.277 +  (apply #(Triangle. %1 %2 %3)
   3.278 +         (map (fn [point]
   3.279 +                (let [point (vec point)]
   3.280 +                  (Vector3f. (get point 0 0)
   3.281 +                             (get point 1 0)
   3.282 +                             (get point 2 0))))
   3.283 +              (take 3 points))))
   3.284  
   3.285 -(defn vector3f-seq [#^Vector3f v]
   3.286 -  [(.getX v) (.getY v) (.getZ v)])
   3.287 -
   3.288 -(defn inside-triangle?
   3.289 -  "Is the point inside the triangle? Now what do we do?
   3.290 -   You might want to hold on there"
   3.291 -  {:author "Dylan Holmes"}
   3.292 -  [tri p]
   3.293 -  (let [[vert-1 vert-2 vert-3] (triangle-seq tri)]
   3.294 -    (and
   3.295 -     (same-side? vert-1 vert-2 vert-3 p)
   3.296 -     (same-side? vert-2 vert-3 vert-1 p)
   3.297 -     (same-side? vert-3 vert-1 vert-2 p))))
   3.298 -
   3.299 -(defn uv-triangle
   3.300 -  "Convert the mesh triangle into the cooresponding triangle in
   3.301 -   UV-space. Z-component of these triangles is always zero." 
   3.302 -  [#^Mesh mesh #^Triangle tri]
   3.303 -  (apply #(Triangle. %1 %2 %3)
   3.304 -         (map vector2f->vector3f
   3.305 -              (tri-uv-coord mesh tri))))
   3.306 -
   3.307 -(defn pixel-triangle
   3.308 -  "Convert the mesh triangle into the corresponding triangle in
   3.309 -  UV-pixel-space. Z compenent will be zero."
   3.310 -  [#^Mesh mesh #^Triangle tri width height]
   3.311 -  (map-triangle (fn [_ v]
   3.312 -                  (Vector3f. (* width (.getX v))
   3.313 -                             (* height (.getY v))
   3.314 -                             0))
   3.315 -                (uv-triangle mesh tri)))
   3.316 -
   3.317 -(def rasterize pixel-triangle)
   3.318 -
   3.319 -
   3.320 -(defn triangle-bounds
   3.321 -  "Dimensions of the bounding square of the triangle in the form
   3.322 -   [x y width height].
   3.323 -   Assumes that the triangle lies in the XY plane."
   3.324 -  [#^Triangle tri]
   3.325 -  (let [verts (map vector3f-seq (triangle-seq tri))
   3.326 -        x (apply min (map first verts))
   3.327 -        y (apply min (map second verts))]
   3.328 -    [x y 
   3.329 -     (- (apply max (map first verts)) x)
   3.330 -     (- (apply max (map second verts)) y)
   3.331 -     ]))
   3.332 -  
   3.333 +(defn convex-bounds
   3.334 +  "Dimensions of the smallest integer bounding square of the list of
   3.335 +   2D verticies in the form: [x y width height]."
   3.336 +  [uv-verts]
   3.337 +  (let [xs (map first uv-verts)
   3.338 +        ys (map second uv-verts)
   3.339 +        x0 (Math/floor (apply min xs))
   3.340 +        y0 (Math/floor (apply min ys))
   3.341 +        x1 (Math/ceil (apply max xs))
   3.342 +        y1 (Math/ceil (apply max ys))]
   3.343 +    [x0 y0 (- x1 x0) (- y1 y0)]))
   3.344  
   3.345  (defn sensors-in-triangle
   3.346    "Find the locations of the touch sensors within a triangle in both
   3.347     UV and gemoetry relative coordinates."
   3.348    [image mesh tri-index]
   3.349    (let [width (.getWidth image)
   3.350 -        height (.getHeight image)]
   3.351 +        height (.getHeight image)
   3.352 +        UV-vertex-coords (triangle-UV-coord mesh width height tri-index)
   3.353 +        bounds (convex-bounds UV-vertex-coords)
   3.354 +        
   3.355 +        cutout-triangle (points->triangle UV-vertex-coords)
   3.356 +        UV-sensor-coords
   3.357 +        (filter (comp (partial inside-triangle? cutout-triangle)
   3.358 +                      (fn [[u v]] (Vector3f. u v 0)))
   3.359 +                (white-coordinates image bounds))
   3.360 +        UV->geometry (triangle-transformation
   3.361 +                      cutout-triangle
   3.362 +                      (triangle mesh tri-index))
   3.363 +        geometry-sensor-coords
   3.364 +        (map (fn [[u v]] (.mult UV->geometry (Vector3f. u v 0)))
   3.365 +             UV-sensor-coords)]
   3.366 +  {:UV UV-sensor-coords :geometry geometry-sensor-coords}))
   3.367  
   3.368 -
   3.369 -
   3.370 -
   3.371 -  )
   3.372 -
   3.373 -
   3.374 -(defn locate-feelers
   3.375 +(defn-memo locate-feelers
   3.376    "Search the geometry's tactile UV image for touch sensors, returning
   3.377    their positions in geometry-relative coordinates."
   3.378    [#^Geometry geo]
   3.379 -  (if-let [image (touch-receptor-image geo)]
   3.380 -    (let [mesh (.getMesh geo)
   3.381 -          tris (triangles geo)
   3.382 -
   3.383 -          width (.getWidth image)
   3.384 -          height (.getHeight image)
   3.385 -          
   3.386 -          ;; for each triangle
   3.387 -          sensor-coords
   3.388 -          (fn [tri]
   3.389 -            ;; translate triangle to uv-pixel-space
   3.390 -            (let [uv-tri
   3.391 -                  (pixel-triangle mesh tri width height)
   3.392 -                  bounds (vec (triangle-bounds uv-tri))]
   3.393 -              
   3.394 -              ;; get that part of the picture
   3.395 -              
   3.396 -              (apply #(.setRoi image %1 %2 %3 %4) bounds)
   3.397 -              (let [cutout (.crop (.getProcessor image))
   3.398 -                    ;; extract white pixels inside triangle
   3.399 -                    cutout-tri
   3.400 -                    (map-triangle
   3.401 -                     (fn [_ v]
   3.402 -                       (.subtract
   3.403 -                        v
   3.404 -                        (Vector3f. (bounds 0) (bounds 1) (float 0))))
   3.405 -                     uv-tri)
   3.406 -                    whites (filter (partial inside-triangle? cutout-tri)
   3.407 -                                   (map vector2f->vector3f
   3.408 -                                        (white-coordinates cutout)))
   3.409 -                    ;; translate pixel coordinates to world-space
   3.410 -                    transform (triangle-transformation cutout-tri tri)]
   3.411 -                (map #(.mult transform %) whites))))]
   3.412 -      (vec (map sensor-coords tris)))
   3.413 -    (repeat (count (triangles geo)) [])))
   3.414 +  (let [mesh (.getMesh geo)
   3.415 +        num-triangles (.getTriangleCount mesh)]
   3.416 +    (if-let [image (tactile-sensor-image geo)]
   3.417 +      (map
   3.418 +       (partial sensors-in-triangle image mesh)
   3.419 +       (range num-triangles))
   3.420 +      (repeat (.getTriangleCount mesh) {:UV nil :geometry nil}))))
   3.421  
   3.422  (use 'clojure.contrib.def)
   3.423  
   3.424  (defn-memo touch-topology [#^Gemoetry geo]
   3.425 -  (if-let [image (touch-receptor-image geo)]
   3.426 -    (let [feeler-coords
   3.427 -          (map
   3.428 -           #(vector (int (.getX %)) (int (.getY %)))
   3.429 -           (white-coordinates
   3.430 -            (.getProcessor image)))]
   3.431 -      (vec (collapse feeler-coords)))
   3.432 -    []))
   3.433 +  (vec (collapse (reduce concat (map :UV (locate-feelers geo))))))
   3.434 +
   3.435 +(defn-memo feeler-coordinates [#^Geometry geo]
   3.436 +  (vec (map :geometry (locate-feelers geo))))
   3.437  
   3.438  (defn enable-touch [#^Geometry geo]
   3.439 -  (let [feeler-coords (locate-feelers geo)
   3.440 +  (let [feeler-coords (feeler-coordinates geo)
   3.441          tris (triangles geo)
   3.442          limit 0.1]
   3.443      (fn [node]
   3.444 @@ -744,6 +704,7 @@
   3.445       ;;(com.aurellem.capture.Capture/captureVideo
   3.446       ;; world (file-str "/home/r/proj/ai-videos/hand"))
   3.447       (.setTimer world (RatchetTimer. 60))
   3.448 +     ;;(speed-up world)
   3.449       ;;(set-gravity world (Vector3f. 0 0 0))
   3.450       )
   3.451     (fn [world tpf]
     4.1 --- a/org/util.org	Sun Jan 15 00:40:49 2012 -0700
     4.2 +++ b/org/util.org	Sun Jan 15 04:08:31 2012 -0700
     4.3 @@ -453,6 +453,13 @@
     4.4    Textual
     4.5    (text [control]
     4.6      (println "...geo...")))
     4.7 +
     4.8 +(extend-type Triangle
     4.9 +  Textual
    4.10 +  (text [t]
    4.11 +    (println "Triangle: " \newline (.get1 t) \newline
    4.12 +             (.get2 t) \newline (.get3 t))))
    4.13 +
    4.14  #+end_src
    4.15  
    4.16  Here I make the =Viewable= protocol and extend it to JME's types.  Now