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