Mercurial > cortex
view org/sense.org @ 197:16cbce075a0b
reorganizing for website
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sun, 05 Feb 2012 06:55:41 -0700 |
parents | 22548d48cc85 |
children | fc0bf33bded2 |
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.org9 * Namespace/Imports10 #+name header11 #+begin_src clojure12 (ns cortex.sense13 "Here are functions useful in the construction of two or more14 sensors/effectors."15 {:author "Robert McInytre"}16 (:use (cortex world util))17 (:import ij.process.ImageProcessor)18 (:import jme3tools.converters.ImageToAwt)19 (:import java.awt.image.BufferedImage)20 (:import com.jme3.collision.CollisionResults)21 (:import com.jme3.bounding.BoundingBox)22 (:import (com.jme3.scene Node Spatial))23 (:import com.jme3.scene.control.AbstractControl)24 (:import (com.jme3.math Quaternion Vector3f)))25 #+end_src27 * Blender Utilities28 #+name: blender29 #+begin_src clojure30 (defn meta-data31 "Get the meta-data for a node created with blender."32 [blender-node key]33 (if-let [data (.getUserData blender-node "properties")]34 (.findValue data key)35 nil))37 (defn jme-to-blender38 "Convert from JME coordinates to Blender coordinates"39 [#^Vector3f in]40 (Vector3f. (.getX in)41 (- (.getZ in))42 (.getY in)))44 (defn blender-to-jme45 "Convert from Blender coordinates to JME coordinates"46 [#^Vector3f in]47 (Vector3f. (.getX in)48 (.getZ in)49 (- (.getY in))))50 #+end_src52 * Topology Related stuff53 #+name: topology54 #+begin_src clojure55 (defn load-image56 "Load an image as a BufferedImage using the asset-manager system."57 [asset-relative-path]58 (ImageToAwt/convert59 (.getImage (.loadTexture (asset-manager) asset-relative-path))60 false false 0))62 (def white 0xFFFFFF)64 (defn white? [rgb]65 (= (bit-and white rgb) white))67 (defn filter-pixels68 "List the coordinates of all pixels matching pred, within the bounds69 provided.70 bounds -> [x0 y0 width height]"71 {:author "Dylan Holmes"}72 ([pred #^BufferedImage image]73 (filter-pixels pred image [0 0 (.getWidth image) (.getHeight image)]))74 ([pred #^BufferedImage image [x0 y0 width height]]75 ((fn accumulate [x y matches]76 (cond77 (>= y (+ height y0)) matches78 (>= x (+ width x0)) (recur 0 (inc y) matches)79 (pred (.getRGB image x y))80 (recur (inc x) y (conj matches [x y]))81 :else (recur (inc x) y matches)))82 x0 y0 [])))84 (defn white-coordinates85 "Coordinates of all the white pixels in a subset of the image."86 ([#^BufferedImage image bounds]87 (filter-pixels white? image bounds))88 ([#^BufferedImage image]89 (filter-pixels white? image)))91 (defn points->image92 "Take a sparse collection of points and visuliaze it as a93 BufferedImage."94 [points]95 (if (empty? points)96 (BufferedImage. 1 1 BufferedImage/TYPE_BYTE_BINARY)97 (let [xs (vec (map first points))98 ys (vec (map second points))99 x0 (apply min xs)100 y0 (apply min ys)101 width (- (apply max xs) x0)102 height (- (apply max ys) y0)103 image (BufferedImage. (inc width) (inc height)104 BufferedImage/TYPE_INT_RGB)]105 (dorun106 (for [x (range (.getWidth image))107 y (range (.getHeight image))]108 (.setRGB image x y 0xFF0000)))109 (dorun110 (for [index (range (count points))]111 (.setRGB image (- (xs index) x0) (- (ys index) y0) -1)))112 image)))114 (defn average [coll]115 (/ (reduce + coll) (count coll)))117 (defn collapse-1d118 "One dimensional analogue of collapse."119 [center line]120 (let [length (count line)121 num-above (count (filter (partial < center) line))122 num-below (- length num-above)]123 (range (- center num-below)124 (+ center num-above))))126 (defn collapse127 "Take a set of pairs of integers and collapse them into a128 contigous bitmap with no \"holes\"."129 [points]130 (if (empty? points) []131 (let132 [num-points (count points)133 center (vector134 (int (average (map first points)))135 (int (average (map first points))))136 flattened137 (reduce138 concat139 (map140 (fn [column]141 (map vector142 (map first column)143 (collapse-1d (second center)144 (map second column))))145 (partition-by first (sort-by first points))))146 squeezed147 (reduce148 concat149 (map150 (fn [row]151 (map vector152 (collapse-1d (first center)153 (map first row))154 (map second row)))155 (partition-by second (sort-by second flattened))))156 relocated157 (let [min-x (apply min (map first squeezed))158 min-y (apply min (map second squeezed))]159 (map (fn [[x y]]160 [(- x min-x)161 (- y min-y)])162 squeezed))]163 relocated)))165 #+end_src167 * Node level stuff168 #+name: node169 #+begin_src clojure170 (defn closest-node171 "Return the node in creature which is closest to the given node."172 [#^Node creature #^Node eye]173 (loop [radius (float 0.01)]174 (let [results (CollisionResults.)]175 (.collideWith176 creature177 (BoundingBox. (.getWorldTranslation eye)178 radius radius radius)179 results)180 (if-let [target (first results)]181 (.getGeometry target)182 (recur (float (* 2 radius)))))))184 (defn bind-sense185 "Bind the sense to the Spatial such that it will maintain its186 current position relative to the Spatial no matter how the spatial187 moves. 'sense can be either a Camera or Listener object."188 [#^Spatial obj sense]189 (let [sense-offset (.subtract (.getLocation sense)190 (.getWorldTranslation obj))191 initial-sense-rotation (Quaternion. (.getRotation sense))192 base-anti-rotation (.inverse (.getWorldRotation obj))]193 (.addControl194 obj195 (proxy [AbstractControl] []196 (controlUpdate [tpf]197 (let [total-rotation198 (.mult base-anti-rotation (.getWorldRotation obj))]199 (.setLocation200 sense201 (.add202 (.mult total-rotation sense-offset)203 (.getWorldTranslation obj)))204 (.setRotation205 sense206 (.mult total-rotation initial-sense-rotation))))207 (controlRender [_ _])))))209 (defn world-to-local210 "Convert the world coordinates into coordinates relative to the211 object (i.e. local coordinates), taking into account the rotation212 of object."213 [#^Spatial object world-coordinate]214 (.worldToLocal object world-coordinate nil))216 (defn local-to-world217 "Convert the local coordinates into world relative coordinates"218 [#^Spatial object local-coordinate]219 (.localToWorld object local-coordinate nil))221 (defn sense-nodes222 "For each sense there is a special blender node whose children are223 considered markers for an instance of a that sense. This function224 generates functions to find those children, given the name of the225 special parent node."226 [parent-name]227 (fn [#^Node creature]228 (if-let [sense-node (.getChild creature parent-name)]229 (seq (.getChildren sense-node))230 (do (println-repl "could not find" parent-name "node") []))))231 #+end_src233 * Viewing Senses234 #+name view-senses235 #+begin_src clojure236 (defn view-sense237 "Take a kernel that produces a BufferedImage from some sense data238 and return a function which takes a list of sense data, uses the239 kernem to convert to images, and displays those images, each in240 its own JFrame."241 [sense-display-kernel]242 (let [windows (atom [])]243 (fn [data]244 (if (> (count data) (count @windows))245 (reset!246 windows (map (fn [_] (view-image)) (range (count data)))))247 (dorun248 (map249 (fn [display datum]250 (display (sense-display-kernel datum)))251 @windows data)))))253 (defn gray254 "Create a gray RGB pixel with R, G, and B set to num. num must be255 between 0 and 255."256 [num]257 (+ num258 (bit-shift-left num 8)259 (bit-shift-left num 16)))260 #+end_src262 * COMMENT generate source263 #+begin_src clojure :tangle ../src/cortex/sense.clj264 <<header>>265 <<blender>>266 <<topology>>267 <<node>>268 <<view-senses>>269 #+end_src