Mercurial > cortex
diff org/sense.org @ 186:21816b27d7c8
moved sense.org to proper position.
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 04 Feb 2012 09:35:15 -0700 |
parents | sense.org@446b115bddc2 |
children | 6142e85f5825 |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/org/sense.org Sat Feb 04 09:35:15 2012 -0700 1.3 @@ -0,0 +1,223 @@ 1.4 +#+title: General sense/effector utilities 1.5 +#+author: Robert McIntyre 1.6 +#+email: rlm@mit.edu 1.7 +#+description: sensory utilities 1.8 +#+keywords: simulation, jMonkeyEngine3, clojure, simulated senses 1.9 +#+SETUPFILE: ../../aurellem/org/setup.org 1.10 +#+INCLUDE: ../../aurellem/org/level-0.org 1.11 + 1.12 +#+name: sense 1.13 +#+begin_src clojure 1.14 +(ns cortex.sense 1.15 + "Here are functions useful in the construction of two or more 1.16 + sensors/effectors." 1.17 + {:author "Robert McInytre"} 1.18 + (:use (cortex world util)) 1.19 + (:import ij.process.ImageProcessor) 1.20 + (:import jme3tools.converters.ImageToAwt) 1.21 + (:import java.awt.image.BufferedImage) 1.22 + (:import com.jme3.collision.CollisionResults) 1.23 + (:import com.jme3.bounding.BoundingBox) 1.24 + (:import (com.jme3.scene Node Spatial)) 1.25 + (:import com.jme3.scene.control.AbstractControl) 1.26 + (:import (com.jme3.math Quaternion Vector3f))) 1.27 + 1.28 +(defn meta-data 1.29 + "Get the meta-data for a node created with blender." 1.30 + [blender-node key] 1.31 + (if-let [data (.getUserData blender-node "properties")] 1.32 + (.findValue data key) 1.33 + nil)) 1.34 + 1.35 +(defn closest-node 1.36 + "Return the node in creature which is closest to the given node." 1.37 + [#^Node creature #^Node eye] 1.38 + (loop [radius (float 0.01)] 1.39 + (let [results (CollisionResults.)] 1.40 + (.collideWith 1.41 + creature 1.42 + (BoundingBox. (.getWorldTranslation eye) 1.43 + radius radius radius) 1.44 + results) 1.45 + (if-let [target (first results)] 1.46 + (.getGeometry target) 1.47 + (recur (float (* 2 radius))))))) 1.48 + 1.49 +(defn bind-sense 1.50 + "Bind the sense to the Spatial such that it will maintain its 1.51 + current position relative to the Spatial no matter how the spatial 1.52 + moves. 'sense can be either a Camera or Listener object." 1.53 + [#^Spatial obj sense] 1.54 + (let [sense-offset (.subtract (.getLocation sense) 1.55 + (.getWorldTranslation obj)) 1.56 + initial-sense-rotation (Quaternion. (.getRotation sense)) 1.57 + base-anti-rotation (.inverse (.getWorldRotation obj))] 1.58 + (.addControl 1.59 + obj 1.60 + (proxy [AbstractControl] [] 1.61 + (controlUpdate [tpf] 1.62 + (let [total-rotation 1.63 + (.mult base-anti-rotation (.getWorldRotation obj))] 1.64 + (.setLocation 1.65 + sense 1.66 + (.add 1.67 + (.mult total-rotation sense-offset) 1.68 + (.getWorldTranslation obj))) 1.69 + (.setRotation 1.70 + sense 1.71 + (.mult total-rotation initial-sense-rotation)))) 1.72 + (controlRender [_ _]))))) 1.73 + 1.74 +(def white 0xFFFFFF) 1.75 + 1.76 +(defn white? [rgb] 1.77 + (= (bit-and white rgb) white)) 1.78 + 1.79 +(defn filter-pixels 1.80 + "List the coordinates of all pixels matching pred, within the bounds 1.81 + provided. 1.82 + bounds -> [x0 y0 width height]" 1.83 + {:author "Dylan Holmes"} 1.84 + ([pred #^BufferedImage image] 1.85 + (filter-pixels pred image [0 0 (.getWidth image) (.getHeight image)])) 1.86 + ([pred #^BufferedImage image [x0 y0 width height]] 1.87 + ((fn accumulate [x y matches] 1.88 + (cond 1.89 + (>= y (+ height y0)) matches 1.90 + (>= x (+ width x0)) (recur 0 (inc y) matches) 1.91 + (pred (.getRGB image x y)) 1.92 + (recur (inc x) y (conj matches [x y])) 1.93 + :else (recur (inc x) y matches))) 1.94 + x0 y0 []))) 1.95 + 1.96 +(defn white-coordinates 1.97 + "Coordinates of all the white pixels in a subset of the image." 1.98 + ([#^BufferedImage image bounds] 1.99 + (filter-pixels white? image bounds)) 1.100 + ([#^BufferedImage image] 1.101 + (filter-pixels white? image))) 1.102 + 1.103 +(defn points->image 1.104 + "Take a sparse collection of points and visuliaze it as a 1.105 + BufferedImage." 1.106 + [points] 1.107 + (if (empty? points) 1.108 + (BufferedImage. 1 1 BufferedImage/TYPE_BYTE_BINARY) 1.109 + (let [xs (vec (map first points)) 1.110 + ys (vec (map second points)) 1.111 + x0 (apply min xs) 1.112 + y0 (apply min ys) 1.113 + width (- (apply max xs) x0) 1.114 + height (- (apply max ys) y0) 1.115 + image (BufferedImage. (inc width) (inc height) 1.116 + BufferedImage/TYPE_INT_RGB)] 1.117 + (dorun 1.118 + (for [x (range (.getWidth image)) 1.119 + y (range (.getHeight image))] 1.120 + (.setRGB image x y 0xFF0000))) 1.121 + (dorun 1.122 + (for [index (range (count points))] 1.123 + (.setRGB image (- (xs index) x0) (- (ys index) y0) -1))) 1.124 + image))) 1.125 + 1.126 +(defn average [coll] 1.127 + (/ (reduce + coll) (count coll))) 1.128 + 1.129 +(defn collapse-1d 1.130 + "One dimensional analogue of collapse." 1.131 + [center line] 1.132 + (let [length (count line) 1.133 + num-above (count (filter (partial < center) line)) 1.134 + num-below (- length num-above)] 1.135 + (range (- center num-below) 1.136 + (+ center num-above)))) 1.137 + 1.138 +(defn collapse 1.139 + "Take a set of pairs of integers and collapse them into a 1.140 + contigous bitmap with no \"holes\"." 1.141 + [points] 1.142 + (if (empty? points) [] 1.143 + (let 1.144 + [num-points (count points) 1.145 + center (vector 1.146 + (int (average (map first points))) 1.147 + (int (average (map first points)))) 1.148 + flattened 1.149 + (reduce 1.150 + concat 1.151 + (map 1.152 + (fn [column] 1.153 + (map vector 1.154 + (map first column) 1.155 + (collapse-1d (second center) 1.156 + (map second column)))) 1.157 + (partition-by first (sort-by first points)))) 1.158 + squeezed 1.159 + (reduce 1.160 + concat 1.161 + (map 1.162 + (fn [row] 1.163 + (map vector 1.164 + (collapse-1d (first center) 1.165 + (map first row)) 1.166 + (map second row))) 1.167 + (partition-by second (sort-by second flattened)))) 1.168 + relocated 1.169 + (let [min-x (apply min (map first squeezed)) 1.170 + min-y (apply min (map second squeezed))] 1.171 + (map (fn [[x y]] 1.172 + [(- x min-x) 1.173 + (- y min-y)]) 1.174 + squeezed))] 1.175 + relocated))) 1.176 + 1.177 +(defn world-to-local 1.178 + "Convert the world coordinates into coordinates relative to the 1.179 + object (i.e. local coordinates), taking into account the rotation 1.180 + of object." 1.181 + [#^Spatial object world-coordinate] 1.182 + (.worldToLocal object world-coordinate nil)) 1.183 + 1.184 +(defn local-to-world 1.185 + "Convert the local coordinates into world relative coordinates" 1.186 + [#^Spatial object local-coordinate] 1.187 + (.localToWorld object local-coordinate nil)) 1.188 + 1.189 +(defn sense-nodes 1.190 + "For each sense there is a special blender node whose children are 1.191 + considered markers for an instance of a that sense. This function 1.192 + generates functions to find those children, given the name of the 1.193 + special parent node." 1.194 + [parent-name] 1.195 + (fn [#^Node creature] 1.196 + (if-let [sense-node (.getChild creature parent-name)] 1.197 + (seq (.getChildren sense-node)) 1.198 + (do (println-repl "could not find" parent-name "node") [])))) 1.199 + 1.200 +(defn load-image 1.201 + "Load an image as a BufferedImage using the asset-manager system." 1.202 + [asset-relative-path] 1.203 + (ImageToAwt/convert 1.204 + (.getImage (.loadTexture (asset-manager) asset-relative-path)) 1.205 + false false 0)) 1.206 + 1.207 +(defn jme-to-blender 1.208 + "Convert from JME coordinates to Blender coordinates" 1.209 + [#^Vector3f in] 1.210 + (Vector3f. (.getX in) 1.211 + (- (.getZ in)) 1.212 + (.getY in))) 1.213 + 1.214 +(defn blender-to-jme 1.215 + "Convert from Blender coordinates to JME coordinates" 1.216 + [#^Vector3f in] 1.217 + (Vector3f. (.getX in) 1.218 + (.getZ in) 1.219 + (- (.getY in)))) 1.220 +#+end_src 1.221 + 1.222 + 1.223 +* COMMENT generate source 1.224 +#+begin_src clojure :tangle ../src/cortex/sense.clj 1.225 +<<sense>> 1.226 +#+end_src