# HG changeset patch # User Robert McIntyre # Date 1329081297 25200 # Node ID f33fec68f775365735e4d1a464b037b52d8e8775 # Parent a7f26a07407105fce36055e48bea2e70f3aee975 touch has been restored, with some very slight speed improvements, and now with much less code diff -r a7f26a074071 -r f33fec68f775 org/touch.org --- a/org/touch.org Sun Feb 12 13:48:28 2012 -0700 +++ b/org/touch.org Sun Feb 12 14:14:57 2012 -0700 @@ -77,15 +77,7 @@ * Skin Creation -* TODO get the actual lengths for each hair - -#+begin_src clojure -pixel-triangles - xyz-triangles - conversions (map triangles->affine-transform pixel-triangles - xyz-triangles) - -#+end_src +* TODO get the actual lengths for each feeler =(touch-kernel)= generates the functions which implement the sense of @@ -119,14 +111,6 @@ - Generate some sort of topology for the sensors. =(touch-topology)= -#+begin_src clojure - - - - -#+end_src - - #+name: kernel #+begin_src clojure @@ -134,77 +118,38 @@ (declare touch-topology feelers set-ray) -(defn set-ray [#^Ray ray #^Matrix4f transform - #^Vector3f origin #^Vector3f tip - length] - (.setOrigin ray (.mult transform origin)) - (.setDirection ray (.subtract - (.mult transform tip) - (.getOrigin ray))) - (.setLimit ray length) - ray) - +(defn set-ray [#^Ray ray #^Matrix4f transform #^Vector3f origin + #^Vector3f tip length] + ;; Doing everything locally recduces garbage collection by enough to + ;; be worth it. + (.mult transform origin (.getOrigin ray)) + + (.mult transform tip (.getDirection ray)) + (.subtractLocal (.getDirection ray) (.getOrigin ray)) + (.setLimit ray length)) (defn touch-kernel "Constructs a function which will return tactile sensory data from 'geo when called from inside a running simulation" [#^Geometry geo] - (let [profile (tactile-sensor-profile geo) - ray-reference-origins (feeler-origins geo profile) - ray-reference-tips (feeler-tips geo profile) - ray-lengths (repeat 9000 0.1) - current-rays (map (fn [] (Ray.)) ray-reference-origins) - topology (touch-topology geo profile)] - (if (empty? ray-reference-origins) nil - (fn [node] - (let [transform (.getWorldMatrix geo)] - (dorun - (map (fn [ray ref-origin ref-tip length] - (set-ray ray transform ref-origin ref-tip length)) - current-rays ray-reference-origins - ray-reference-tips ray-lengths)) - (vector - topology - (vec - (for [ray current-rays] - (do - (let [results (CollisionResults.)] - (.collideWith node ray results) - (let [touch-objects - (filter #(not (= geo (.getGeometry %))) - results)] - [(if (empty? touch-objects) - (.getLimit ray) - (.getDistance (first touch-objects))) - (.getLimit ray)]))))))))))) - -(defn touch-kernel* - "Returns a function which returns tactile sensory data when called - inside a running simulation." - [#^Geometry geo] - (let [feeler-coords (feeler-coordinates geo) - tris (triangles geo) - limit (tactile-scale geo)] - (if (empty? (touch-topology geo)) - nil + (if-let + [profile (tactile-sensor-profile geo)] + (let [ray-reference-origins (feeler-origins geo profile) + ray-reference-tips (feeler-tips geo profile) + ray-lengths (repeat 9000 0.1) + current-rays (map (fn [_] (Ray.)) ray-reference-origins) + topology (touch-topology geo profile)] (fn [node] - (let [sensor-origins - (map - #(map (partial local-to-world geo) %) - feeler-coords) - triangle-normals - (map (partial get-ray-direction geo) - tris) - rays - (flatten - (map (fn [origins norm] - (map #(doto (Ray. % norm) - (.setLimit limit)) origins)) - sensor-origins triangle-normals))] + (let [transform (.getWorldMatrix geo)] + (dorun + (map (fn [ray ref-origin ref-tip length] + (set-ray ray transform ref-origin ref-tip length)) + current-rays ray-reference-origins + ray-reference-tips ray-lengths)) (vector - (touch-topology geo) + topology (vec - (for [ray rays] + (for [ray current-rays] (do (let [results (CollisionResults.)] (.collideWith node ray results) @@ -212,8 +157,9 @@ (filter #(not (= geo (.getGeometry %))) results)] [(if (empty? touch-objects) - limit (.getDistance (first touch-objects))) - limit]))))))))))) + (.getLimit ray) + (.getDistance (first touch-objects))) + (.getLimit ray)]))))))))))) (defn touch! "Endow the creature with the sense of touch. Returns a sequence of @@ -227,6 +173,9 @@ (node-seq creature))))) #+end_src +#+results: kernel +: #'cortex.touch/touch! + * Sensor Related Functions These functions analyze the touch-sensor-profile image convert the @@ -279,59 +228,9 @@ (defn touch-topology [#^Geometry geo image] - (collapse (feeler-pixel-coords geo image))) - - -(defn sensors-in-triangle - "Locate the touch sensors in the triangle, returning a map of their - UV and geometry-relative coordinates." - [image mesh tri-index] - (let [width (.getWidth image) - height (.getHeight image) - UV-vertex-coords (triangle-UV-coord mesh width height tri-index) - bounds (convex-bounds UV-vertex-coords) - - cutout-triangle (points->triangle UV-vertex-coords) - UV-sensor-coords - (filter (comp (partial inside-triangle? cutout-triangle) - (fn [[u v]] (Vector3f. u v 0))) - (white-coordinates image bounds)) - UV->geometry (triangle-transformation - cutout-triangle - (mesh-triangle mesh tri-index)) - geometry-sensor-coords - (map (fn [[u v]] (.mult UV->geometry (Vector3f. u v 0))) - UV-sensor-coords)] - {:UV UV-sensor-coords :geometry geometry-sensor-coords})) - -(defn-memo locate-feelers - "Search the geometry's tactile UV profile for touch sensors, - returning their positions in geometry-relative coordinates." - [#^Geometry geo] - (let [mesh (.getMesh geo) - num-triangles (.getTriangleCount mesh)] - (if-let [image (tactile-sensor-profile geo)] - (map - (partial sensors-in-triangle image mesh) - (range num-triangles)) - (repeat (.getTriangleCount mesh) {:UV nil :geometry nil})))) - -(defn-memo touch-topology - "Return a sequence of vectors of the form [x y] describing the - \"topology\" of the tactile sensors. Points that are close together - in the touch-topology are generally close together in the simulation." - [#^Gemoetry geo] - (vec (collapse (reduce concat (map :UV (locate-feelers geo)))))) - -(defn-memo feeler-coordinates - "The location of the touch sensors in world-space coordinates." - [#^Geometry geo] - (vec (map :geometry (locate-feelers geo)))) + (collapse (reduce concat (feeler-pixel-coords geo image)))) #+end_src - - - * Visualizing Touch #+name: visualization #+begin_src clojure @@ -457,6 +356,8 @@ #+name: triangles-3 #+begin_src clojure +(in-ns 'cortex.touch) + (defn triangle->matrix4f "Converts the triangle into a 4x4 matrix: The first three columns contain the vertices of the triangle; the last contains the unit @@ -492,32 +393,6 @@ functions make this easy. If these classes implemented =Iterable= then this code would not be necessary. Hopefully they will in the future. -#+name: triangles-2 -#+begin_src clojure -(defn point->vector2f [[u v]] - (Vector2f. u v)) - -(defn vector2f->vector3f [v] - (Vector3f. (.getX v) (.getY v) 0)) - -(defn map-triangle [f #^Triangle tri] - (Triangle. - (f 0 (.get1 tri)) - (f 1 (.get2 tri)) - (f 2 (.get3 tri)))) - -(defn points->triangle - "Convert a list of points into a triangle." - [points] - (apply #(Triangle. %1 %2 %3) - (map (fn [point] - (let [point (vec point)] - (Vector3f. (get point 0 0) - (get point 1 0) - (get point 2 0)))) - (take 3 points)))) -#+end_src - * Triangle Boundaries @@ -563,39 +438,11 @@ (same-side? vert-3 vert-1 vert-2 p)))) #+end_src -#+results: triangles-4 -: #'cortex.touch/inside-triangle? - - * Physics Collision Objects The "hairs" are actually =Rays= which extend from a point on a =Triangle= in the =Mesh= normal to the =Triangle's= surface. -#+name: rays -#+begin_src clojure -(defn get-ray-origin - "Return the origin which a Ray would have to have to be in the exact - center of a particular Triangle in the Geometry in World - Coordinates." - [geom tri] - (let [new (Vector3f.)] - (.calculateCenter tri) - (.localToWorld geom (.getCenter tri) new) new)) - -(defn get-ray-direction - "Return the direction which a Ray would have to have to be to point - normal to the Triangle, in coordinates relative to the center of the - Triangle." - [geom tri] - (let [n+c (Vector3f.)] - (.calculateNormal tri) - (.calculateCenter tri) - (.localToWorld - geom - (.add (.getCenter tri) (.getNormal tri)) n+c) - (.subtract n+c (get-ray-origin geom tri)))) -#+end_src * Headers #+name: touch-header @@ -636,7 +483,12 @@ (light-up-everything world)) (fn [world tpf] - (touch-display (map #(% (.getRootNode world)) touch)))))) + + + (dorun (map #(% (.getRootNode world)) touch)) + + + )))) #+end_src * Source Listing * Next @@ -647,11 +499,9 @@ <> <> <> -<> <> <> <> -<> <> <> #+end_src