Mercurial > cortex
diff org/skin.org @ 156:e8df6e76c3e5
refactored touch
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Fri, 03 Feb 2012 06:15:34 -0700 |
parents | 39e4e1542e4a |
children |
line wrap: on
line diff
1.1 --- a/org/skin.org Fri Feb 03 06:04:30 2012 -0700 1.2 +++ b/org/skin.org Fri Feb 03 06:15:34 2012 -0700 1.3 @@ -25,11 +25,15 @@ 1.4 density of triangles along the surface of the Geometry. Enables a 1.5 Geometry to know what parts of itself are touching nearby objects." 1.6 {:author "Robert McIntyre"} 1.7 - (:use (cortex world util)) 1.8 + (:use (cortex world util sense)) 1.9 (:import com.jme3.scene.Geometry) 1.10 (:import com.jme3.collision.CollisionResults) 1.11 + (:import jme3tools.converters.ImageToAwt) 1.12 (:import (com.jme3.math Triangle Vector3f Ray))) 1.13 1.14 +(use 'clojure.contrib.def) 1.15 +(cortex.import/mega-import-jme3) 1.16 + 1.17 (defn triangles 1.18 "Return a sequence of all the Triangles which compose a given 1.19 Geometry." 1.20 @@ -56,8 +60,7 @@ 1.21 (.localToWorld geom (.getCenter tri) new) new)) 1.22 1.23 (defn get-ray-direction 1.24 - "Return the direction which a Ray would have to have to be in the 1.25 - exact center of a particular Triangle in the Geometry, pointing 1.26 + "Return the direction which a Ray would have to have to be to point 1.27 normal to the Triangle, in coordinates relative to the center of the 1.28 Triangle." 1.29 [geom tri] 1.30 @@ -69,37 +72,239 @@ 1.31 (.add (.getCenter tri) (.getNormal tri)) n+c) 1.32 (.subtract n+c (get-ray-origin geom tri)))) 1.33 1.34 -(defn normal-rays 1.35 - "For each Triangle which comprises the Geometry, returns a Ray which 1.36 - is centered on that Triangle, points outward in a normal direction, 1.37 - and extends for =limit= distance." 1.38 - [limit #^Geometry geom] 1.39 - (vec 1.40 - (map 1.41 - (fn [tri] 1.42 - (doto 1.43 - (Ray. (get-ray-origin geom tri) 1.44 - (get-ray-direction geom tri)) 1.45 - (.setLimit limit))) 1.46 - (triangles geom)))) 1.47 +;; Every Mesh has many triangles, each with its own index. 1.48 +;; Every vertex has its own index as well. 1.49 1.50 -(defn touch-percieve 1.51 - "Augment a Geometry with the sense of touch. Returns a sequence of 1.52 - non-negative integers, one for each triangle, with the value of the 1.53 - integer describing how many objects a ray of length =limit=, normal 1.54 - to the triangle and originating from its center, encountered. The 1.55 - Geometry itself is not counted among the results." 1.56 - [limit geom node] 1.57 - (let [normals (normal-rays limit geom)] 1.58 - (doall 1.59 - (for [ray normals] 1.60 +(defn tactile-sensor-image 1.61 + "Return the touch-sensor distribution image in BufferedImage format, 1.62 + or nil if it does not exist." 1.63 + [#^Geometry obj] 1.64 + (if-let [image-path (meta-data obj "touch")] 1.65 + (ImageToAwt/convert 1.66 + (.getImage 1.67 + (.loadTexture 1.68 + (asset-manager) 1.69 + image-path)) 1.70 + false false 0))) 1.71 + 1.72 + 1.73 + 1.74 +(defn triangle 1.75 + "Get the triangle specified by triangle-index from the mesh within 1.76 + bounds." 1.77 + [#^Mesh mesh triangle-index] 1.78 + (let [scratch (Triangle.)] 1.79 + (.getTriangle mesh triangle-index scratch) 1.80 + scratch)) 1.81 + 1.82 +(defn triangle-vertex-indices 1.83 + "Get the triangle vertex indices of a given triangle from a given 1.84 + mesh." 1.85 + [#^Mesh mesh triangle-index] 1.86 + (let [indices (int-array 3)] 1.87 + (.getTriangle mesh triangle-index indices) 1.88 + (vec indices))) 1.89 + 1.90 +(defn vertex-UV-coord 1.91 + "Get the uv-coordinates of the vertex named by vertex-index" 1.92 + [#^Mesh mesh vertex-index] 1.93 + (let [UV-buffer 1.94 + (.getData 1.95 + (.getBuffer 1.96 + mesh 1.97 + VertexBuffer$Type/TexCoord))] 1.98 + [(.get UV-buffer (* vertex-index 2)) 1.99 + (.get UV-buffer (+ 1 (* vertex-index 2)))])) 1.100 + 1.101 +(defn triangle-UV-coord 1.102 + "Get the uv-cooridnates of the triangle's verticies." 1.103 + [#^Mesh mesh width height triangle-index] 1.104 + (map (fn [[u v]] (vector (* width u) (* height v))) 1.105 + (map (partial vertex-UV-coord mesh) 1.106 + (triangle-vertex-indices mesh triangle-index)))) 1.107 + 1.108 +(defn same-side? 1.109 + "Given the points p1 and p2 and the reference point ref, is point p 1.110 + on the same side of the line that goes through p1 and p2 as ref is?" 1.111 + [p1 p2 ref p] 1.112 + (<= 1.113 + 0 1.114 + (.dot 1.115 + (.cross (.subtract p2 p1) (.subtract p p1)) 1.116 + (.cross (.subtract p2 p1) (.subtract ref p1))))) 1.117 + 1.118 +(defn triangle-seq [#^Triangle tri] 1.119 + [(.get1 tri) (.get2 tri) (.get3 tri)]) 1.120 + 1.121 +(defn vector3f-seq [#^Vector3f v] 1.122 + [(.getX v) (.getY v) (.getZ v)]) 1.123 + 1.124 +(defn inside-triangle? 1.125 + "Is the point inside the triangle?" 1.126 + {:author "Dylan Holmes"} 1.127 + [#^Triangle tri #^Vector3f p] 1.128 + (let [[vert-1 vert-2 vert-3] (triangle-seq tri)] 1.129 + (and 1.130 + (same-side? vert-1 vert-2 vert-3 p) 1.131 + (same-side? vert-2 vert-3 vert-1 p) 1.132 + (same-side? vert-3 vert-1 vert-2 p)))) 1.133 + 1.134 +(defn triangle->matrix4f 1.135 + "Converts the triangle into a 4x4 matrix: The first three columns 1.136 + contain the vertices of the triangle; the last contains the unit 1.137 + normal of the triangle. The bottom row is filled with 1s." 1.138 + [#^Triangle t] 1.139 + (let [mat (Matrix4f.) 1.140 + [vert-1 vert-2 vert-3] 1.141 + ((comp vec map) #(.get t %) (range 3)) 1.142 + unit-normal (do (.calculateNormal t)(.getNormal t)) 1.143 + vertices [vert-1 vert-2 vert-3 unit-normal]] 1.144 + (dorun 1.145 + (for [row (range 4) col (range 3)] 1.146 (do 1.147 - (let [results (CollisionResults.)] 1.148 - (.collideWith node ray results) 1.149 - (let [touch-objects 1.150 - (set (filter #(not (= geom %)) 1.151 - (map #(.getGeometry %) results)))] 1.152 - (count touch-objects)))))))) 1.153 + (.set mat col row (.get (vertices row)col)) 1.154 + (.set mat 3 row 1)))) 1.155 + mat)) 1.156 + 1.157 +(defn triangle-transformation 1.158 + "Returns the affine transformation that converts each vertex in the 1.159 + first triangle into the corresponding vertex in the second 1.160 + triangle." 1.161 + [#^Triangle tri-1 #^Triangle tri-2] 1.162 + (.mult 1.163 + (triangle->matrix4f tri-2) 1.164 + (.invert (triangle->matrix4f tri-1)))) 1.165 + 1.166 +(defn point->vector2f [[u v]] 1.167 + (Vector2f. u v)) 1.168 + 1.169 +(defn vector2f->vector3f [v] 1.170 + (Vector3f. (.getX v) (.getY v) 0)) 1.171 + 1.172 +(defn map-triangle [f #^Triangle tri] 1.173 + (Triangle. 1.174 + (f 0 (.get1 tri)) 1.175 + (f 1 (.get2 tri)) 1.176 + (f 2 (.get3 tri)))) 1.177 + 1.178 +(defn points->triangle 1.179 + "Convert a list of points into a triangle." 1.180 + [points] 1.181 + (apply #(Triangle. %1 %2 %3) 1.182 + (map (fn [point] 1.183 + (let [point (vec point)] 1.184 + (Vector3f. (get point 0 0) 1.185 + (get point 1 0) 1.186 + (get point 2 0)))) 1.187 + (take 3 points)))) 1.188 + 1.189 +(defn convex-bounds 1.190 + ;;dylan 1.191 + "Returns the smallest square containing the given 1.192 +vertices, as a vector of integers [left top width height]." 1.193 + ;; "Dimensions of the smallest integer bounding square of the list of 1.194 + ;; 2D verticies in the form: [x y width height]." 1.195 + [uv-verts] 1.196 + (let [xs (map first uv-verts) 1.197 + ys (map second uv-verts) 1.198 + x0 (Math/floor (apply min xs)) 1.199 + y0 (Math/floor (apply min ys)) 1.200 + x1 (Math/ceil (apply max xs)) 1.201 + y1 (Math/ceil (apply max ys))] 1.202 + [x0 y0 (- x1 x0) (- y1 y0)])) 1.203 + 1.204 +(defn sensors-in-triangle 1.205 + ;;dylan 1.206 + "Locate the touch sensors in the triangle, returning a map of their UV and geometry-relative coordinates." 1.207 + ;;"Find the locations of the touch sensors within a triangle in both 1.208 + ;; UV and gemoetry relative coordinates." 1.209 + [image mesh tri-index] 1.210 + (let [width (.getWidth image) 1.211 + height (.getHeight image) 1.212 + UV-vertex-coords (triangle-UV-coord mesh width height tri-index) 1.213 + bounds (convex-bounds UV-vertex-coords) 1.214 + 1.215 + cutout-triangle (points->triangle UV-vertex-coords) 1.216 + UV-sensor-coords 1.217 + (filter (comp (partial inside-triangle? cutout-triangle) 1.218 + (fn [[u v]] (Vector3f. u v 0))) 1.219 + (white-coordinates image bounds)) 1.220 + UV->geometry (triangle-transformation 1.221 + cutout-triangle 1.222 + (triangle mesh tri-index)) 1.223 + geometry-sensor-coords 1.224 + (map (fn [[u v]] (.mult UV->geometry (Vector3f. u v 0))) 1.225 + UV-sensor-coords)] 1.226 + {:UV UV-sensor-coords :geometry geometry-sensor-coords})) 1.227 + 1.228 +(defn-memo locate-feelers 1.229 + "Search the geometry's tactile UV image for touch sensors, returning 1.230 + their positions in geometry-relative coordinates." 1.231 + [#^Geometry geo] 1.232 + (let [mesh (.getMesh geo) 1.233 + num-triangles (.getTriangleCount mesh)] 1.234 + (if-let [image (tactile-sensor-image geo)] 1.235 + (map 1.236 + (partial sensors-in-triangle image mesh) 1.237 + (range num-triangles)) 1.238 + (repeat (.getTriangleCount mesh) {:UV nil :geometry nil})))) 1.239 + 1.240 + 1.241 + 1.242 +(defn-memo touch-topology [#^Gemoetry geo] 1.243 + (vec (collapse (reduce concat (map :UV (locate-feelers geo)))))) 1.244 + 1.245 +(defn-memo feeler-coordinates [#^Geometry geo] 1.246 + (vec (map :geometry (locate-feelers geo)))) 1.247 + 1.248 +(defn enable-touch [#^Geometry geo] 1.249 + (let [feeler-coords (feeler-coordinates geo) 1.250 + tris (triangles geo) 1.251 + limit 0.1 1.252 + ;;results (CollisionResults.) 1.253 + ] 1.254 + (if (empty? (touch-topology geo)) 1.255 + nil 1.256 + (fn [node] 1.257 + (let [sensor-origins 1.258 + (map 1.259 + #(map (partial local-to-world geo) %) 1.260 + feeler-coords) 1.261 + triangle-normals 1.262 + (map (partial get-ray-direction geo) 1.263 + tris) 1.264 + rays 1.265 + (flatten 1.266 + (map (fn [origins norm] 1.267 + (map #(doto (Ray. % norm) 1.268 + (.setLimit limit)) origins)) 1.269 + sensor-origins triangle-normals))] 1.270 + (vector 1.271 + (touch-topology geo) 1.272 + (vec 1.273 + (for [ray rays] 1.274 + (do 1.275 + (let [results (CollisionResults.)] 1.276 + (.collideWith node ray results) 1.277 + (let [touch-objects 1.278 + (filter #(not (= geo (.getGeometry %))) 1.279 + results)] 1.280 + (- 255 1.281 + (if (empty? touch-objects) 255 1.282 + (rem 1.283 + (int 1.284 + (* 255 (/ (.getDistance 1.285 + (first touch-objects)) limit))) 1.286 + 256)))))))))))))) 1.287 + 1.288 + 1.289 +(defn touch [#^Node pieces] 1.290 + (filter (comp not nil?) 1.291 + (map enable-touch 1.292 + (filter #(isa? (class %) Geometry) 1.293 + (node-seq pieces))))) 1.294 + 1.295 + 1.296 #+end_src 1.297 1.298