Mercurial > cortex
changeset 151:aaacf087504c
refactored vision code
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Fri, 03 Feb 2012 05:52:18 -0700 |
parents | e1232043656a |
children | c901b17a1f52 |
files | org/blender.org org/eyes.org org/sense-util.org org/test-creature.org org/util.org |
diffstat | 5 files changed, 348 insertions(+), 286 deletions(-) [+] |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/org/blender.org Fri Feb 03 05:52:18 2012 -0700 1.3 @@ -0,0 +1,19 @@ 1.4 +#+title: Blender Clojure utilities 1.5 +#+author: Robert McIntyre 1.6 +#+email: rlm@mit.edu 1.7 +#+description: blender utilities 1.8 +#+keywords: simulation, jMonkeyEngine3, clojure, blender 1.9 +#+SETUPFILE: ../../aurellem/org/setup.org 1.10 +#+INCLUDE: ../../aurellem/org/level-0.org 1.11 + 1.12 + 1.13 +#+name: blender 1.14 +#+begin_src clojure 1.15 + 1.16 +#+end_src 1.17 + 1.18 + 1.19 +* COMMENT generate source 1.20 +#+begin_src clojure :tangle ../src/cortex/blender.clj 1.21 +<<blender>> 1.22 +#+end_src
2.1 --- a/org/eyes.org Fri Feb 03 05:08:45 2012 -0700 2.2 +++ b/org/eyes.org Fri Feb 03 05:52:18 2012 -0700 2.3 @@ -11,6 +11,47 @@ 2.4 2.5 I want to make creatures with eyes. Each eye can be independely moved 2.6 and should see its own version of the world depending on where it is. 2.7 + 2.8 +Here's how vision will work. 2.9 + 2.10 +Make the continuation in scene-processor take FrameBuffer, 2.11 +byte-buffer, BufferedImage already sized to the correct 2.12 +dimensions. the continuation will decide wether to "mix" them 2.13 +into the BufferedImage, lazily ignore them, or mix them halfway 2.14 +and call c/graphics card routines. 2.15 + 2.16 +(vision creature) will take an optional :skip argument which will 2.17 +inform the continuations in scene processor to skip the given 2.18 +number of cycles 0 means that no cycles will be skipped. 2.19 + 2.20 +(vision creature) will return [init-functions sensor-functions]. 2.21 +The init-functions are each single-arg functions that take the 2.22 +world and register the cameras and must each be called before the 2.23 +corresponding sensor-functions. Each init-function returns the 2.24 +viewport for that eye which can be manipulated, saved, etc. Each 2.25 +sensor-function is a thunk and will return data in the same 2.26 +format as the tactile-sensor functions the structure is 2.27 +[topology, sensor-data]. Internally, these sensor-functions 2.28 +maintain a reference to sensor-data which is periodically updated 2.29 +by the continuation function established by its init-function. 2.30 +They can be queried every cycle, but their information may not 2.31 +necessairly be different every cycle. 2.32 + 2.33 +Each eye in the creature in blender will work the same way as 2.34 +joints -- a zero dimensional object with no geometry whose local 2.35 +coordinate system determines the orientation of the resulting 2.36 +eye. All eyes will have a parent named "eyes" just as all joints 2.37 +have a parent named "joints". The resulting camera will be a 2.38 +ChaseCamera or a CameraNode bound to the geo that is closest to 2.39 +the eye marker. The eye marker will contain the metadata for the 2.40 +eye, and will be moved by it's bound geometry. The dimensions of 2.41 +the eye's camera are equal to the dimensions of the eye's "UV" 2.42 +map. 2.43 + 2.44 + 2.45 + 2.46 + 2.47 + 2.48 #+name: eyes 2.49 #+begin_src clojure 2.50 (ns cortex.vision 2.51 @@ -18,14 +59,18 @@ 2.52 eyes from different positions to observe the same world, and pass 2.53 the observed data to any arbitray function." 2.54 {:author "Robert McIntyre"} 2.55 - (:use cortex.world) 2.56 + (:use (cortex world sense util)) 2.57 (:import com.jme3.post.SceneProcessor) 2.58 (:import (com.jme3.util BufferUtils Screenshots)) 2.59 (:import java.nio.ByteBuffer) 2.60 (:import java.awt.image.BufferedImage) 2.61 (:import com.jme3.renderer.ViewPort) 2.62 (:import com.jme3.math.ColorRGBA) 2.63 - (:import com.jme3.renderer.Renderer)) 2.64 + (:import com.jme3.renderer.Renderer) 2.65 + (:import jme3tools.converters.ImageToAwt) 2.66 + (:import com.jme3.scene.Node)) 2.67 + 2.68 +(cortex.import/mega-import-jme3) 2.69 2.70 2.71 (defn vision-pipeline 2.72 @@ -92,10 +137,108 @@ 2.73 (.setBackgroundColor ColorRGBA/Black) 2.74 (.addProcessor (vision-pipeline continuation)) 2.75 (.attachScene (.getRootNode world))))) 2.76 + 2.77 +(defn retina-sensor-image 2.78 + "Return a map of pixel selection functions to BufferedImages 2.79 + describing the distribution of light-sensitive components on this 2.80 + geometry's surface. Each function creates an integer from the rgb 2.81 + values found in the pixel. :red, :green, :blue, :gray are already 2.82 + defined as extracting the red green blue and average components 2.83 + respectively." 2.84 + [#^Spatial eye] 2.85 + (if-let [eye-map (meta-data eye "eye")] 2.86 + (map-vals 2.87 + #(ImageToAwt/convert 2.88 + (.getImage (.loadTexture (asset-manager) %)) 2.89 + false false 0) 2.90 + (eval (read-string eye-map))))) 2.91 + 2.92 +(defn eye-dimensions 2.93 + "returns the width and height specified in the metadata of the eye" 2.94 + [#^Spatial eye] 2.95 + (let [dimensions 2.96 + (map #(vector (.getWidth %) (.getHeight %)) 2.97 + (vals (retina-sensor-image eye)))] 2.98 + [(apply max (map first dimensions)) 2.99 + (apply max (map second dimensions))])) 2.100 + 2.101 +(defn creature-eyes 2.102 + ;;dylan 2.103 + "Return the children of the creature's \"eyes\" node." 2.104 + ;;"The eye nodes which are children of the \"eyes\" node in the 2.105 + ;;creature." 2.106 + [#^Node creature] 2.107 + (if-let [eye-node (.getChild creature "eyes")] 2.108 + (seq (.getChildren eye-node)) 2.109 + (do (println-repl "could not find eyes node") []))) 2.110 + 2.111 + 2.112 +(defn attach-eye 2.113 + "Attach a Camera to the appropiate area and return the Camera." 2.114 + [#^Node creature #^Spatial eye] 2.115 + (let [target (closest-node creature eye) 2.116 + [cam-width cam-height] (eye-dimensions eye) 2.117 + cam (Camera. cam-width cam-height)] 2.118 + (.setLocation cam (.getWorldTranslation eye)) 2.119 + (.setRotation cam (.getWorldRotation eye)) 2.120 + (.setFrustumPerspective 2.121 + cam 45 (/ (.getWidth cam) (.getHeight cam)) 2.122 + 1 1000) 2.123 + (bind-sense target cam) 2.124 + cam)) 2.125 + 2.126 +(def presets 2.127 + {:all 0xFFFFFF 2.128 + :red 0xFF0000 2.129 + :blue 0x0000FF 2.130 + :green 0x00FF00}) 2.131 + 2.132 +(defn enable-vision 2.133 + "return [init-function sensor-functions] for a particular eye" 2.134 + [#^Node creature #^Spatial eye & {skip :skip :or {skip 0}}] 2.135 + (let [retinal-map (retina-sensor-image eye) 2.136 + camera (attach-eye creature eye) 2.137 + vision-image 2.138 + (atom 2.139 + (BufferedImage. (.getWidth camera) 2.140 + (.getHeight camera) 2.141 + BufferedImage/TYPE_BYTE_BINARY))] 2.142 + [(fn [world] 2.143 + (add-eye 2.144 + world camera 2.145 + (let [counter (atom 0)] 2.146 + (fn [r fb bb bi] 2.147 + (if (zero? (rem (swap! counter inc) (inc skip))) 2.148 + (reset! vision-image (BufferedImage! r fb bb bi))))))) 2.149 + (vec 2.150 + (map 2.151 + (fn [[key image]] 2.152 + (let [whites (white-coordinates image) 2.153 + topology (vec (collapse whites)) 2.154 + mask (presets key)] 2.155 + (fn [] 2.156 + (vector 2.157 + topology 2.158 + (vec 2.159 + (for [[x y] whites] 2.160 + (bit-and 2.161 + mask (.getRGB @vision-image x y)))))))) 2.162 + retinal-map))])) 2.163 + 2.164 +(defn vision 2.165 + [#^Node creature & {skip :skip :or {skip 0}}] 2.166 + (reduce 2.167 + (fn [[init-a senses-a] 2.168 + [init-b senses-b]] 2.169 + [(conj init-a init-b) 2.170 + (into senses-a senses-b)]) 2.171 + [[][]] 2.172 + (for [eye (creature-eyes creature)] 2.173 + (enable-vision creature eye)))) 2.174 + 2.175 + 2.176 #+end_src 2.177 2.178 -#+results: eyes 2.179 -: #'cortex.vision/add-eye 2.180 2.181 Note the use of continuation passing style for connecting the eye to a 2.182 function to process the output. You can create any number of eyes, and
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/org/sense-util.org Fri Feb 03 05:52:18 2012 -0700 3.3 @@ -0,0 +1,174 @@ 3.4 +#+title: General sense/effector utilities 3.5 +#+author: Robert McIntyre 3.6 +#+email: rlm@mit.edu 3.7 +#+description: sensory utilities 3.8 +#+keywords: simulation, jMonkeyEngine3, clojure, simulated senses 3.9 +#+SETUPFILE: ../../aurellem/org/setup.org 3.10 +#+INCLUDE: ../../aurellem/org/level-0.org 3.11 + 3.12 + 3.13 +#+name: sense-util 3.14 +#+begin_src clojure 3.15 +(ns cortex.sense) 3.16 +(cortex.import/mega-import-jme3) 3.17 +(import ij.process.ImageProcessor) 3.18 +(import java.awt.image.BufferedImage) 3.19 + 3.20 + 3.21 +(defn meta-data [blender-node key] 3.22 + (if-let [data (.getUserData blender-node "properties")] 3.23 + (.findValue data key) 3.24 + nil)) 3.25 + 3.26 +(defn closest-node 3.27 + "Return the object in creature which is closest to the given node." 3.28 + ;;dylan"The closest object in creature to the given node." 3.29 + [#^Node creature #^Node eye] 3.30 + (loop [radius (float 0.01)] 3.31 + (let [results (CollisionResults.)] 3.32 + (.collideWith 3.33 + creature 3.34 + (BoundingBox. (.getWorldTranslation eye) 3.35 + radius radius radius) 3.36 + results) 3.37 + (if-let [target (first results)] 3.38 + (.getGeometry target) 3.39 + (recur (float (* 2 radius))))))) 3.40 + 3.41 +(defn bind-sense 3.42 + "Bind the sense to the Spatial such that it will maintain its 3.43 + current position relative to the Spatial no matter how the spatial 3.44 + moves. 'sense can be either a Camera or Listener object." 3.45 + [#^Spatial obj sense] 3.46 + (let [sense-offset (.subtract (.getLocation sense) 3.47 + (.getWorldTranslation obj)) 3.48 + initial-sense-rotation (Quaternion. (.getRotation sense)) 3.49 + base-anti-rotation (.inverse (.getWorldRotation obj))] 3.50 + (.addControl 3.51 + obj 3.52 + (proxy [AbstractControl] [] 3.53 + (controlUpdate [tpf] 3.54 + (let [total-rotation 3.55 + (.mult base-anti-rotation (.getWorldRotation obj))] 3.56 + (.setLocation sense 3.57 + (.add 3.58 + (.mult total-rotation sense-offset) 3.59 + (.getWorldTranslation obj))) 3.60 + (.setRotation sense 3.61 + (.mult total-rotation initial-sense-rotation)))) 3.62 + (controlRender [_ _]))))) 3.63 + 3.64 +(def white -1) 3.65 + 3.66 +(defn filter-pixels 3.67 + "List the coordinates of all pixels matching pred, within the bounds 3.68 + provided. Bounds -> [x0 y0 width height]" 3.69 + {:author "Dylan Holmes"} 3.70 + ([pred #^BufferedImage image] 3.71 + (filter-pixels pred image [0 0 (.getWidth image) (.getHeight image)])) 3.72 + ([pred #^BufferedImage image [x0 y0 width height]] 3.73 + ((fn accumulate [x y matches] 3.74 + (cond 3.75 + (>= y (+ height y0)) matches 3.76 + (>= x (+ width x0)) (recur 0 (inc y) matches) 3.77 + (pred (.getRGB image x y)) 3.78 + (recur (inc x) y (conj matches [x y])) 3.79 + :else (recur (inc x) y matches))) 3.80 + x0 y0 []))) 3.81 + 3.82 +(defn white-coordinates 3.83 + "Coordinates of all the white pixels in a subset of the image." 3.84 + ([#^BufferedImage image bounds] 3.85 + (filter-pixels #(= % white) image bounds)) 3.86 + ([#^BufferedImage image] 3.87 + (filter-pixels #(= % white) image))) 3.88 + 3.89 +(defn points->image 3.90 + "Take a sparse collection of points and visuliaze it as a 3.91 + BufferedImage." 3.92 + 3.93 + ;; TODO maybe parallelize this since it's easy 3.94 + 3.95 + [points] 3.96 + (if (empty? points) 3.97 + (BufferedImage. 1 1 BufferedImage/TYPE_BYTE_BINARY) 3.98 + (let [xs (vec (map first points)) 3.99 + ys (vec (map second points)) 3.100 + x0 (apply min xs) 3.101 + y0 (apply min ys) 3.102 + width (- (apply max xs) x0) 3.103 + height (- (apply max ys) y0) 3.104 + image (BufferedImage. (inc width) (inc height) 3.105 + BufferedImage/TYPE_INT_RGB)] 3.106 + (dorun 3.107 + (for [x (range (.getWidth image)) 3.108 + y (range (.getHeight image))] 3.109 + (.setRGB image x y 0xFF0000))) 3.110 + (dorun 3.111 + (for [index (range (count points))] 3.112 + (.setRGB image (- (xs index) x0) (- (ys index) y0) -1))) 3.113 + 3.114 + image))) 3.115 + 3.116 +(defn average [coll] 3.117 + (/ (reduce + coll) (count coll))) 3.118 + 3.119 +(defn collapse-1d 3.120 + "One dimensional analogue of collapse" 3.121 + [center line] 3.122 + (let [length (count line) 3.123 + num-above (count (filter (partial < center) line)) 3.124 + num-below (- length num-above)] 3.125 + (range (- center num-below) 3.126 + (+ center num-above)))) 3.127 + 3.128 +(defn collapse 3.129 + "Take a set of pairs of integers and collapse them into a 3.130 + contigous bitmap." 3.131 + [points] 3.132 + (if (empty? points) [] 3.133 + (let 3.134 + [num-points (count points) 3.135 + center (vector 3.136 + (int (average (map first points))) 3.137 + (int (average (map first points)))) 3.138 + flattened 3.139 + (reduce 3.140 + concat 3.141 + (map 3.142 + (fn [column] 3.143 + (map vector 3.144 + (map first column) 3.145 + (collapse-1d (second center) 3.146 + (map second column)))) 3.147 + (partition-by first (sort-by first points)))) 3.148 + squeezed 3.149 + (reduce 3.150 + concat 3.151 + (map 3.152 + (fn [row] 3.153 + (map vector 3.154 + (collapse-1d (first center) 3.155 + (map first row)) 3.156 + (map second row))) 3.157 + (partition-by second (sort-by second flattened)))) 3.158 + relocate 3.159 + (let [min-x (apply min (map first squeezed)) 3.160 + min-y (apply min (map second squeezed))] 3.161 + (map (fn [[x y]] 3.162 + [(- x min-x) 3.163 + (- y min-y)]) 3.164 + squeezed))] 3.165 + relocate))) 3.166 + 3.167 +#+end_src 3.168 + 3.169 +#+results: sense-util 3.170 +: #'cortex.sense/meta-data 3.171 + 3.172 + 3.173 + 3.174 +* COMMENT generate source 3.175 +#+begin_src clojure :tangle ../src/cortex/sense.clj 3.176 +<<sense-util>> 3.177 +#+end_src
4.1 --- a/org/test-creature.org Fri Feb 03 05:08:45 2012 -0700 4.2 +++ b/org/test-creature.org Fri Feb 03 05:52:18 2012 -0700 4.3 @@ -147,7 +147,7 @@ 4.4 ;; TODO remove this! 4.5 (require 'cortex.import) 4.6 (cortex.import/mega-import-jme3) 4.7 -(use '(cortex world util body hearing touch vision)) 4.8 +(use '(cortex world util body hearing touch vision sense)) 4.9 4.10 (rlm.rlm-commands/help) 4.11 (import java.awt.image.BufferedImage) 4.12 @@ -160,83 +160,6 @@ 4.13 (declare joint-create) 4.14 (use 'clojure.contrib.def) 4.15 4.16 -(defn points->image 4.17 - "Take a sparse collection of points and visuliaze it as a 4.18 - BufferedImage." 4.19 - 4.20 - ;; TODO maybe parallelize this since it's easy 4.21 - 4.22 - [points] 4.23 - (if (empty? points) 4.24 - (BufferedImage. 1 1 BufferedImage/TYPE_BYTE_BINARY) 4.25 - (let [xs (vec (map first points)) 4.26 - ys (vec (map second points)) 4.27 - x0 (apply min xs) 4.28 - y0 (apply min ys) 4.29 - width (- (apply max xs) x0) 4.30 - height (- (apply max ys) y0) 4.31 - image (BufferedImage. (inc width) (inc height) 4.32 - BufferedImage/TYPE_INT_RGB)] 4.33 - (dorun 4.34 - (for [x (range (.getWidth image)) 4.35 - y (range (.getHeight image))] 4.36 - (.setRGB image x y 0xFF0000))) 4.37 - (dorun 4.38 - (for [index (range (count points))] 4.39 - (.setRGB image (- (xs index) x0) (- (ys index) y0) -1))) 4.40 - 4.41 - image))) 4.42 - 4.43 -(defn average [coll] 4.44 - (/ (reduce + coll) (count coll))) 4.45 - 4.46 -(defn collapse-1d 4.47 - "One dimensional analogue of collapse" 4.48 - [center line] 4.49 - (let [length (count line) 4.50 - num-above (count (filter (partial < center) line)) 4.51 - num-below (- length num-above)] 4.52 - (range (- center num-below) 4.53 - (+ center num-above)))) 4.54 - 4.55 -(defn collapse 4.56 - "Take a set of pairs of integers and collapse them into a 4.57 - contigous bitmap." 4.58 - [points] 4.59 - (if (empty? points) [] 4.60 - (let 4.61 - [num-points (count points) 4.62 - center (vector 4.63 - (int (average (map first points))) 4.64 - (int (average (map first points)))) 4.65 - flattened 4.66 - (reduce 4.67 - concat 4.68 - (map 4.69 - (fn [column] 4.70 - (map vector 4.71 - (map first column) 4.72 - (collapse-1d (second center) 4.73 - (map second column)))) 4.74 - (partition-by first (sort-by first points)))) 4.75 - squeezed 4.76 - (reduce 4.77 - concat 4.78 - (map 4.79 - (fn [row] 4.80 - (map vector 4.81 - (collapse-1d (first center) 4.82 - (map first row)) 4.83 - (map second row))) 4.84 - (partition-by second (sort-by second flattened)))) 4.85 - relocate 4.86 - (let [min-x (apply min (map first squeezed)) 4.87 - min-y (apply min (map second squeezed))] 4.88 - (map (fn [[x y]] 4.89 - [(- x min-x) 4.90 - (- y min-y)]) 4.91 - squeezed))] 4.92 - relocate))) 4.93 4.94 (defn load-bullet [] 4.95 (let [sim (world (Node.) {} no-op no-op)] 4.96 @@ -254,11 +177,6 @@ 4.97 (.registerLoader BlenderModelLoader (into-array String ["blend"]))) 4.98 model)) 4.99 4.100 -(defn meta-data [blender-node key] 4.101 - (if-let [data (.getUserData blender-node "properties")] 4.102 - (.findValue data key) 4.103 - nil)) 4.104 - 4.105 (defn blender-to-jme 4.106 "Convert from Blender coordinates to JME coordinates" 4.107 [#^Vector3f in] 4.108 @@ -474,33 +392,7 @@ 4.109 image-path)) 4.110 false false 0))) 4.111 4.112 -(import ij.process.ImageProcessor) 4.113 -(import java.awt.image.BufferedImage) 4.114 4.115 -(def white -1) 4.116 - 4.117 -(defn filter-pixels 4.118 - "List the coordinates of all pixels matching pred, within the bounds 4.119 - provided. Bounds -> [x0 y0 width height]" 4.120 - {:author "Dylan Holmes"} 4.121 - ([pred #^BufferedImage image] 4.122 - (filter-pixels pred image [0 0 (.getWidth image) (.getHeight image)])) 4.123 - ([pred #^BufferedImage image [x0 y0 width height]] 4.124 - ((fn accumulate [x y matches] 4.125 - (cond 4.126 - (>= y (+ height y0)) matches 4.127 - (>= x (+ width x0)) (recur 0 (inc y) matches) 4.128 - (pred (.getRGB image x y)) 4.129 - (recur (inc x) y (conj matches [x y])) 4.130 - :else (recur (inc x) y matches))) 4.131 - x0 y0 []))) 4.132 - 4.133 -(defn white-coordinates 4.134 - "Coordinates of all the white pixels in a subset of the image." 4.135 - ([#^BufferedImage image bounds] 4.136 - (filter-pixels #(= % white) image bounds)) 4.137 - ([#^BufferedImage image] 4.138 - (filter-pixels #(= % white) image))) 4.139 4.140 (defn triangle 4.141 "Get the triangle specified by triangle-index from the mesh within 4.142 @@ -718,87 +610,12 @@ 4.143 (node-seq pieces))))) 4.144 4.145 4.146 -;; human eye transmits 62kb/s to brain Bandwidth is 8.75 Mb/s 4.147 -;; http://en.wikipedia.org/wiki/Retina 4.148 - 4.149 (defn test-eye [] 4.150 (.getChild 4.151 (.getChild (worm-model) "eyes") 4.152 "eye")) 4.153 4.154 4.155 -(defn retina-sensor-image 4.156 - "Return a map of pixel selection functions to BufferedImages 4.157 - describing the distribution of light-sensitive components on this 4.158 - geometry's surface. Each function creates an integer from the rgb 4.159 - values found in the pixel. :red, :green, :blue, :gray are already 4.160 - defined as extracting the red green blue and average components 4.161 - respectively." 4.162 - [#^Spatial eye] 4.163 - (if-let [eye-map (meta-data eye "eye")] 4.164 - (map-vals 4.165 - #(ImageToAwt/convert 4.166 - (.getImage (.loadTexture (asset-manager) %)) 4.167 - false false 0) 4.168 - (eval (read-string eye-map))))) 4.169 - 4.170 -(defn eye-dimensions 4.171 - "returns the width and height specified in the metadata of the eye" 4.172 - [#^Spatial eye] 4.173 - (let [dimensions 4.174 - (map #(vector (.getWidth %) (.getHeight %)) 4.175 - (vals (retina-sensor-image eye)))] 4.176 - [(apply max (map first dimensions)) 4.177 - (apply max (map second dimensions))])) 4.178 - 4.179 -(defn creature-eyes 4.180 - ;;dylan 4.181 - "Return the children of the creature's \"eyes\" node." 4.182 - ;;"The eye nodes which are children of the \"eyes\" node in the 4.183 - ;;creature." 4.184 - [#^Node creature] 4.185 - (if-let [eye-node (.getChild creature "eyes")] 4.186 - (seq (.getChildren eye-node)) 4.187 - (do (println-repl "could not find eyes node") []))) 4.188 - 4.189 -;; Here's how vision will work. 4.190 - 4.191 -;; Make the continuation in scene-processor take FrameBuffer, 4.192 -;; byte-buffer, BufferedImage already sized to the correct 4.193 -;; dimensions. the continuation will decide wether to "mix" them 4.194 -;; into the BufferedImage, lazily ignore them, or mix them halfway 4.195 -;; and call c/graphics card routines. 4.196 - 4.197 -;; (vision creature) will take an optional :skip argument which will 4.198 -;; inform the continuations in scene processor to skip the given 4.199 -;; number of cycles; 0 means that no cycles will be skipped. 4.200 - 4.201 -;; (vision creature) will return [init-functions sensor-functions]. 4.202 -;; The init-functions are each single-arg functions that take the 4.203 -;; world and register the cameras and must each be called before the 4.204 -;; corresponding sensor-functions. Each init-function returns the 4.205 -;; viewport for that eye which can be manipulated, saved, etc. Each 4.206 -;; sensor-function is a thunk and will return data in the same 4.207 -;; format as the tactile-sensor functions; the structure is 4.208 -;; [topology, sensor-data]. Internally, these sensor-functions 4.209 -;; maintain a reference to sensor-data which is periodically updated 4.210 -;; by the continuation function established by its init-function. 4.211 -;; They can be queried every cycle, but their information may not 4.212 -;; necessairly be different every cycle. 4.213 - 4.214 -;; Each eye in the creature in blender will work the same way as 4.215 -;; joints -- a zero dimensional object with no geometry whose local 4.216 -;; coordinate system determines the orientation of the resulting 4.217 -;; eye. All eyes will have a parent named "eyes" just as all joints 4.218 -;; have a parent named "joints". The resulting camera will be a 4.219 -;; ChaseCamera or a CameraNode bound to the geo that is closest to 4.220 -;; the eye marker. The eye marker will contain the metadata for the 4.221 -;; eye, and will be moved by it's bound geometry. The dimensions of 4.222 -;; the eye's camera are equal to the dimensions of the eye's "UV" 4.223 -;; map. 4.224 - 4.225 - 4.226 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 4.227 4.228 ;; Ears work the same way as vision. 4.229 4.230 @@ -817,45 +634,9 @@ 4.231 (seq (.getChildren ear-node)) 4.232 (do (println-repl "could not find ears node") []))) 4.233 4.234 -(defn closest-node 4.235 - "Return the object in creature which is closest to the given node." 4.236 - ;;dylan"The closest object in creature to the given node." 4.237 - [#^Node creature #^Node eye] 4.238 - (loop [radius (float 0.01)] 4.239 - (let [results (CollisionResults.)] 4.240 - (.collideWith 4.241 - creature 4.242 - (BoundingBox. (.getWorldTranslation eye) 4.243 - radius radius radius) 4.244 - results) 4.245 - (if-let [target (first results)] 4.246 - (.getGeometry target) 4.247 - (recur (float (* 2 radius))))))) 4.248 4.249 ;;dylan (defn follow-sense, adjoin-sense, attach-stimuli, 4.250 ;;anchor-qualia, augment-organ, with-organ 4.251 -(defn bind-sense 4.252 - "Bind the sense to the Spatial such that it will maintain its 4.253 - current position relative to the Spatial no matter how the spatial 4.254 - moves. 'sense can be either a Camera or Listener object." 4.255 - [#^Spatial obj sense] 4.256 - (let [sense-offset (.subtract (.getLocation sense) 4.257 - (.getWorldTranslation obj)) 4.258 - initial-sense-rotation (Quaternion. (.getRotation sense)) 4.259 - base-anti-rotation (.inverse (.getWorldRotation obj))] 4.260 - (.addControl 4.261 - obj 4.262 - (proxy [AbstractControl] [] 4.263 - (controlUpdate [tpf] 4.264 - (let [total-rotation 4.265 - (.mult base-anti-rotation (.getWorldRotation obj))] 4.266 - (.setLocation sense 4.267 - (.add 4.268 - (.mult total-rotation sense-offset) 4.269 - (.getWorldTranslation obj))) 4.270 - (.setRotation sense 4.271 - (.mult total-rotation initial-sense-rotation)))) 4.272 - (controlRender [_ _]))))) 4.273 4.274 4.275 (defn update-listener-velocity 4.276 @@ -919,68 +700,6 @@ 4.277 (for [ear (creature-ears creature)] 4.278 (enable-hearing creature ear)))) 4.279 4.280 -(defn attach-eye 4.281 - "Attach a Camera to the appropiate area and return the Camera." 4.282 - [#^Node creature #^Spatial eye] 4.283 - (let [target (closest-node creature eye) 4.284 - [cam-width cam-height] (eye-dimensions eye) 4.285 - cam (Camera. cam-width cam-height)] 4.286 - (.setLocation cam (.getWorldTranslation eye)) 4.287 - (.setRotation cam (.getWorldRotation eye)) 4.288 - (.setFrustumPerspective 4.289 - cam 45 (/ (.getWidth cam) (.getHeight cam)) 4.290 - 1 1000) 4.291 - (bind-sense target cam) 4.292 - cam)) 4.293 - 4.294 -(def presets 4.295 - {:all 0xFFFFFF 4.296 - :red 0xFF0000 4.297 - :blue 0x0000FF 4.298 - :green 0x00FF00}) 4.299 - 4.300 -(defn enable-vision 4.301 - "return [init-function sensor-functions] for a particular eye" 4.302 - [#^Node creature #^Spatial eye & {skip :skip :or {skip 0}}] 4.303 - (let [retinal-map (retina-sensor-image eye) 4.304 - camera (attach-eye creature eye) 4.305 - vision-image 4.306 - (atom 4.307 - (BufferedImage. (.getWidth camera) 4.308 - (.getHeight camera) 4.309 - BufferedImage/TYPE_BYTE_BINARY))] 4.310 - [(fn [world] 4.311 - (add-eye 4.312 - world camera 4.313 - (let [counter (atom 0)] 4.314 - (fn [r fb bb bi] 4.315 - (if (zero? (rem (swap! counter inc) (inc skip))) 4.316 - (reset! vision-image (BufferedImage! r fb bb bi))))))) 4.317 - (vec 4.318 - (map 4.319 - (fn [[key image]] 4.320 - (let [whites (white-coordinates image) 4.321 - topology (vec (collapse whites)) 4.322 - mask (presets key)] 4.323 - (fn [] 4.324 - (vector 4.325 - topology 4.326 - (vec 4.327 - (for [[x y] whites] 4.328 - (bit-and 4.329 - mask (.getRGB @vision-image x y)))))))) 4.330 - retinal-map))])) 4.331 - 4.332 -(defn vision 4.333 - [#^Node creature & {skip :skip :or {skip 0}}] 4.334 - (reduce 4.335 - (fn [[init-a senses-a] 4.336 - [init-b senses-b]] 4.337 - [(conj init-a init-b) 4.338 - (into senses-a senses-b)]) 4.339 - [[][]] 4.340 - (for [eye (creature-eyes creature)] 4.341 - (enable-vision creature eye)))) 4.342 4.343 4.344
5.1 --- a/org/util.org Fri Feb 03 05:08:45 2012 -0700 5.2 +++ b/org/util.org Fri Feb 03 05:52:18 2012 -0700 5.3 @@ -197,6 +197,13 @@ 5.4 [fn m] 5.5 (apply fn (reduce #(into %1 %2) [] m))) 5.6 5.7 +(defn map-vals 5.8 + "Transform a map by applying a function to its values, 5.9 + keeping the keys the same." 5.10 + [f m] (zipmap (keys m) (map f (vals m)))) 5.11 + 5.12 + 5.13 + 5.14 #+end_src 5.15 5.16 #+results: util