annotate org/sense-util.org @ 178:6fba17a74a57

refactored touch
author Robert McIntyre <rlm@mit.edu>
date Sat, 04 Feb 2012 07:05:54 -0700
parents 9e6a30b8c99a
children 0f1c7921d967
rev   line source
rlm@151 1 #+title: General sense/effector utilities
rlm@151 2 #+author: Robert McIntyre
rlm@151 3 #+email: rlm@mit.edu
rlm@151 4 #+description: sensory utilities
rlm@151 5 #+keywords: simulation, jMonkeyEngine3, clojure, simulated senses
rlm@151 6 #+SETUPFILE: ../../aurellem/org/setup.org
rlm@151 7 #+INCLUDE: ../../aurellem/org/level-0.org
rlm@151 8
rlm@151 9
rlm@151 10 #+name: sense-util
rlm@151 11 #+begin_src clojure
rlm@151 12 (ns cortex.sense)
rlm@151 13 (cortex.import/mega-import-jme3)
rlm@151 14 (import ij.process.ImageProcessor)
rlm@151 15 (import java.awt.image.BufferedImage)
rlm@167 16 (use 'cortex.util)
rlm@167 17 (import jme3tools.converters.ImageToAwt)
rlm@151 18
rlm@151 19 (defn meta-data [blender-node key]
rlm@151 20 (if-let [data (.getUserData blender-node "properties")]
rlm@151 21 (.findValue data key)
rlm@151 22 nil))
rlm@151 23
rlm@151 24 (defn closest-node
rlm@151 25 "Return the object in creature which is closest to the given node."
rlm@151 26 ;;dylan"The closest object in creature to the given node."
rlm@151 27 [#^Node creature #^Node eye]
rlm@151 28 (loop [radius (float 0.01)]
rlm@151 29 (let [results (CollisionResults.)]
rlm@151 30 (.collideWith
rlm@151 31 creature
rlm@151 32 (BoundingBox. (.getWorldTranslation eye)
rlm@151 33 radius radius radius)
rlm@151 34 results)
rlm@151 35 (if-let [target (first results)]
rlm@151 36 (.getGeometry target)
rlm@151 37 (recur (float (* 2 radius)))))))
rlm@151 38
rlm@151 39 (defn bind-sense
rlm@151 40 "Bind the sense to the Spatial such that it will maintain its
rlm@151 41 current position relative to the Spatial no matter how the spatial
rlm@151 42 moves. 'sense can be either a Camera or Listener object."
rlm@151 43 [#^Spatial obj sense]
rlm@151 44 (let [sense-offset (.subtract (.getLocation sense)
rlm@151 45 (.getWorldTranslation obj))
rlm@151 46 initial-sense-rotation (Quaternion. (.getRotation sense))
rlm@151 47 base-anti-rotation (.inverse (.getWorldRotation obj))]
rlm@151 48 (.addControl
rlm@151 49 obj
rlm@151 50 (proxy [AbstractControl] []
rlm@151 51 (controlUpdate [tpf]
rlm@151 52 (let [total-rotation
rlm@151 53 (.mult base-anti-rotation (.getWorldRotation obj))]
rlm@151 54 (.setLocation sense
rlm@151 55 (.add
rlm@151 56 (.mult total-rotation sense-offset)
rlm@151 57 (.getWorldTranslation obj)))
rlm@151 58 (.setRotation sense
rlm@151 59 (.mult total-rotation initial-sense-rotation))))
rlm@151 60 (controlRender [_ _])))))
rlm@151 61
rlm@151 62 (def white -1)
rlm@151 63
rlm@151 64 (defn filter-pixels
rlm@151 65 "List the coordinates of all pixels matching pred, within the bounds
rlm@151 66 provided. Bounds -> [x0 y0 width height]"
rlm@151 67 {:author "Dylan Holmes"}
rlm@151 68 ([pred #^BufferedImage image]
rlm@151 69 (filter-pixels pred image [0 0 (.getWidth image) (.getHeight image)]))
rlm@151 70 ([pred #^BufferedImage image [x0 y0 width height]]
rlm@151 71 ((fn accumulate [x y matches]
rlm@151 72 (cond
rlm@151 73 (>= y (+ height y0)) matches
rlm@151 74 (>= x (+ width x0)) (recur 0 (inc y) matches)
rlm@151 75 (pred (.getRGB image x y))
rlm@151 76 (recur (inc x) y (conj matches [x y]))
rlm@151 77 :else (recur (inc x) y matches)))
rlm@151 78 x0 y0 [])))
rlm@151 79
rlm@151 80 (defn white-coordinates
rlm@151 81 "Coordinates of all the white pixels in a subset of the image."
rlm@151 82 ([#^BufferedImage image bounds]
rlm@151 83 (filter-pixels #(= % white) image bounds))
rlm@151 84 ([#^BufferedImage image]
rlm@151 85 (filter-pixels #(= % white) image)))
rlm@151 86
rlm@151 87 (defn points->image
rlm@151 88 "Take a sparse collection of points and visuliaze it as a
rlm@151 89 BufferedImage."
rlm@151 90
rlm@151 91 ;; TODO maybe parallelize this since it's easy
rlm@151 92
rlm@151 93 [points]
rlm@151 94 (if (empty? points)
rlm@151 95 (BufferedImage. 1 1 BufferedImage/TYPE_BYTE_BINARY)
rlm@151 96 (let [xs (vec (map first points))
rlm@151 97 ys (vec (map second points))
rlm@151 98 x0 (apply min xs)
rlm@151 99 y0 (apply min ys)
rlm@151 100 width (- (apply max xs) x0)
rlm@151 101 height (- (apply max ys) y0)
rlm@151 102 image (BufferedImage. (inc width) (inc height)
rlm@151 103 BufferedImage/TYPE_INT_RGB)]
rlm@151 104 (dorun
rlm@151 105 (for [x (range (.getWidth image))
rlm@151 106 y (range (.getHeight image))]
rlm@151 107 (.setRGB image x y 0xFF0000)))
rlm@151 108 (dorun
rlm@151 109 (for [index (range (count points))]
rlm@151 110 (.setRGB image (- (xs index) x0) (- (ys index) y0) -1)))
rlm@151 111
rlm@151 112 image)))
rlm@151 113
rlm@151 114 (defn average [coll]
rlm@151 115 (/ (reduce + coll) (count coll)))
rlm@151 116
rlm@151 117 (defn collapse-1d
rlm@151 118 "One dimensional analogue of collapse"
rlm@151 119 [center line]
rlm@151 120 (let [length (count line)
rlm@151 121 num-above (count (filter (partial < center) line))
rlm@151 122 num-below (- length num-above)]
rlm@151 123 (range (- center num-below)
rlm@151 124 (+ center num-above))))
rlm@151 125
rlm@151 126 (defn collapse
rlm@151 127 "Take a set of pairs of integers and collapse them into a
rlm@151 128 contigous bitmap."
rlm@151 129 [points]
rlm@151 130 (if (empty? points) []
rlm@151 131 (let
rlm@151 132 [num-points (count points)
rlm@151 133 center (vector
rlm@151 134 (int (average (map first points)))
rlm@151 135 (int (average (map first points))))
rlm@151 136 flattened
rlm@151 137 (reduce
rlm@151 138 concat
rlm@151 139 (map
rlm@151 140 (fn [column]
rlm@151 141 (map vector
rlm@151 142 (map first column)
rlm@151 143 (collapse-1d (second center)
rlm@151 144 (map second column))))
rlm@151 145 (partition-by first (sort-by first points))))
rlm@151 146 squeezed
rlm@151 147 (reduce
rlm@151 148 concat
rlm@151 149 (map
rlm@151 150 (fn [row]
rlm@151 151 (map vector
rlm@151 152 (collapse-1d (first center)
rlm@151 153 (map first row))
rlm@151 154 (map second row)))
rlm@151 155 (partition-by second (sort-by second flattened))))
rlm@151 156 relocate
rlm@151 157 (let [min-x (apply min (map first squeezed))
rlm@151 158 min-y (apply min (map second squeezed))]
rlm@151 159 (map (fn [[x y]]
rlm@151 160 [(- x min-x)
rlm@151 161 (- y min-y)])
rlm@151 162 squeezed))]
rlm@151 163 relocate)))
rlm@151 164
rlm@156 165 (defn world-to-local
rlm@156 166 "Convert the world coordinates into coordinates relative to the
rlm@156 167 object (i.e. local coordinates), taking into account the rotation
rlm@156 168 of object."
rlm@156 169 [#^Spatial object world-coordinate]
rlm@156 170 (.worldToLocal object world-coordinate nil))
rlm@156 171
rlm@156 172 (defn local-to-world
rlm@156 173 "Convert the local coordinates into coordinates into world relative
rlm@156 174 coordinates"
rlm@156 175 [#^Spatial object local-coordinate]
rlm@156 176 (.localToWorld object local-coordinate nil))
rlm@156 177
rlm@164 178
rlm@164 179 (defn sense-nodes [parent-name]
rlm@164 180 (fn [#^Node creature]
rlm@164 181 (if-let [sense-node (.getChild creature parent-name)]
rlm@164 182 (seq (.getChildren sense-node))
rlm@164 183 (do (println-repl "could not find" parent-name "node") []))))
rlm@164 184
rlm@167 185 (defn load-image
rlm@167 186 "Load an image as a BufferedImage using the asset-manager system."
rlm@167 187 [asset-relative-path]
rlm@167 188 (ImageToAwt/convert
rlm@167 189 (.getImage (.loadTexture (asset-manager) asset-relative-path))
rlm@167 190 false false 0))
rlm@167 191
rlm@164 192
rlm@151 193 #+end_src
rlm@151 194
rlm@151 195 #+results: sense-util
rlm@151 196 : #'cortex.sense/meta-data
rlm@151 197
rlm@151 198
rlm@151 199
rlm@151 200 * COMMENT generate source
rlm@151 201 #+begin_src clojure :tangle ../src/cortex/sense.clj
rlm@151 202 <<sense-util>>
rlm@151 203 #+end_src