Mercurial > cortex
view org/sense.org @ 187:6142e85f5825
extracted common elements of display code
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 04 Feb 2012 09:42:19 -0700 |
parents | 21816b27d7c8 |
children | 22548d48cc85 |
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 #+name: sense10 #+begin_src clojure11 (ns cortex.sense12 "Here are functions useful in the construction of two or more13 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)))25 (defn meta-data26 "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))32 (defn closest-node33 "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 (.collideWith38 creature39 (BoundingBox. (.getWorldTranslation eye)40 radius radius radius)41 results)42 (if-let [target (first results)]43 (.getGeometry target)44 (recur (float (* 2 radius)))))))46 (defn bind-sense47 "Bind the sense to the Spatial such that it will maintain its48 current position relative to the Spatial no matter how the spatial49 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 (.addControl56 obj57 (proxy [AbstractControl] []58 (controlUpdate [tpf]59 (let [total-rotation60 (.mult base-anti-rotation (.getWorldRotation obj))]61 (.setLocation62 sense63 (.add64 (.mult total-rotation sense-offset)65 (.getWorldTranslation obj)))66 (.setRotation67 sense68 (.mult total-rotation initial-sense-rotation))))69 (controlRender [_ _])))))71 (def white 0xFFFFFF)73 (defn white? [rgb]74 (= (bit-and white rgb) white))76 (defn filter-pixels77 "List the coordinates of all pixels matching pred, within the bounds78 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 (cond86 (>= y (+ height y0)) matches87 (>= 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 [])))93 (defn white-coordinates94 "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)))100 (defn points->image101 "Take a sparse collection of points and visuliaze it as a102 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 (dorun115 (for [x (range (.getWidth image))116 y (range (.getHeight image))]117 (.setRGB image x y 0xFF0000)))118 (dorun119 (for [index (range (count points))]120 (.setRGB image (- (xs index) x0) (- (ys index) y0) -1)))121 image)))123 (defn average [coll]124 (/ (reduce + coll) (count coll)))126 (defn collapse-1d127 "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))))135 (defn collapse136 "Take a set of pairs of integers and collapse them into a137 contigous bitmap with no \"holes\"."138 [points]139 (if (empty? points) []140 (let141 [num-points (count points)142 center (vector143 (int (average (map first points)))144 (int (average (map first points))))145 flattened146 (reduce147 concat148 (map149 (fn [column]150 (map vector151 (map first column)152 (collapse-1d (second center)153 (map second column))))154 (partition-by first (sort-by first points))))155 squeezed156 (reduce157 concat158 (map159 (fn [row]160 (map vector161 (collapse-1d (first center)162 (map first row))163 (map second row)))164 (partition-by second (sort-by second flattened))))165 relocated166 (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)))174 (defn world-to-local175 "Convert the world coordinates into coordinates relative to the176 object (i.e. local coordinates), taking into account the rotation177 of object."178 [#^Spatial object world-coordinate]179 (.worldToLocal object world-coordinate nil))181 (defn local-to-world182 "Convert the local coordinates into world relative coordinates"183 [#^Spatial object local-coordinate]184 (.localToWorld object local-coordinate nil))186 (defn sense-nodes187 "For each sense there is a special blender node whose children are188 considered markers for an instance of a that sense. This function189 generates functions to find those children, given the name of the190 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") []))))197 (defn load-image198 "Load an image as a BufferedImage using the asset-manager system."199 [asset-relative-path]200 (ImageToAwt/convert201 (.getImage (.loadTexture (asset-manager) asset-relative-path))202 false false 0))204 (defn jme-to-blender205 "Convert from JME coordinates to Blender coordinates"206 [#^Vector3f in]207 (Vector3f. (.getX in)208 (- (.getZ in))209 (.getY in)))211 (defn blender-to-jme212 "Convert from Blender coordinates to JME coordinates"213 [#^Vector3f in]214 (Vector3f. (.getX in)215 (.getZ in)216 (- (.getY in))))219 (defn view-sense220 "Take a function that produces a BufferedImage from some sense data221 and return a function which takes a list of sense and displays222 those images in multiple JFrames."223 [sense-display-kernel]224 (let225 [windows (atom [])]226 (fn [data]227 (if (> (count data) (count @windows))228 (reset! windows (map (fn [_] (view-image))229 (range (count data)))))230 (dorun231 (map232 (fn [display gen data]233 (display (gen data)))234 @windows sense-display-kernel data)))))238 #+end_src241 * COMMENT generate source242 #+begin_src clojure :tangle ../src/cortex/sense.clj243 <<sense>>244 #+end_src