diff org/test-creature.org @ 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
line wrap: on
line diff
     1.1 --- a/org/test-creature.org	Sun Jan 15 00:40:49 2012 -0700
     1.2 +++ b/org/test-creature.org	Sun Jan 15 04:08:31 2012 -0700
     1.3 @@ -65,6 +65,7 @@
     1.4  (import java.awt.Dimension)
     1.5  (import com.aurellem.capture.RatchetTimer)
     1.6  (declare joint-create)
     1.7 +(use 'clojure.contrib.def)
     1.8  
     1.9  (defn view-image
    1.10    "Initailizes a JPanel on which you may draw a BufferedImage.
    1.11 @@ -142,40 +143,41 @@
    1.12    "Take a set of pairs of integers and collapse them into a
    1.13     contigous bitmap."
    1.14    [points]
    1.15 -  (let
    1.16 -      [num-points (count points)
    1.17 -       center (vector
    1.18 -               (int (average (map first points)))
    1.19 -               (int (average (map first points))))
    1.20 -       flattened
    1.21 -       (reduce
    1.22 -        concat 
    1.23 -        (map
    1.24 -         (fn [column]
    1.25 -           (map vector
    1.26 -                (map first column)
    1.27 -                (collapse-1d (second center)
    1.28 -                             (map second column))))
    1.29 -         (partition-by first (sort-by first points))))
    1.30 -       squeezed
    1.31 -       (reduce
    1.32 -        concat 
    1.33 -        (map
    1.34 -         (fn [row]
    1.35 -           (map vector
    1.36 -                (collapse-1d (first center)
    1.37 -                             (map first row))
    1.38 -                (map second row)))
    1.39 -         (partition-by second (sort-by second flattened))))
    1.40 -       relocate
    1.41 -       (let [min-x (apply min (map first squeezed))
    1.42 -             min-y (apply min (map second squeezed))]
    1.43 -         (map (fn [[x y]]
    1.44 -                [(- x min-x)
    1.45 -                 (- y min-y)])
    1.46 -              squeezed))]
    1.47 -    relocate
    1.48 -   ))
    1.49 +  (if (empty? points) []
    1.50 +      (let
    1.51 +          [num-points (count points)
    1.52 +           center (vector
    1.53 +                   (int (average (map first points)))
    1.54 +                   (int (average (map first points))))
    1.55 +           flattened
    1.56 +           (reduce
    1.57 +            concat 
    1.58 +            (map
    1.59 +             (fn [column]
    1.60 +               (map vector
    1.61 +                    (map first column)
    1.62 +                    (collapse-1d (second center)
    1.63 +                                 (map second column))))
    1.64 +             (partition-by first (sort-by first points))))
    1.65 +           squeezed
    1.66 +           (reduce
    1.67 +            concat 
    1.68 +            (map
    1.69 +             (fn [row]
    1.70 +               (map vector
    1.71 +                    (collapse-1d (first center)
    1.72 +                                 (map first row))
    1.73 +                    (map second row)))
    1.74 +             (partition-by second (sort-by second flattened))))
    1.75 +           relocate
    1.76 +           (let [min-x (apply min (map first squeezed))
    1.77 +                 min-y (apply min (map second squeezed))]
    1.78 +             (map (fn [[x y]]
    1.79 +                    [(- x min-x)
    1.80 +                     (- y min-y)])
    1.81 +                  squeezed))]
    1.82 +        relocate
    1.83 +        )))
    1.84  
    1.85  (defn load-bullet []
    1.86    (let [sim (world (Node.) {} no-op no-op)]
    1.87 @@ -417,33 +419,10 @@
    1.88  
    1.89  (import ij.ImagePlus)
    1.90  
    1.91 -(defn triangle-indices
    1.92 -  "Get the triangle vertex indices of a given triangle from a given
    1.93 -   mesh."
    1.94 -  [#^Mesh mesh triangle-index]
    1.95 -  (let [indices (int-array 3)]
    1.96 -    (.getTriangle mesh triangle-index indices)
    1.97 -    (vec indices)))
    1.98 +;; Every Mesh has many triangles, each with its own index.
    1.99 +;; Every vertex has its own index as well.
   1.100  
   1.101 -(defn uv-coord
   1.102 -  "Get the uv-coordinates of the vertex named by vertex-index"
   1.103 -  [#^Mesh mesh vertex-index]
   1.104 -  (let [UV-buffer
   1.105 -        (.getData
   1.106 -         (.getBuffer
   1.107 -          mesh
   1.108 -          VertexBuffer$Type/TexCoord))]
   1.109 -    (Vector2f.
   1.110 -     (.get UV-buffer (* vertex-index 2))
   1.111 -     (.get UV-buffer (+ 1 (* vertex-index 2))))))
   1.112 -
   1.113 -(defn tri-uv-coord
   1.114 -  "Get the uv-cooridnates of the triangle's verticies."
   1.115 -  [#^Mesh mesh #^Triangle triangle]
   1.116 -  (map (partial uv-coord mesh)
   1.117 -       (triangle-indices mesh (.getIndex triangle))))
   1.118 -
   1.119 -(defn touch-receptor-image
   1.120 +(defn tactile-sensor-image
   1.121    "Return the touch-sensor distribution image in ImagePlus format, or
   1.122     nil if it does not exist."
   1.123    [#^Geometry obj]
   1.124 @@ -456,9 +435,7 @@
   1.125            [texture
   1.126             (.getTextureValue texture-param)
   1.127             im (.getImage texture)]
   1.128 -        (ImagePlus.
   1.129 -         "UV-map"
   1.130 -         (ImageToAwt/convert im false false 0))))))
   1.131 +        (ImageToAwt/convert im false false 0)))))
   1.132  
   1.133  (import ij.process.ImageProcessor)
   1.134  (import java.awt.image.BufferedImage)
   1.135 @@ -466,25 +443,58 @@
   1.136  (def white -1)
   1.137    
   1.138  (defn filter-pixels
   1.139 -  "List the coordinates of all pixels matching pred."
   1.140 +  "List the coordinates of all pixels matching pred, within the bounds
   1.141 +   provided. Bounds -> [x0 y0 width height]"
   1.142    {:author "Dylan Holmes"}
   1.143 -  [pred #^ImageProcessor ip]
   1.144 -  (let
   1.145 -      [width (.getWidth ip)
   1.146 -       height (.getHeight ip)]
   1.147 -    ((fn accumulate [x y matches]
   1.148 -       (cond
   1.149 -        (>= y height) matches
   1.150 -        (>= x width) (recur 0 (inc y) matches)
   1.151 -        (pred (.getPixel ip x y))
   1.152 -        (recur (inc x) y (conj matches (Vector2f. x y)))
   1.153 -        :else (recur (inc x) y matches)))
   1.154 -     0 0 [])))
   1.155 +  ([pred #^BufferedImage image]
   1.156 +     (filter-pixels pred image [0 0 (.getWidth image) (.getHeight image)]))
   1.157 +  ([pred #^BufferedImage image [x0 y0 width height]]
   1.158 +     ((fn accumulate [x y matches]
   1.159 +        (cond
   1.160 +         (>= y (+ height y0)) matches
   1.161 +         (>= x (+ width x0)) (recur 0 (inc y) matches)
   1.162 +         (pred (.getRGB image x y))
   1.163 +         (recur (inc x) y (conj matches [x y]))
   1.164 +         :else (recur (inc x) y matches)))
   1.165 +      x0 y0 [])))
   1.166  
   1.167  (defn white-coordinates
   1.168 -  "List the coordinates of all the white pixels in an image."
   1.169 -  [#^ImageProcessor ip]
   1.170 -  (filter-pixels #(= % white) ip))
   1.171 +  "Coordinates of all the white pixels in a subset of the image."
   1.172 +  [#^BufferedImage image bounds]
   1.173 +  (filter-pixels #(= % white) image bounds))
   1.174 +
   1.175 +(defn triangle
   1.176 +  "Get the triangle specified by triangle-index from the mesh"
   1.177 +  [#^Mesh mesh triangle-index]
   1.178 +  (let [scratch (Triangle.)]
   1.179 +    (.getTriangle mesh triangle-index scratch)
   1.180 +    scratch))
   1.181 +
   1.182 +(defn triangle-vertex-indices
   1.183 +  "Get the triangle vertex indices of a given triangle from a given
   1.184 +   mesh."
   1.185 +  [#^Mesh mesh triangle-index]
   1.186 +  (let [indices (int-array 3)]
   1.187 +    (.getTriangle mesh triangle-index indices)
   1.188 +    (vec indices)))
   1.189 +
   1.190 +(defn vertex-UV-coord
   1.191 +  "Get the uv-coordinates of the vertex named by vertex-index"
   1.192 +  [#^Mesh mesh vertex-index]
   1.193 +  (let [UV-buffer
   1.194 +        (.getData
   1.195 +         (.getBuffer
   1.196 +          mesh
   1.197 +          VertexBuffer$Type/TexCoord))]
   1.198 +    [(.get UV-buffer (* vertex-index 2))
   1.199 +     (.get UV-buffer (+ 1 (* vertex-index 2)))]))
   1.200 +
   1.201 +(defn triangle-UV-coord
   1.202 +  "Get the uv-cooridnates of the triangle's verticies."
   1.203 +  [#^Mesh mesh width height triangle-index]
   1.204 +  (map (fn [[u v]] (vector (* width u) (* height v)))
   1.205 +       (map (partial vertex-UV-coord mesh)
   1.206 +            (triangle-vertex-indices mesh triangle-index))))
   1.207    
   1.208  (defn same-side?
   1.209    "Given the points p1 and p2 and the reference point ref, is point p
   1.210 @@ -496,11 +506,26 @@
   1.211      (.cross (.subtract p2 p1) (.subtract p p1))
   1.212      (.cross (.subtract p2 p1) (.subtract ref p1)))))
   1.213  
   1.214 +(defn triangle-seq [#^Triangle tri]
   1.215 +  [(.get1 tri) (.get2 tri) (.get3 tri)])
   1.216 +
   1.217 +(defn vector3f-seq [#^Vector3f v]
   1.218 +  [(.getX v) (.getY v) (.getZ v)])
   1.219 +
   1.220 +(defn inside-triangle?
   1.221 +  "Is the point inside the triangle?"
   1.222 +  {:author "Dylan Holmes"}
   1.223 +  [#^Triangle tri #^Vector3f p]
   1.224 +  (let [[vert-1 vert-2 vert-3] (triangle-seq tri)]
   1.225 +    (and
   1.226 +     (same-side? vert-1 vert-2 vert-3 p)
   1.227 +     (same-side? vert-2 vert-3 vert-1 p)
   1.228 +     (same-side? vert-3 vert-1 vert-2 p))))
   1.229 +
   1.230  (defn triangle->matrix4f
   1.231 -  "Converts the triangle into a 4x4 matrix of vertices: The first
   1.232 -   three columns contain the vertices of the triangle; the last
   1.233 -   contains the unit normal of the triangle. The bottom row is filled
   1.234 -   with 1s."
   1.235 +  "Converts the triangle into a 4x4 matrix: The first three columns
   1.236 +   contain the vertices of the triangle; the last contains the unit
   1.237 +   normal of the triangle. The bottom row is filled with 1s."
   1.238    [#^Triangle t]
   1.239    (let [mat (Matrix4f.)
   1.240          [vert-1 vert-2 vert-3]
   1.241 @@ -523,150 +548,85 @@
   1.242     (triangle->matrix4f tri-2)
   1.243     (.invert (triangle->matrix4f tri-1))))
   1.244  
   1.245 -(def death (Triangle. 
   1.246 -            (Vector3f. 1 1 1)
   1.247 -            (Vector3f. 1 2 3)
   1.248 -            (Vector3f. 5 6 7)))
   1.249 -
   1.250 -(def death-2 (Triangle. 
   1.251 -             (Vector3f. 2 2 2)
   1.252 -             (Vector3f. 1 1 1)
   1.253 -             (Vector3f. 0 1 0)))
   1.254 +(defn point->vector2f [[u v]]
   1.255 +  (Vector2f. u v))
   1.256  
   1.257  (defn vector2f->vector3f [v]
   1.258    (Vector3f. (.getX v) (.getY v) 0))
   1.259  
   1.260 -(extend-type Triangle
   1.261 -  Textual
   1.262 -  (text [t]
   1.263 -    (println "Triangle: " \newline (.get1 t) \newline
   1.264 -             (.get2 t) \newline (.get3 t))))
   1.265 -
   1.266  (defn map-triangle [f #^Triangle tri]
   1.267    (Triangle.
   1.268     (f 0 (.get1 tri))
   1.269     (f 1 (.get2 tri))
   1.270     (f 2 (.get3 tri))))
   1.271  
   1.272 -(defn triangle-seq [#^Triangle tri]
   1.273 -  [(.get1 tri) (.get2 tri) (.get3 tri)])
   1.274 +(defn points->triangle
   1.275 +  "Convert a list of points into a triangle."
   1.276 +  [points]
   1.277 +  (apply #(Triangle. %1 %2 %3)
   1.278 +         (map (fn [point]
   1.279 +                (let [point (vec point)]
   1.280 +                  (Vector3f. (get point 0 0)
   1.281 +                             (get point 1 0)
   1.282 +                             (get point 2 0))))
   1.283 +              (take 3 points))))
   1.284  
   1.285 -(defn vector3f-seq [#^Vector3f v]
   1.286 -  [(.getX v) (.getY v) (.getZ v)])
   1.287 -
   1.288 -(defn inside-triangle?
   1.289 -  "Is the point inside the triangle? Now what do we do?
   1.290 -   You might want to hold on there"
   1.291 -  {:author "Dylan Holmes"}
   1.292 -  [tri p]
   1.293 -  (let [[vert-1 vert-2 vert-3] (triangle-seq tri)]
   1.294 -    (and
   1.295 -     (same-side? vert-1 vert-2 vert-3 p)
   1.296 -     (same-side? vert-2 vert-3 vert-1 p)
   1.297 -     (same-side? vert-3 vert-1 vert-2 p))))
   1.298 -
   1.299 -(defn uv-triangle
   1.300 -  "Convert the mesh triangle into the cooresponding triangle in
   1.301 -   UV-space. Z-component of these triangles is always zero." 
   1.302 -  [#^Mesh mesh #^Triangle tri]
   1.303 -  (apply #(Triangle. %1 %2 %3)
   1.304 -         (map vector2f->vector3f
   1.305 -              (tri-uv-coord mesh tri))))
   1.306 -
   1.307 -(defn pixel-triangle
   1.308 -  "Convert the mesh triangle into the corresponding triangle in
   1.309 -  UV-pixel-space. Z compenent will be zero."
   1.310 -  [#^Mesh mesh #^Triangle tri width height]
   1.311 -  (map-triangle (fn [_ v]
   1.312 -                  (Vector3f. (* width (.getX v))
   1.313 -                             (* height (.getY v))
   1.314 -                             0))
   1.315 -                (uv-triangle mesh tri)))
   1.316 -
   1.317 -(def rasterize pixel-triangle)
   1.318 -
   1.319 -
   1.320 -(defn triangle-bounds
   1.321 -  "Dimensions of the bounding square of the triangle in the form
   1.322 -   [x y width height].
   1.323 -   Assumes that the triangle lies in the XY plane."
   1.324 -  [#^Triangle tri]
   1.325 -  (let [verts (map vector3f-seq (triangle-seq tri))
   1.326 -        x (apply min (map first verts))
   1.327 -        y (apply min (map second verts))]
   1.328 -    [x y 
   1.329 -     (- (apply max (map first verts)) x)
   1.330 -     (- (apply max (map second verts)) y)
   1.331 -     ]))
   1.332 -  
   1.333 +(defn convex-bounds
   1.334 +  "Dimensions of the smallest integer bounding square of the list of
   1.335 +   2D verticies in the form: [x y width height]."
   1.336 +  [uv-verts]
   1.337 +  (let [xs (map first uv-verts)
   1.338 +        ys (map second uv-verts)
   1.339 +        x0 (Math/floor (apply min xs))
   1.340 +        y0 (Math/floor (apply min ys))
   1.341 +        x1 (Math/ceil (apply max xs))
   1.342 +        y1 (Math/ceil (apply max ys))]
   1.343 +    [x0 y0 (- x1 x0) (- y1 y0)]))
   1.344  
   1.345  (defn sensors-in-triangle
   1.346    "Find the locations of the touch sensors within a triangle in both
   1.347     UV and gemoetry relative coordinates."
   1.348    [image mesh tri-index]
   1.349    (let [width (.getWidth image)
   1.350 -        height (.getHeight image)]
   1.351 +        height (.getHeight image)
   1.352 +        UV-vertex-coords (triangle-UV-coord mesh width height tri-index)
   1.353 +        bounds (convex-bounds UV-vertex-coords)
   1.354 +        
   1.355 +        cutout-triangle (points->triangle UV-vertex-coords)
   1.356 +        UV-sensor-coords
   1.357 +        (filter (comp (partial inside-triangle? cutout-triangle)
   1.358 +                      (fn [[u v]] (Vector3f. u v 0)))
   1.359 +                (white-coordinates image bounds))
   1.360 +        UV->geometry (triangle-transformation
   1.361 +                      cutout-triangle
   1.362 +                      (triangle mesh tri-index))
   1.363 +        geometry-sensor-coords
   1.364 +        (map (fn [[u v]] (.mult UV->geometry (Vector3f. u v 0)))
   1.365 +             UV-sensor-coords)]
   1.366 +  {:UV UV-sensor-coords :geometry geometry-sensor-coords}))
   1.367  
   1.368 -
   1.369 -
   1.370 -
   1.371 -  )
   1.372 -
   1.373 -
   1.374 -(defn locate-feelers
   1.375 +(defn-memo locate-feelers
   1.376    "Search the geometry's tactile UV image for touch sensors, returning
   1.377    their positions in geometry-relative coordinates."
   1.378    [#^Geometry geo]
   1.379 -  (if-let [image (touch-receptor-image geo)]
   1.380 -    (let [mesh (.getMesh geo)
   1.381 -          tris (triangles geo)
   1.382 -
   1.383 -          width (.getWidth image)
   1.384 -          height (.getHeight image)
   1.385 -          
   1.386 -          ;; for each triangle
   1.387 -          sensor-coords
   1.388 -          (fn [tri]
   1.389 -            ;; translate triangle to uv-pixel-space
   1.390 -            (let [uv-tri
   1.391 -                  (pixel-triangle mesh tri width height)
   1.392 -                  bounds (vec (triangle-bounds uv-tri))]
   1.393 -              
   1.394 -              ;; get that part of the picture
   1.395 -              
   1.396 -              (apply #(.setRoi image %1 %2 %3 %4) bounds)
   1.397 -              (let [cutout (.crop (.getProcessor image))
   1.398 -                    ;; extract white pixels inside triangle
   1.399 -                    cutout-tri
   1.400 -                    (map-triangle
   1.401 -                     (fn [_ v]
   1.402 -                       (.subtract
   1.403 -                        v
   1.404 -                        (Vector3f. (bounds 0) (bounds 1) (float 0))))
   1.405 -                     uv-tri)
   1.406 -                    whites (filter (partial inside-triangle? cutout-tri)
   1.407 -                                   (map vector2f->vector3f
   1.408 -                                        (white-coordinates cutout)))
   1.409 -                    ;; translate pixel coordinates to world-space
   1.410 -                    transform (triangle-transformation cutout-tri tri)]
   1.411 -                (map #(.mult transform %) whites))))]
   1.412 -      (vec (map sensor-coords tris)))
   1.413 -    (repeat (count (triangles geo)) [])))
   1.414 +  (let [mesh (.getMesh geo)
   1.415 +        num-triangles (.getTriangleCount mesh)]
   1.416 +    (if-let [image (tactile-sensor-image geo)]
   1.417 +      (map
   1.418 +       (partial sensors-in-triangle image mesh)
   1.419 +       (range num-triangles))
   1.420 +      (repeat (.getTriangleCount mesh) {:UV nil :geometry nil}))))
   1.421  
   1.422  (use 'clojure.contrib.def)
   1.423  
   1.424  (defn-memo touch-topology [#^Gemoetry geo]
   1.425 -  (if-let [image (touch-receptor-image geo)]
   1.426 -    (let [feeler-coords
   1.427 -          (map
   1.428 -           #(vector (int (.getX %)) (int (.getY %)))
   1.429 -           (white-coordinates
   1.430 -            (.getProcessor image)))]
   1.431 -      (vec (collapse feeler-coords)))
   1.432 -    []))
   1.433 +  (vec (collapse (reduce concat (map :UV (locate-feelers geo))))))
   1.434 +
   1.435 +(defn-memo feeler-coordinates [#^Geometry geo]
   1.436 +  (vec (map :geometry (locate-feelers geo))))
   1.437  
   1.438  (defn enable-touch [#^Geometry geo]
   1.439 -  (let [feeler-coords (locate-feelers geo)
   1.440 +  (let [feeler-coords (feeler-coordinates geo)
   1.441          tris (triangles geo)
   1.442          limit 0.1]
   1.443      (fn [node]
   1.444 @@ -744,6 +704,7 @@
   1.445       ;;(com.aurellem.capture.Capture/captureVideo
   1.446       ;; world (file-str "/home/r/proj/ai-videos/hand"))
   1.447       (.setTimer world (RatchetTimer. 60))
   1.448 +     ;;(speed-up world)
   1.449       ;;(set-gravity world (Vector3f. 0 0 0))
   1.450       )
   1.451     (fn [world tpf]