Mercurial > cortex
view org/skin.org @ 37:eeba17a4bd54
cleaning up the touch code
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Thu, 03 Nov 2011 09:52:34 -0700 |
parents | 97703c7f020e |
children | 2ce7400825c2 |
line wrap: on
line source
1 #+title: Simulated Sense of Touch2 #+author: Robert McIntyre3 #+email: rlm@mit.edu4 #+description: Simulated touch for AI research using JMonkeyEngine and clojure.5 #+keywords: simulation, tactile sense, jMonkeyEngine3, clojure6 #+SETUPFILE: ../../aurellem/org/setup.org7 #+INCLUDE: ../../aurellem/org/level-0.org9 * Touch11 My creatures need to be able to feel their environments. The idea here12 is to thousands of small /touch receptors/ along the geometries which13 make up the creature's body. The number of touch receptors in a given14 area is determined by how complicated that area is, as determined by15 the total number of triangles in that region. This way, complicated16 regions like the hands/face, etc. get more touch receptors than17 simpler areas of the body.19 #+srcname: skin-main20 #+begin_src clojure21 (ns cortex.touch22 "Simulate the sense of touch in jMonkeyEngine3. Enables any Geometry23 to be outfitted with touch sensors with density proportional to the24 density of triangles along the surface of the Geometry. Enables a25 Geometry to know what parts of itself are touching nearby objects."26 {:author "Robert McIntyre"}27 (:use (cortex world util))28 (:import com.jme3.scene.Geometry)29 (:import com.jme3.collision.CollisionResult)30 (:import com.jme3.math Triangle Vector3f Ray))32 (defn triangles33 "Return a sequence of all the Triangles which compose a given34 Geometry."35 [#^Geometry geom]36 (let37 [mesh (.getMesh geom)38 triangles (transient [])]39 (dorun40 (for [n (range (.getTriangleCount mesh))]41 (let [tri (Triangle.)]42 (.getTriangle mesh n tri)43 ;; (.calculateNormal tri)44 ;; (.calculateCenter tri)45 (conj! triangles tri))))46 (persistent! triangles)))48 (defn get-ray-origin49 "Return the origin which a Ray would have to have to be in the exact50 center of a particular Triangle in the Geometry in World51 Coordinates."52 [geom tri]53 (let [new (Vector3f.)]54 (.calculateCenter tri)55 (.localToWorld geom (.getCenter tri) new) new))57 (defn get-ray-direction58 "Return the direction which a Ray would have to have to be in the59 exact center of a particular Triangle in the Geometry, pointing60 normal to the Triangle, in coordinates relative to the center of the61 Triangle."62 [geom tri]63 (let [n+c (Vector3f.)]64 (.calculateNormal tri)65 (.calculateCenter tri)66 (.localToWorld67 geom68 (.add (.getCenter tri) (.getNormal tri)) n+c)69 (.subtract n+c (get-ray-origin geom tri))))71 (defn normal-rays72 "For each Triangle which comprises the Geometry, returns a Ray which73 is centered on that Triangle, points outward in a normal direction,74 and extends for =limit= distance."75 [limit #^Geometry geom]76 (vec77 (map78 (fn [tri]79 (doto80 (Ray. (get-ray-origin geom tri)81 (get-ray-direction geom tri))82 (.setLimit limit)))83 (triangles geom))))85 (defn touch-percieve86 "Augment a Geometry with the sense of touch. Returns a sequence of87 non-negative integers, one for each triangle, with the value of the88 integer describing how many objects a ray of length =limit=, normal89 to the triangle and originating from its center, encountered. The90 Geometry itself is not counted among the results."91 [limit geom node]92 (let [normals (normal-rays limit geom)]93 (doall94 (for [ray normals]95 (do96 (let [results (CollisionResults.)]97 (.collideWith node ray results)98 (let [touch-objects99 (set (filter #(not (= geom %))100 (map #(.getGeometry %) results)))]101 (count touch-objects))))))))102 #+end_src105 * Example107 #+begin_src clojure110 (defn ray-origin-debug111 [ray color]112 (make-shape113 (assoc base-shape114 :shape (Sphere. 5 5 0.05)115 :name "arrow"116 :color color117 :texture false118 :physical? false119 :position120 (.getOrigin ray))))122 (defn ray-debug [ray color]123 (make-shape124 (assoc125 base-shape126 :name "debug-ray"127 :physical? false128 :shape (com.jme3.scene.shape.Line.129 (.getOrigin ray)130 (.add131 (.getOrigin ray)132 (.mult (.getDirection ray)133 (float (.getLimit ray))))))))136 (defn contact-color [contacts]137 (case contacts138 0 ColorRGBA/Gray139 1 ColorRGBA/Red140 2 ColorRGBA/Green141 3 ColorRGBA/Yellow142 4 ColorRGBA/Orange143 5 ColorRGBA/Red144 6 ColorRGBA/Magenta145 7 ColorRGBA/Pink146 8 ColorRGBA/White))148 (defn update-ray-debug [node ray contacts]149 (let [origin (.getChild node 0)]150 (.setLocalTranslation origin (.getOrigin ray))151 (.setColor (.getMaterial origin) "Color" (contact-color contacts))))153 (defn init-node154 [debug-node rays]155 (println-repl "Init touch debug node.")156 (.detachAllChildren debug-node)157 (dorun158 (for [ray rays]159 (do160 (.attachChild161 debug-node162 (doto (Node.)163 (.attachChild (ray-origin-debug ray ColorRGBA/Gray))164 (.attachChild (ray-debug ray ColorRGBA/Gray))165 ))))))167 (defn manage-ray-debug-node [debug-node geom touch-data limit]168 (let [rays (normal-rays limit geom)]169 (if (not= (count (.getChildren debug-node)) (count touch-data))170 (init-node debug-node rays))171 (dorun172 (for [n (range (count touch-data))]173 (update-ray-debug174 (.getChild debug-node n) (nth rays n) (nth touch-data n))))))178 (defn no-logging []179 (.setLevel (Logger/getLogger "com.jme3") Level/OFF))181 (defn set-accuracy [world new-accuracy]182 (let [physics-manager (.getState (.getStateManager world) BulletAppState)]183 (.setAccuracy (.getPhysicsSpace physics-manager) (float new-accuracy))))185 (defn transparent-sphere []186 (doto187 (make-shape188 (merge base-shape189 {:position (Vector3f. 0 2 0)190 :name "the blob."191 :material "Common/MatDefs/Misc/Unshaded.j3md"192 :texture "Textures/purpleWisp.png"193 :physical? true194 :mass 70195 :color ColorRGBA/Blue196 :shape (Sphere. 10 10 1)}))197 (-> (.getMaterial)198 (.getAdditionalRenderState)199 (.setBlendMode RenderState$BlendMode/Alpha))200 (.setQueueBucket RenderQueue$Bucket/Transparent)))202 (defn transparent-box []203 (doto204 (make-shape205 (merge base-shape206 {:position (Vector3f. 0 2 0)207 :name "box"208 :material "Common/MatDefs/Misc/Unshaded.j3md"209 :texture "Textures/purpleWisp.png"210 :physical? true211 :mass 70212 :color ColorRGBA/Blue213 :shape (Box. 1 1 1)}))214 (-> (.getMaterial)215 (.getAdditionalRenderState)216 (.setBlendMode RenderState$BlendMode/Alpha))217 (.setQueueBucket RenderQueue$Bucket/Transparent)))219 (defn transparent-floor []220 (doto221 (box 5 0.2 5 :mass 0 :position (Vector3f. 0 -2 0)222 :material "Common/MatDefs/Misc/Unshaded.j3md"223 :texture "Textures/redWisp.png"224 :name "floor")225 (-> (.getMaterial)226 (.getAdditionalRenderState)227 (.setBlendMode RenderState$BlendMode/Alpha))228 (.setQueueBucket RenderQueue$Bucket/Transparent)))230 (defn test-skin []231 (let [b232 ;;(transparent-box)233 (transparent-sphere)234 ;;(sphere)235 f (transparent-floor)236 debug-node (Node.)237 node (doto (Node.) (.attachChild b) (.attachChild f))238 root-node (doto (Node.) (.attachChild node)239 (.attachChild debug-node))240 ]242 (world243 root-node244 {"key-return" (fire-cannon-ball node)}245 (fn [world]246 ;; (Capture/SimpleCaptureVideo247 ;; world248 ;; (file-str "/home/r/proj/cortex/tmp/blob.avi"))249 ;; (no-logging)250 ;;(enable-debug world)251 ;; (set-accuracy world (/ 1 60))252 )254 (fn [& _]255 (let [sensitivity 0.2256 touch-data (touch-percieve sensitivity b node)]257 (manage-ray-debug-node debug-node b touch-data sensitivity)258 )259 (Thread/sleep 10)260 ))))263 #+end_src269 * COMMENT code generation270 #+begin_src clojure :tangle ../src/cortex/touch.clj :noweb yes271 <<skin-main>>272 #+end_src