Mercurial > cortex
view org/sense-util.org @ 164:c33a8e5fe7bc
removed hearing-init-fns requirement, changed names
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 04 Feb 2012 03:29:59 -0700 |
parents | e8df6e76c3e5 |
children | 9e6a30b8c99a |
line wrap: on
line source
1 #+title: General sense/effector utilities2 #+author: Robert McIntyre3 #+email: rlm@mit.edu4 #+description: sensory utilities5 #+keywords: simulation, jMonkeyEngine3, clojure, simulated senses6 #+SETUPFILE: ../../aurellem/org/setup.org7 #+INCLUDE: ../../aurellem/org/level-0.org10 #+name: sense-util11 #+begin_src clojure12 (ns cortex.sense)13 (cortex.import/mega-import-jme3)14 (import ij.process.ImageProcessor)15 (import java.awt.image.BufferedImage)18 (defn meta-data [blender-node key]19 (if-let [data (.getUserData blender-node "properties")]20 (.findValue data key)21 nil))23 (defn closest-node24 "Return the object in creature which is closest to the given node."25 ;;dylan"The closest object in creature to the given node."26 [#^Node creature #^Node eye]27 (loop [radius (float 0.01)]28 (let [results (CollisionResults.)]29 (.collideWith30 creature31 (BoundingBox. (.getWorldTranslation eye)32 radius radius radius)33 results)34 (if-let [target (first results)]35 (.getGeometry target)36 (recur (float (* 2 radius)))))))38 (defn bind-sense39 "Bind the sense to the Spatial such that it will maintain its40 current position relative to the Spatial no matter how the spatial41 moves. 'sense can be either a Camera or Listener object."42 [#^Spatial obj sense]43 (let [sense-offset (.subtract (.getLocation sense)44 (.getWorldTranslation obj))45 initial-sense-rotation (Quaternion. (.getRotation sense))46 base-anti-rotation (.inverse (.getWorldRotation obj))]47 (.addControl48 obj49 (proxy [AbstractControl] []50 (controlUpdate [tpf]51 (let [total-rotation52 (.mult base-anti-rotation (.getWorldRotation obj))]53 (.setLocation sense54 (.add55 (.mult total-rotation sense-offset)56 (.getWorldTranslation obj)))57 (.setRotation sense58 (.mult total-rotation initial-sense-rotation))))59 (controlRender [_ _])))))61 (def white -1)63 (defn filter-pixels64 "List the coordinates of all pixels matching pred, within the bounds65 provided. Bounds -> [x0 y0 width height]"66 {:author "Dylan Holmes"}67 ([pred #^BufferedImage image]68 (filter-pixels pred image [0 0 (.getWidth image) (.getHeight image)]))69 ([pred #^BufferedImage image [x0 y0 width height]]70 ((fn accumulate [x y matches]71 (cond72 (>= y (+ height y0)) matches73 (>= x (+ width x0)) (recur 0 (inc y) matches)74 (pred (.getRGB image x y))75 (recur (inc x) y (conj matches [x y]))76 :else (recur (inc x) y matches)))77 x0 y0 [])))79 (defn white-coordinates80 "Coordinates of all the white pixels in a subset of the image."81 ([#^BufferedImage image bounds]82 (filter-pixels #(= % white) image bounds))83 ([#^BufferedImage image]84 (filter-pixels #(= % white) image)))86 (defn points->image87 "Take a sparse collection of points and visuliaze it as a88 BufferedImage."90 ;; TODO maybe parallelize this since it's easy92 [points]93 (if (empty? points)94 (BufferedImage. 1 1 BufferedImage/TYPE_BYTE_BINARY)95 (let [xs (vec (map first points))96 ys (vec (map second points))97 x0 (apply min xs)98 y0 (apply min ys)99 width (- (apply max xs) x0)100 height (- (apply max ys) y0)101 image (BufferedImage. (inc width) (inc height)102 BufferedImage/TYPE_INT_RGB)]103 (dorun104 (for [x (range (.getWidth image))105 y (range (.getHeight image))]106 (.setRGB image x y 0xFF0000)))107 (dorun108 (for [index (range (count points))]109 (.setRGB image (- (xs index) x0) (- (ys index) y0) -1)))111 image)))113 (defn average [coll]114 (/ (reduce + coll) (count coll)))116 (defn collapse-1d117 "One dimensional analogue of collapse"118 [center line]119 (let [length (count line)120 num-above (count (filter (partial < center) line))121 num-below (- length num-above)]122 (range (- center num-below)123 (+ center num-above))))125 (defn collapse126 "Take a set of pairs of integers and collapse them into a127 contigous bitmap."128 [points]129 (if (empty? points) []130 (let131 [num-points (count points)132 center (vector133 (int (average (map first points)))134 (int (average (map first points))))135 flattened136 (reduce137 concat138 (map139 (fn [column]140 (map vector141 (map first column)142 (collapse-1d (second center)143 (map second column))))144 (partition-by first (sort-by first points))))145 squeezed146 (reduce147 concat148 (map149 (fn [row]150 (map vector151 (collapse-1d (first center)152 (map first row))153 (map second row)))154 (partition-by second (sort-by second flattened))))155 relocate156 (let [min-x (apply min (map first squeezed))157 min-y (apply min (map second squeezed))]158 (map (fn [[x y]]159 [(- x min-x)160 (- y min-y)])161 squeezed))]162 relocate)))164 (defn world-to-local165 "Convert the world coordinates into coordinates relative to the166 object (i.e. local coordinates), taking into account the rotation167 of object."168 [#^Spatial object world-coordinate]169 (.worldToLocal object world-coordinate nil))171 (defn local-to-world172 "Convert the local coordinates into coordinates into world relative173 coordinates"174 [#^Spatial object local-coordinate]175 (.localToWorld object local-coordinate nil))178 (defn sense-nodes [parent-name]179 (fn [#^Node creature]180 (if-let [sense-node (.getChild creature parent-name)]181 (seq (.getChildren sense-node))182 (do (println-repl "could not find" parent-name "node") []))))185 #+end_src187 #+results: sense-util188 : #'cortex.sense/meta-data192 * COMMENT generate source193 #+begin_src clojure :tangle ../src/cortex/sense.clj194 <<sense-util>>195 #+end_src