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