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