Mercurial > cortex
diff org/touch.org @ 228:0589c35f04f2
wrote intro for touch.org
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 11 Feb 2012 18:42:27 -0700 |
parents | 2a7f57e7efdb |
children | 6f1be9525e40 |
line wrap: on
line diff
1.1 --- a/org/touch.org Sat Feb 11 14:12:17 2012 -0700 1.2 +++ b/org/touch.org Sat Feb 11 18:42:27 2012 -0700 1.3 @@ -11,179 +11,34 @@ 1.4 Touch is critical to navigation and spatial reasoning and as such I 1.5 need a simulated version of it to give to my AI creatures. 1.6 1.7 -#+name: skin-main 1.8 +However, touch in my virtual can not exactly correspond to human touch 1.9 +because my creatures are made out of completely rigid segments that 1.10 +don't deform like human skin. 1.11 + 1.12 +Human skin has a wide array of touch sensors, each of which speciliaze 1.13 +in detecting different vibrational modes and pressures. These sensors 1.14 +can integrate a vast expanse of skin (i.e. your entire palm), or a 1.15 +tiny patch of skin at the tip of your finger. The hairs of the skin 1.16 +help detect objects before they even come into contact with the skin 1.17 +proper. 1.18 + 1.19 +Instead of measuring deformation or vibration, I surround each rigid 1.20 +part with a plenitude of hair-like objects which do not interact with 1.21 +the physical world. Physical objects can pass through them with no 1.22 +effect. The hairs are able to measure contact with other objects, and 1.23 +constantly report how much of their extent is covered. So, even though 1.24 +the creature's body parts do not deform, the hairs create a margin 1.25 +around those body parts which achieves a sense of touch which is a 1.26 +hybrid between a human's sense of deformation and sense from hairs. 1.27 + 1.28 +Implementing touch in jMonkeyEngine follows a different techinal route 1.29 +than vision and hearing. Those two senses piggybacked off 1.30 +jMonkeyEngine's 3D audio and video rendering subsystems. To simulate 1.31 +Touch, I use jMonkeyEngine's physics system to execute many small 1.32 +collision detections, one for each "hair". 1.33 + 1.34 +* Sensor Related Functions 1.35 #+begin_src clojure 1.36 -(in-ns 'cortex.touch) 1.37 - 1.38 -(defn triangles 1.39 - "Return a sequence of all the Triangles which compose a given 1.40 - Geometry." 1.41 - [#^Geometry geom] 1.42 - (let 1.43 - [mesh (.getMesh geom) 1.44 - triangles (transient [])] 1.45 - (dorun 1.46 - (for [n (range (.getTriangleCount mesh))] 1.47 - (let [tri (Triangle.)] 1.48 - (.getTriangle mesh n tri) 1.49 - ;; (.calculateNormal tri) 1.50 - ;; (.calculateCenter tri) 1.51 - (conj! triangles tri)))) 1.52 - (persistent! triangles))) 1.53 - 1.54 -(defn get-ray-origin 1.55 - "Return the origin which a Ray would have to have to be in the exact 1.56 - center of a particular Triangle in the Geometry in World 1.57 - Coordinates." 1.58 - [geom tri] 1.59 - (let [new (Vector3f.)] 1.60 - (.calculateCenter tri) 1.61 - (.localToWorld geom (.getCenter tri) new) new)) 1.62 - 1.63 -(defn get-ray-direction 1.64 - "Return the direction which a Ray would have to have to be to point 1.65 - normal to the Triangle, in coordinates relative to the center of the 1.66 - Triangle." 1.67 - [geom tri] 1.68 - (let [n+c (Vector3f.)] 1.69 - (.calculateNormal tri) 1.70 - (.calculateCenter tri) 1.71 - (.localToWorld 1.72 - geom 1.73 - (.add (.getCenter tri) (.getNormal tri)) n+c) 1.74 - (.subtract n+c (get-ray-origin geom tri)))) 1.75 - 1.76 -;; Every Mesh has many triangles, each with its own index. 1.77 -;; Every vertex has its own index as well. 1.78 - 1.79 -(defn tactile-sensor-profile 1.80 - "Return the touch-sensor distribution image in BufferedImage format, 1.81 - or nil if it does not exist." 1.82 - [#^Geometry obj] 1.83 - (if-let [image-path (meta-data obj "touch")] 1.84 - (load-image image-path))) 1.85 - 1.86 -(defn mesh-triangle 1.87 - "Get the triangle specified by triangle-index from the mesh within 1.88 - bounds." 1.89 - [#^Mesh mesh triangle-index] 1.90 - (let [scratch (Triangle.)] 1.91 - (.getTriangle mesh triangle-index scratch) 1.92 - scratch)) 1.93 - 1.94 -(defn triangle-vertex-indices 1.95 - "Get the triangle vertex indices of a given triangle from a given 1.96 - mesh." 1.97 - [#^Mesh mesh triangle-index] 1.98 - (let [indices (int-array 3)] 1.99 - (.getTriangle mesh triangle-index indices) 1.100 - (vec indices))) 1.101 - 1.102 -(defn vertex-UV-coord 1.103 - "Get the UV-coordinates of the vertex named by vertex-index" 1.104 - [#^Mesh mesh vertex-index] 1.105 - (let [UV-buffer 1.106 - (.getData 1.107 - (.getBuffer 1.108 - mesh 1.109 - VertexBuffer$Type/TexCoord))] 1.110 - [(.get UV-buffer (* vertex-index 2)) 1.111 - (.get UV-buffer (+ 1 (* vertex-index 2)))])) 1.112 - 1.113 -(defn triangle-UV-coord 1.114 - "Get the UV-cooridnates of the triangle's verticies." 1.115 - [#^Mesh mesh width height triangle-index] 1.116 - (map (fn [[u v]] (vector (* width u) (* height v))) 1.117 - (map (partial vertex-UV-coord mesh) 1.118 - (triangle-vertex-indices mesh triangle-index)))) 1.119 - 1.120 -(defn same-side? 1.121 - "Given the points p1 and p2 and the reference point ref, is point p 1.122 - on the same side of the line that goes through p1 and p2 as ref is?" 1.123 - [p1 p2 ref p] 1.124 - (<= 1.125 - 0 1.126 - (.dot 1.127 - (.cross (.subtract p2 p1) (.subtract p p1)) 1.128 - (.cross (.subtract p2 p1) (.subtract ref p1))))) 1.129 - 1.130 -(defn triangle-seq [#^Triangle tri] 1.131 - [(.get1 tri) (.get2 tri) (.get3 tri)]) 1.132 - 1.133 -(defn vector3f-seq [#^Vector3f v] 1.134 - [(.getX v) (.getY v) (.getZ v)]) 1.135 - 1.136 -(defn inside-triangle? 1.137 - "Is the point inside the triangle?" 1.138 - {:author "Dylan Holmes"} 1.139 - [#^Triangle tri #^Vector3f p] 1.140 - (let [[vert-1 vert-2 vert-3] (triangle-seq tri)] 1.141 - (and 1.142 - (same-side? vert-1 vert-2 vert-3 p) 1.143 - (same-side? vert-2 vert-3 vert-1 p) 1.144 - (same-side? vert-3 vert-1 vert-2 p)))) 1.145 - 1.146 -(defn triangle->matrix4f 1.147 - "Converts the triangle into a 4x4 matrix: The first three columns 1.148 - contain the vertices of the triangle; the last contains the unit 1.149 - normal of the triangle. The bottom row is filled with 1s." 1.150 - [#^Triangle t] 1.151 - (let [mat (Matrix4f.) 1.152 - [vert-1 vert-2 vert-3] 1.153 - ((comp vec map) #(.get t %) (range 3)) 1.154 - unit-normal (do (.calculateNormal t)(.getNormal t)) 1.155 - vertices [vert-1 vert-2 vert-3 unit-normal]] 1.156 - (dorun 1.157 - (for [row (range 4) col (range 3)] 1.158 - (do 1.159 - (.set mat col row (.get (vertices row)col)) 1.160 - (.set mat 3 row 1)))) 1.161 - mat)) 1.162 - 1.163 -(defn triangle-transformation 1.164 - "Returns the affine transformation that converts each vertex in the 1.165 - first triangle into the corresponding vertex in the second 1.166 - triangle." 1.167 - [#^Triangle tri-1 #^Triangle tri-2] 1.168 - (.mult 1.169 - (triangle->matrix4f tri-2) 1.170 - (.invert (triangle->matrix4f tri-1)))) 1.171 - 1.172 -(defn point->vector2f [[u v]] 1.173 - (Vector2f. u v)) 1.174 - 1.175 -(defn vector2f->vector3f [v] 1.176 - (Vector3f. (.getX v) (.getY v) 0)) 1.177 - 1.178 -(defn map-triangle [f #^Triangle tri] 1.179 - (Triangle. 1.180 - (f 0 (.get1 tri)) 1.181 - (f 1 (.get2 tri)) 1.182 - (f 2 (.get3 tri)))) 1.183 - 1.184 -(defn points->triangle 1.185 - "Convert a list of points into a triangle." 1.186 - [points] 1.187 - (apply #(Triangle. %1 %2 %3) 1.188 - (map (fn [point] 1.189 - (let [point (vec point)] 1.190 - (Vector3f. (get point 0 0) 1.191 - (get point 1 0) 1.192 - (get point 2 0)))) 1.193 - (take 3 points)))) 1.194 - 1.195 -(defn convex-bounds 1.196 - "Returns the smallest square containing the given vertices, as a 1.197 - vector of integers [left top width height]." 1.198 - [uv-verts] 1.199 - (let [xs (map first uv-verts) 1.200 - ys (map second uv-verts) 1.201 - x0 (Math/floor (apply min xs)) 1.202 - y0 (Math/floor (apply min ys)) 1.203 - x1 (Math/ceil (apply max xs)) 1.204 - y1 (Math/ceil (apply max ys))] 1.205 - [x0 y0 (- x1 x0) (- y1 y0)])) 1.206 - 1.207 (defn sensors-in-triangle 1.208 "Locate the touch sensors in the triangle, returning a map of their 1.209 UV and geometry-relative coordinates." 1.210 @@ -229,7 +84,198 @@ 1.211 "The location of the touch sensors in world-space coordinates." 1.212 [#^Geometry geo] 1.213 (vec (map :geometry (locate-feelers geo)))) 1.214 +#+end_src 1.215 1.216 +* Triangle Manipulation Functions 1.217 + 1.218 +#+begin_src clojure 1.219 +(defn triangles 1.220 + "Return a sequence of all the Triangles which compose a given 1.221 + Geometry." 1.222 + [#^Geometry geom] 1.223 + (let 1.224 + [mesh (.getMesh geom) 1.225 + triangles (transient [])] 1.226 + (dorun 1.227 + (for [n (range (.getTriangleCount mesh))] 1.228 + (let [tri (Triangle.)] 1.229 + (.getTriangle mesh n tri) 1.230 + ;; (.calculateNormal tri) 1.231 + ;; (.calculateCenter tri) 1.232 + (conj! triangles tri)))) 1.233 + (persistent! triangles))) 1.234 + 1.235 +(defn mesh-triangle 1.236 + "Get the triangle specified by triangle-index from the mesh within 1.237 + bounds." 1.238 + [#^Mesh mesh triangle-index] 1.239 + (let [scratch (Triangle.)] 1.240 + (.getTriangle mesh triangle-index scratch) 1.241 + scratch)) 1.242 + 1.243 +(defn triangle-vertex-indices 1.244 + "Get the triangle vertex indices of a given triangle from a given 1.245 + mesh." 1.246 + [#^Mesh mesh triangle-index] 1.247 + (let [indices (int-array 3)] 1.248 + (.getTriangle mesh triangle-index indices) 1.249 + (vec indices))) 1.250 + 1.251 +(defn vertex-UV-coord 1.252 + "Get the UV-coordinates of the vertex named by vertex-index" 1.253 + [#^Mesh mesh vertex-index] 1.254 + (let [UV-buffer 1.255 + (.getData 1.256 + (.getBuffer 1.257 + mesh 1.258 + VertexBuffer$Type/TexCoord))] 1.259 + [(.get UV-buffer (* vertex-index 2)) 1.260 + (.get UV-buffer (+ 1 (* vertex-index 2)))])) 1.261 + 1.262 +(defn triangle-UV-coord 1.263 + "Get the UV-cooridnates of the triangle's verticies." 1.264 + [#^Mesh mesh width height triangle-index] 1.265 + (map (fn [[u v]] (vector (* width u) (* height v))) 1.266 + (map (partial vertex-UV-coord mesh) 1.267 + (triangle-vertex-indices mesh triangle-index)))) 1.268 +#+end_src 1.269 + 1.270 +* Schrapnel Conversion Functions 1.271 +#+begin_src clojure 1.272 +(defn triangle-seq [#^Triangle tri] 1.273 + [(.get1 tri) (.get2 tri) (.get3 tri)]) 1.274 + 1.275 +(defn vector3f-seq [#^Vector3f v] 1.276 + [(.getX v) (.getY v) (.getZ v)]) 1.277 + 1.278 +(defn point->vector2f [[u v]] 1.279 + (Vector2f. u v)) 1.280 + 1.281 +(defn vector2f->vector3f [v] 1.282 + (Vector3f. (.getX v) (.getY v) 0)) 1.283 + 1.284 +(defn map-triangle [f #^Triangle tri] 1.285 + (Triangle. 1.286 + (f 0 (.get1 tri)) 1.287 + (f 1 (.get2 tri)) 1.288 + (f 2 (.get3 tri)))) 1.289 + 1.290 +(defn points->triangle 1.291 + "Convert a list of points into a triangle." 1.292 + [points] 1.293 + (apply #(Triangle. %1 %2 %3) 1.294 + (map (fn [point] 1.295 + (let [point (vec point)] 1.296 + (Vector3f. (get point 0 0) 1.297 + (get point 1 0) 1.298 + (get point 2 0)))) 1.299 + (take 3 points)))) 1.300 +#+end_src 1.301 + 1.302 +* Triangle Affine Transforms 1.303 + 1.304 +#+begin_src clojure 1.305 +(defn triangle->matrix4f 1.306 + "Converts the triangle into a 4x4 matrix: The first three columns 1.307 + contain the vertices of the triangle; the last contains the unit 1.308 + normal of the triangle. The bottom row is filled with 1s." 1.309 + [#^Triangle t] 1.310 + (let [mat (Matrix4f.) 1.311 + [vert-1 vert-2 vert-3] 1.312 + ((comp vec map) #(.get t %) (range 3)) 1.313 + unit-normal (do (.calculateNormal t)(.getNormal t)) 1.314 + vertices [vert-1 vert-2 vert-3 unit-normal]] 1.315 + (dorun 1.316 + (for [row (range 4) col (range 3)] 1.317 + (do 1.318 + (.set mat col row (.get (vertices row)col)) 1.319 + (.set mat 3 row 1)))) 1.320 + mat)) 1.321 + 1.322 +(defn triangle-transformation 1.323 + "Returns the affine transformation that converts each vertex in the 1.324 + first triangle into the corresponding vertex in the second 1.325 + triangle." 1.326 + [#^Triangle tri-1 #^Triangle tri-2] 1.327 + (.mult 1.328 + (triangle->matrix4f tri-2) 1.329 + (.invert (triangle->matrix4f tri-1)))) 1.330 +#+end_src 1.331 + 1.332 +* Blender Meta-Data 1.333 + 1.334 +#+begin_src clojure 1.335 +(defn tactile-sensor-profile 1.336 + "Return the touch-sensor distribution image in BufferedImage format, 1.337 + or nil if it does not exist." 1.338 + [#^Geometry obj] 1.339 + (if-let [image-path (meta-data obj "touch")] 1.340 + (load-image image-path))) 1.341 +#+end_src 1.342 + 1.343 +* Physics Collision Objects 1.344 +#+begin_src clojure 1.345 +(defn get-ray-origin 1.346 + "Return the origin which a Ray would have to have to be in the exact 1.347 + center of a particular Triangle in the Geometry in World 1.348 + Coordinates." 1.349 + [geom tri] 1.350 + (let [new (Vector3f.)] 1.351 + (.calculateCenter tri) 1.352 + (.localToWorld geom (.getCenter tri) new) new)) 1.353 + 1.354 +(defn get-ray-direction 1.355 + "Return the direction which a Ray would have to have to be to point 1.356 + normal to the Triangle, in coordinates relative to the center of the 1.357 + Triangle." 1.358 + [geom tri] 1.359 + (let [n+c (Vector3f.)] 1.360 + (.calculateNormal tri) 1.361 + (.calculateCenter tri) 1.362 + (.localToWorld 1.363 + geom 1.364 + (.add (.getCenter tri) (.getNormal tri)) n+c) 1.365 + (.subtract n+c (get-ray-origin geom tri)))) 1.366 +#+end_src 1.367 + 1.368 +* Triangle Boundaries 1.369 +#+begin_src clojure 1.370 +(defn same-side? 1.371 + "Given the points p1 and p2 and the reference point ref, is point p 1.372 + on the same side of the line that goes through p1 and p2 as ref is?" 1.373 + [p1 p2 ref p] 1.374 + (<= 1.375 + 0 1.376 + (.dot 1.377 + (.cross (.subtract p2 p1) (.subtract p p1)) 1.378 + (.cross (.subtract p2 p1) (.subtract ref p1))))) 1.379 + 1.380 +(defn inside-triangle? 1.381 + "Is the point inside the triangle?" 1.382 + {:author "Dylan Holmes"} 1.383 + [#^Triangle tri #^Vector3f p] 1.384 + (let [[vert-1 vert-2 vert-3] (triangle-seq tri)] 1.385 + (and 1.386 + (same-side? vert-1 vert-2 vert-3 p) 1.387 + (same-side? vert-2 vert-3 vert-1 p) 1.388 + (same-side? vert-3 vert-1 vert-2 p)))) 1.389 + 1.390 +(defn convex-bounds 1.391 + "Returns the smallest square containing the given vertices, as a 1.392 + vector of integers [left top width height]." 1.393 + [uv-verts] 1.394 + (let [xs (map first uv-verts) 1.395 + ys (map second uv-verts) 1.396 + x0 (Math/floor (apply min xs)) 1.397 + y0 (Math/floor (apply min ys)) 1.398 + x1 (Math/ceil (apply max xs)) 1.399 + y1 (Math/ceil (apply max ys))] 1.400 + [x0 y0 (- x1 x0) (- y1 y0)])) 1.401 +#+end_src 1.402 + 1.403 +* Skin Creation 1.404 + 1.405 +#+begin_src clojure 1.406 (defn touch-fn 1.407 "Returns a function which returns tactile sensory data when called 1.408 inside a running simulation." 1.409 @@ -283,7 +329,11 @@ 1.410 (map touch-fn 1.411 (filter #(isa? (class %) Geometry) 1.412 (node-seq creature))))) 1.413 +#+end_src 1.414 1.415 +* Visualizing Touch 1.416 + 1.417 +#+begin_src clojure 1.418 (defn view-touch 1.419 "Creates a function which accepts a list of touch sensor-data and 1.420 displays each element to the screen." 1.421 @@ -316,6 +366,13 @@ 1.422 (:import (com.jme3.math Triangle Vector3f Vector2f Ray Matrix4f))) 1.423 #+end_src 1.424 1.425 +;; Every Mesh has many triangles, each with its own index. 1.426 +;; Every vertex has its own index as well. 1.427 + 1.428 +* Source Listing 1.429 +* Next 1.430 + 1.431 + 1.432 * COMMENT Code Generation 1.433 #+begin_src clojure :tangle ../src/cortex/touch.clj 1.434 <<skin-main>>