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