Mercurial > cortex
diff org/test-creature.org @ 151:aaacf087504c
refactored vision code
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Fri, 03 Feb 2012 05:52:18 -0700 |
parents | 1e6beed24cec |
children | c95179907951 |
line wrap: on
line diff
1.1 --- a/org/test-creature.org Fri Feb 03 05:08:45 2012 -0700 1.2 +++ b/org/test-creature.org Fri Feb 03 05:52:18 2012 -0700 1.3 @@ -147,7 +147,7 @@ 1.4 ;; TODO remove this! 1.5 (require 'cortex.import) 1.6 (cortex.import/mega-import-jme3) 1.7 -(use '(cortex world util body hearing touch vision)) 1.8 +(use '(cortex world util body hearing touch vision sense)) 1.9 1.10 (rlm.rlm-commands/help) 1.11 (import java.awt.image.BufferedImage) 1.12 @@ -160,83 +160,6 @@ 1.13 (declare joint-create) 1.14 (use 'clojure.contrib.def) 1.15 1.16 -(defn points->image 1.17 - "Take a sparse collection of points and visuliaze it as a 1.18 - BufferedImage." 1.19 - 1.20 - ;; TODO maybe parallelize this since it's easy 1.21 - 1.22 - [points] 1.23 - (if (empty? points) 1.24 - (BufferedImage. 1 1 BufferedImage/TYPE_BYTE_BINARY) 1.25 - (let [xs (vec (map first points)) 1.26 - ys (vec (map second points)) 1.27 - x0 (apply min xs) 1.28 - y0 (apply min ys) 1.29 - width (- (apply max xs) x0) 1.30 - height (- (apply max ys) y0) 1.31 - image (BufferedImage. (inc width) (inc height) 1.32 - BufferedImage/TYPE_INT_RGB)] 1.33 - (dorun 1.34 - (for [x (range (.getWidth image)) 1.35 - y (range (.getHeight image))] 1.36 - (.setRGB image x y 0xFF0000))) 1.37 - (dorun 1.38 - (for [index (range (count points))] 1.39 - (.setRGB image (- (xs index) x0) (- (ys index) y0) -1))) 1.40 - 1.41 - image))) 1.42 - 1.43 -(defn average [coll] 1.44 - (/ (reduce + coll) (count coll))) 1.45 - 1.46 -(defn collapse-1d 1.47 - "One dimensional analogue of collapse" 1.48 - [center line] 1.49 - (let [length (count line) 1.50 - num-above (count (filter (partial < center) line)) 1.51 - num-below (- length num-above)] 1.52 - (range (- center num-below) 1.53 - (+ center num-above)))) 1.54 - 1.55 -(defn collapse 1.56 - "Take a set of pairs of integers and collapse them into a 1.57 - contigous bitmap." 1.58 - [points] 1.59 - (if (empty? points) [] 1.60 - (let 1.61 - [num-points (count points) 1.62 - center (vector 1.63 - (int (average (map first points))) 1.64 - (int (average (map first points)))) 1.65 - flattened 1.66 - (reduce 1.67 - concat 1.68 - (map 1.69 - (fn [column] 1.70 - (map vector 1.71 - (map first column) 1.72 - (collapse-1d (second center) 1.73 - (map second column)))) 1.74 - (partition-by first (sort-by first points)))) 1.75 - squeezed 1.76 - (reduce 1.77 - concat 1.78 - (map 1.79 - (fn [row] 1.80 - (map vector 1.81 - (collapse-1d (first center) 1.82 - (map first row)) 1.83 - (map second row))) 1.84 - (partition-by second (sort-by second flattened)))) 1.85 - relocate 1.86 - (let [min-x (apply min (map first squeezed)) 1.87 - min-y (apply min (map second squeezed))] 1.88 - (map (fn [[x y]] 1.89 - [(- x min-x) 1.90 - (- y min-y)]) 1.91 - squeezed))] 1.92 - relocate))) 1.93 1.94 (defn load-bullet [] 1.95 (let [sim (world (Node.) {} no-op no-op)] 1.96 @@ -254,11 +177,6 @@ 1.97 (.registerLoader BlenderModelLoader (into-array String ["blend"]))) 1.98 model)) 1.99 1.100 -(defn meta-data [blender-node key] 1.101 - (if-let [data (.getUserData blender-node "properties")] 1.102 - (.findValue data key) 1.103 - nil)) 1.104 - 1.105 (defn blender-to-jme 1.106 "Convert from Blender coordinates to JME coordinates" 1.107 [#^Vector3f in] 1.108 @@ -474,33 +392,7 @@ 1.109 image-path)) 1.110 false false 0))) 1.111 1.112 -(import ij.process.ImageProcessor) 1.113 -(import java.awt.image.BufferedImage) 1.114 1.115 -(def white -1) 1.116 - 1.117 -(defn filter-pixels 1.118 - "List the coordinates of all pixels matching pred, within the bounds 1.119 - provided. Bounds -> [x0 y0 width height]" 1.120 - {:author "Dylan Holmes"} 1.121 - ([pred #^BufferedImage image] 1.122 - (filter-pixels pred image [0 0 (.getWidth image) (.getHeight image)])) 1.123 - ([pred #^BufferedImage image [x0 y0 width height]] 1.124 - ((fn accumulate [x y matches] 1.125 - (cond 1.126 - (>= y (+ height y0)) matches 1.127 - (>= x (+ width x0)) (recur 0 (inc y) matches) 1.128 - (pred (.getRGB image x y)) 1.129 - (recur (inc x) y (conj matches [x y])) 1.130 - :else (recur (inc x) y matches))) 1.131 - x0 y0 []))) 1.132 - 1.133 -(defn white-coordinates 1.134 - "Coordinates of all the white pixels in a subset of the image." 1.135 - ([#^BufferedImage image bounds] 1.136 - (filter-pixels #(= % white) image bounds)) 1.137 - ([#^BufferedImage image] 1.138 - (filter-pixels #(= % white) image))) 1.139 1.140 (defn triangle 1.141 "Get the triangle specified by triangle-index from the mesh within 1.142 @@ -718,87 +610,12 @@ 1.143 (node-seq pieces))))) 1.144 1.145 1.146 -;; human eye transmits 62kb/s to brain Bandwidth is 8.75 Mb/s 1.147 -;; http://en.wikipedia.org/wiki/Retina 1.148 - 1.149 (defn test-eye [] 1.150 (.getChild 1.151 (.getChild (worm-model) "eyes") 1.152 "eye")) 1.153 1.154 1.155 -(defn retina-sensor-image 1.156 - "Return a map of pixel selection functions to BufferedImages 1.157 - describing the distribution of light-sensitive components on this 1.158 - geometry's surface. Each function creates an integer from the rgb 1.159 - values found in the pixel. :red, :green, :blue, :gray are already 1.160 - defined as extracting the red green blue and average components 1.161 - respectively." 1.162 - [#^Spatial eye] 1.163 - (if-let [eye-map (meta-data eye "eye")] 1.164 - (map-vals 1.165 - #(ImageToAwt/convert 1.166 - (.getImage (.loadTexture (asset-manager) %)) 1.167 - false false 0) 1.168 - (eval (read-string eye-map))))) 1.169 - 1.170 -(defn eye-dimensions 1.171 - "returns the width and height specified in the metadata of the eye" 1.172 - [#^Spatial eye] 1.173 - (let [dimensions 1.174 - (map #(vector (.getWidth %) (.getHeight %)) 1.175 - (vals (retina-sensor-image eye)))] 1.176 - [(apply max (map first dimensions)) 1.177 - (apply max (map second dimensions))])) 1.178 - 1.179 -(defn creature-eyes 1.180 - ;;dylan 1.181 - "Return the children of the creature's \"eyes\" node." 1.182 - ;;"The eye nodes which are children of the \"eyes\" node in the 1.183 - ;;creature." 1.184 - [#^Node creature] 1.185 - (if-let [eye-node (.getChild creature "eyes")] 1.186 - (seq (.getChildren eye-node)) 1.187 - (do (println-repl "could not find eyes node") []))) 1.188 - 1.189 -;; Here's how vision will work. 1.190 - 1.191 -;; Make the continuation in scene-processor take FrameBuffer, 1.192 -;; byte-buffer, BufferedImage already sized to the correct 1.193 -;; dimensions. the continuation will decide wether to "mix" them 1.194 -;; into the BufferedImage, lazily ignore them, or mix them halfway 1.195 -;; and call c/graphics card routines. 1.196 - 1.197 -;; (vision creature) will take an optional :skip argument which will 1.198 -;; inform the continuations in scene processor to skip the given 1.199 -;; number of cycles; 0 means that no cycles will be skipped. 1.200 - 1.201 -;; (vision creature) will return [init-functions sensor-functions]. 1.202 -;; The init-functions are each single-arg functions that take the 1.203 -;; world and register the cameras and must each be called before the 1.204 -;; corresponding sensor-functions. Each init-function returns the 1.205 -;; viewport for that eye which can be manipulated, saved, etc. Each 1.206 -;; sensor-function is a thunk and will return data in the same 1.207 -;; format as the tactile-sensor functions; the structure is 1.208 -;; [topology, sensor-data]. Internally, these sensor-functions 1.209 -;; maintain a reference to sensor-data which is periodically updated 1.210 -;; by the continuation function established by its init-function. 1.211 -;; They can be queried every cycle, but their information may not 1.212 -;; necessairly be different every cycle. 1.213 - 1.214 -;; Each eye in the creature in blender will work the same way as 1.215 -;; joints -- a zero dimensional object with no geometry whose local 1.216 -;; coordinate system determines the orientation of the resulting 1.217 -;; eye. All eyes will have a parent named "eyes" just as all joints 1.218 -;; have a parent named "joints". The resulting camera will be a 1.219 -;; ChaseCamera or a CameraNode bound to the geo that is closest to 1.220 -;; the eye marker. The eye marker will contain the metadata for the 1.221 -;; eye, and will be moved by it's bound geometry. The dimensions of 1.222 -;; the eye's camera are equal to the dimensions of the eye's "UV" 1.223 -;; map. 1.224 - 1.225 - 1.226 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1.227 1.228 ;; Ears work the same way as vision. 1.229 1.230 @@ -817,45 +634,9 @@ 1.231 (seq (.getChildren ear-node)) 1.232 (do (println-repl "could not find ears node") []))) 1.233 1.234 -(defn closest-node 1.235 - "Return the object in creature which is closest to the given node." 1.236 - ;;dylan"The closest object in creature to the given node." 1.237 - [#^Node creature #^Node eye] 1.238 - (loop [radius (float 0.01)] 1.239 - (let [results (CollisionResults.)] 1.240 - (.collideWith 1.241 - creature 1.242 - (BoundingBox. (.getWorldTranslation eye) 1.243 - radius radius radius) 1.244 - results) 1.245 - (if-let [target (first results)] 1.246 - (.getGeometry target) 1.247 - (recur (float (* 2 radius))))))) 1.248 1.249 ;;dylan (defn follow-sense, adjoin-sense, attach-stimuli, 1.250 ;;anchor-qualia, augment-organ, with-organ 1.251 -(defn bind-sense 1.252 - "Bind the sense to the Spatial such that it will maintain its 1.253 - current position relative to the Spatial no matter how the spatial 1.254 - moves. 'sense can be either a Camera or Listener object." 1.255 - [#^Spatial obj sense] 1.256 - (let [sense-offset (.subtract (.getLocation sense) 1.257 - (.getWorldTranslation obj)) 1.258 - initial-sense-rotation (Quaternion. (.getRotation sense)) 1.259 - base-anti-rotation (.inverse (.getWorldRotation obj))] 1.260 - (.addControl 1.261 - obj 1.262 - (proxy [AbstractControl] [] 1.263 - (controlUpdate [tpf] 1.264 - (let [total-rotation 1.265 - (.mult base-anti-rotation (.getWorldRotation obj))] 1.266 - (.setLocation sense 1.267 - (.add 1.268 - (.mult total-rotation sense-offset) 1.269 - (.getWorldTranslation obj))) 1.270 - (.setRotation sense 1.271 - (.mult total-rotation initial-sense-rotation)))) 1.272 - (controlRender [_ _]))))) 1.273 1.274 1.275 (defn update-listener-velocity 1.276 @@ -919,68 +700,6 @@ 1.277 (for [ear (creature-ears creature)] 1.278 (enable-hearing creature ear)))) 1.279 1.280 -(defn attach-eye 1.281 - "Attach a Camera to the appropiate area and return the Camera." 1.282 - [#^Node creature #^Spatial eye] 1.283 - (let [target (closest-node creature eye) 1.284 - [cam-width cam-height] (eye-dimensions eye) 1.285 - cam (Camera. cam-width cam-height)] 1.286 - (.setLocation cam (.getWorldTranslation eye)) 1.287 - (.setRotation cam (.getWorldRotation eye)) 1.288 - (.setFrustumPerspective 1.289 - cam 45 (/ (.getWidth cam) (.getHeight cam)) 1.290 - 1 1000) 1.291 - (bind-sense target cam) 1.292 - cam)) 1.293 - 1.294 -(def presets 1.295 - {:all 0xFFFFFF 1.296 - :red 0xFF0000 1.297 - :blue 0x0000FF 1.298 - :green 0x00FF00}) 1.299 - 1.300 -(defn enable-vision 1.301 - "return [init-function sensor-functions] for a particular eye" 1.302 - [#^Node creature #^Spatial eye & {skip :skip :or {skip 0}}] 1.303 - (let [retinal-map (retina-sensor-image eye) 1.304 - camera (attach-eye creature eye) 1.305 - vision-image 1.306 - (atom 1.307 - (BufferedImage. (.getWidth camera) 1.308 - (.getHeight camera) 1.309 - BufferedImage/TYPE_BYTE_BINARY))] 1.310 - [(fn [world] 1.311 - (add-eye 1.312 - world camera 1.313 - (let [counter (atom 0)] 1.314 - (fn [r fb bb bi] 1.315 - (if (zero? (rem (swap! counter inc) (inc skip))) 1.316 - (reset! vision-image (BufferedImage! r fb bb bi))))))) 1.317 - (vec 1.318 - (map 1.319 - (fn [[key image]] 1.320 - (let [whites (white-coordinates image) 1.321 - topology (vec (collapse whites)) 1.322 - mask (presets key)] 1.323 - (fn [] 1.324 - (vector 1.325 - topology 1.326 - (vec 1.327 - (for [[x y] whites] 1.328 - (bit-and 1.329 - mask (.getRGB @vision-image x y)))))))) 1.330 - retinal-map))])) 1.331 - 1.332 -(defn vision 1.333 - [#^Node creature & {skip :skip :or {skip 0}}] 1.334 - (reduce 1.335 - (fn [[init-a senses-a] 1.336 - [init-b senses-b]] 1.337 - [(conj init-a init-b) 1.338 - (into senses-a senses-b)]) 1.339 - [[][]] 1.340 - (for [eye (creature-eyes creature)] 1.341 - (enable-vision creature eye)))) 1.342 1.343 1.344