Mercurial > cortex
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]