view org/skin.org @ 40:bc93abad23ee

moved usefull functions to util
author Robert McIntyre <rlm@mit.edu>
date Thu, 03 Nov 2011 10:10:55 -0700
parents 2ce7400825c2
children cce471a4108a
line wrap: on
line source
1 #+title: Simulated Sense of Touch
2 #+author: Robert McIntyre
3 #+email: rlm@mit.edu
4 #+description: Simulated touch for AI research using JMonkeyEngine and clojure.
5 #+keywords: simulation, tactile sense, jMonkeyEngine3, clojure
6 #+SETUPFILE: ../../aurellem/org/setup.org
7 #+INCLUDE: ../../aurellem/org/level-0.org
10 * Touch
12 My creatures need to be able to feel their environments. The idea here
13 is to thousands of small /touch receptors/ along the geometries which
14 make up the creature's body. The number of touch receptors in a given
15 area is determined by how complicated that area is, as determined by
16 the total number of triangles in that region. This way, complicated
17 regions like the hands/face, etc. get more touch receptors than
18 simpler areas of the body.
20 #+srcname: skin-main
21 #+begin_src clojure
22 (ns cortex.touch
23 "Simulate the sense of touch in jMonkeyEngine3. Enables any Geometry
24 to be outfitted with touch sensors with density proportional to the
25 density of triangles along the surface of the Geometry. Enables a
26 Geometry to know what parts of itself are touching nearby objects."
27 {:author "Robert McIntyre"}
28 (:use (cortex world util))
29 (:import com.jme3.scene.Geometry)
30 (:import com.jme3.collision.CollisionResults)
31 (:import (com.jme3.math Triangle Vector3f Ray)))
33 (defn triangles
34 "Return a sequence of all the Triangles which compose a given
35 Geometry."
36 [#^Geometry geom]
37 (let
38 [mesh (.getMesh geom)
39 triangles (transient [])]
40 (dorun
41 (for [n (range (.getTriangleCount mesh))]
42 (let [tri (Triangle.)]
43 (.getTriangle mesh n tri)
44 ;; (.calculateNormal tri)
45 ;; (.calculateCenter tri)
46 (conj! triangles tri))))
47 (persistent! triangles)))
49 (defn get-ray-origin
50 "Return the origin which a Ray would have to have to be in the exact
51 center of a particular Triangle in the Geometry in World
52 Coordinates."
53 [geom tri]
54 (let [new (Vector3f.)]
55 (.calculateCenter tri)
56 (.localToWorld geom (.getCenter tri) new) new))
58 (defn get-ray-direction
59 "Return the direction which a Ray would have to have to be in the
60 exact center of a particular Triangle in the Geometry, pointing
61 normal to the Triangle, in coordinates relative to the center of the
62 Triangle."
63 [geom tri]
64 (let [n+c (Vector3f.)]
65 (.calculateNormal tri)
66 (.calculateCenter tri)
67 (.localToWorld
68 geom
69 (.add (.getCenter tri) (.getNormal tri)) n+c)
70 (.subtract n+c (get-ray-origin geom tri))))
72 (defn normal-rays
73 "For each Triangle which comprises the Geometry, returns a Ray which
74 is centered on that Triangle, points outward in a normal direction,
75 and extends for =limit= distance."
76 [limit #^Geometry geom]
77 (vec
78 (map
79 (fn [tri]
80 (doto
81 (Ray. (get-ray-origin geom tri)
82 (get-ray-direction geom tri))
83 (.setLimit limit)))
84 (triangles geom))))
86 (defn touch-percieve
87 "Augment a Geometry with the sense of touch. Returns a sequence of
88 non-negative integers, one for each triangle, with the value of the
89 integer describing how many objects a ray of length =limit=, normal
90 to the triangle and originating from its center, encountered. The
91 Geometry itself is not counted among the results."
92 [limit geom node]
93 (let [normals (normal-rays limit geom)]
94 (doall
95 (for [ray normals]
96 (do
97 (let [results (CollisionResults.)]
98 (.collideWith node ray results)
99 (let [touch-objects
100 (set (filter #(not (= geom %))
101 (map #(.getGeometry %) results)))]
102 (count touch-objects))))))))
103 #+end_src
106 * Example
108 #+srcname: touch-test
109 #+begin_src clojure
110 (ns test.touch
111 (:use (cortex world util touch)))
113 (cortex.import/mega-import-jme3)
115 (use 'hello.brick-wall)
118 (defn ray-origin-debug
119 [ray color]
120 (make-shape
121 (assoc base-shape
122 :shape (Sphere. 5 5 0.05)
123 :name "arrow"
124 :color color
125 :texture false
126 :physical? false
127 :position
128 (.getOrigin ray))))
130 (defn ray-debug [ray color]
131 (make-shape
132 (assoc
133 base-shape
134 :name "debug-ray"
135 :physical? false
136 :shape (com.jme3.scene.shape.Line.
137 (.getOrigin ray)
138 (.add
139 (.getOrigin ray)
140 (.mult (.getDirection ray)
141 (float (.getLimit ray))))))))
144 (defn contact-color [contacts]
145 (case contacts
146 0 ColorRGBA/Gray
147 1 ColorRGBA/Red
148 2 ColorRGBA/Green
149 3 ColorRGBA/Yellow
150 4 ColorRGBA/Orange
151 5 ColorRGBA/Red
152 6 ColorRGBA/Magenta
153 7 ColorRGBA/Pink
154 8 ColorRGBA/White))
156 (defn update-ray-debug [node ray contacts]
157 (let [origin (.getChild node 0)]
158 (.setLocalTranslation origin (.getOrigin ray))
159 (.setColor (.getMaterial origin) "Color" (contact-color contacts))))
161 (defn init-node
162 [debug-node rays]
163 (println-repl "Init touch debug node.")
164 (.detachAllChildren debug-node)
165 (dorun
166 (for [ray rays]
167 (do
168 (.attachChild
169 debug-node
170 (doto (Node.)
171 (.attachChild (ray-origin-debug ray ColorRGBA/Gray))
172 (.attachChild (ray-debug ray ColorRGBA/Gray))
173 ))))))
175 (defn manage-ray-debug-node [debug-node geom touch-data limit]
176 (let [rays (normal-rays limit geom)]
177 (if (not= (count (.getChildren debug-node)) (count touch-data))
178 (init-node debug-node rays))
179 (dorun
180 (for [n (range (count touch-data))]
181 (update-ray-debug
182 (.getChild debug-node n) (nth rays n) (nth touch-data n))))))
184 (defn transparent-sphere []
185 (doto
186 (make-shape
187 (merge base-shape
188 {:position (Vector3f. 0 2 0)
189 :name "the blob."
190 :material "Common/MatDefs/Misc/Unshaded.j3md"
191 :texture "Textures/purpleWisp.png"
192 :physical? true
193 :mass 70
194 :color ColorRGBA/Blue
195 :shape (Sphere. 10 10 1)}))
196 (-> (.getMaterial)
197 (.getAdditionalRenderState)
198 (.setBlendMode RenderState$BlendMode/Alpha))
199 (.setQueueBucket RenderQueue$Bucket/Transparent)))
201 (defn transparent-box []
202 (doto
203 (make-shape
204 (merge base-shape
205 {:position (Vector3f. 0 2 0)
206 :name "box"
207 :material "Common/MatDefs/Misc/Unshaded.j3md"
208 :texture "Textures/purpleWisp.png"
209 :physical? true
210 :mass 70
211 :color ColorRGBA/Blue
212 :shape (Box. 1 1 1)}))
213 (-> (.getMaterial)
214 (.getAdditionalRenderState)
215 (.setBlendMode RenderState$BlendMode/Alpha))
216 (.setQueueBucket RenderQueue$Bucket/Transparent)))
218 (defn transparent-floor []
219 (doto
220 (box 5 0.2 5 :mass 0 :position (Vector3f. 0 -2 0)
221 :material "Common/MatDefs/Misc/Unshaded.j3md"
222 :texture "Textures/redWisp.png"
223 :name "floor")
224 (-> (.getMaterial)
225 (.getAdditionalRenderState)
226 (.setBlendMode RenderState$BlendMode/Alpha))
227 (.setQueueBucket RenderQueue$Bucket/Transparent)))
229 (defn test-skin []
230 (let [b
231 ;;(transparent-box)
232 (transparent-sphere)
233 ;;(sphere)
234 f (transparent-floor)
235 debug-node (Node.)
236 node (doto (Node.) (.attachChild b) (.attachChild f))
237 root-node (doto (Node.) (.attachChild node)
238 (.attachChild debug-node))
239 ]
241 (world
242 root-node
243 {"key-return" (fire-cannon-ball node)}
244 (fn [world]
245 ;; (Capture/SimpleCaptureVideo
246 ;; world
247 ;; (file-str "/home/r/proj/cortex/tmp/blob.avi"))
248 ;; (no-logging)
249 ;;(enable-debug world)
250 ;; (set-accuracy world (/ 1 60))
251 )
253 (fn [& _]
254 (let [sensitivity 0.2
255 touch-data (touch-percieve sensitivity b node)]
256 (manage-ray-debug-node debug-node b touch-data sensitivity)
257 )
258 (Thread/sleep 10)
259 ))))
262 #+end_src
268 * COMMENT code generation
269 #+begin_src clojure :tangle ../src/cortex/touch.clj
270 <<skin-main>>
271 #+end_src
273 #+begin_src clojure :tangle ../src/test/touch.clj
274 <<touch-test>>
275 #+end_src