Mercurial > cortex
view org/test-creature.org @ 101:65332841b7d9
topological sensor bundling appears to work
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 14 Jan 2012 04:28:37 -0700 |
parents | 940074adc1d5 |
children | 7eeb940bcbc8 |
line wrap: on
line source
1 #+title: First attempt at a creature!2 #+author: Robert McIntyre3 #+email: rlm@mit.edu4 #+description:5 #+keywords: simulation, jMonkeyEngine3, clojure6 #+SETUPFILE: ../../aurellem/org/setup.org7 #+INCLUDE: ../../aurellem/org/level-0.org10 * objectives11 - [ ] get an overall bitmap-like image for touch12 - [ ] write code to visuliaze this bitmap13 - [ ] directly change the UV-pixels to show touch sensor activation14 - [ ] write an explination for why b&w bitmaps for senses is appropiate15 - [ ] clean up touch code and write visulazation test16 - [ ] do the same for eyes18 * Intro19 So far, I've made the following senses --20 - Vision21 - Hearing22 - Touch23 - Proprioception25 And one effector:26 - Movement28 However, the code so far has only enabled these senses, but has not29 actually implemented them. For example, there is still a lot of work30 to be done for vision. I need to be able to create an /eyeball/ in31 simulation that can be moved around and see the world from different32 angles. I also need to determine weather to use log-polar or cartesian33 for the visual input, and I need to determine how/wether to34 disceritise the visual input.36 I also want to be able to visualize both the sensors and the37 effectors in pretty pictures. This semi-retarted creature will by my38 first attempt at bringing everything together.40 * The creature's body42 Still going to do an eve-like body in blender, but due to problems43 importing the joints, etc into jMonkeyEngine3, I',m going to do all44 the connecting here in clojure code, using the names of the individual45 components and trial and error. Later, I'll maybe make some sort of46 creature-building modifications to blender that support whatever47 discreitized senses I'm going to make.49 #+name: body-150 #+begin_src clojure51 (ns cortex.silly52 "let's play!"53 {:author "Robert McIntyre"})55 ;; TODO remove this!56 (require 'cortex.import)57 (cortex.import/mega-import-jme3)58 (use '(cortex world util body hearing touch vision))60 (rlm.rlm-commands/help)61 (import java.awt.image.BufferedImage)62 (import javax.swing.JPanel)63 (import javax.swing.SwingUtilities)64 (import java.awt.Dimension)65 (import javax.swing.JFrame)66 (import java.awt.Dimension)67 (declare joint-create)69 (defn view-image70 "Initailizes a JPanel on which you may draw a BufferedImage.71 Returns a function that accepts a BufferedImage and draws it to the72 JPanel."73 []74 (let [image75 (atom76 (BufferedImage. 1 1 BufferedImage/TYPE_4BYTE_ABGR))77 panel78 (proxy [JPanel] []79 (paint80 [graphics]81 (proxy-super paintComponent graphics)82 (.drawImage graphics @image 0 0 nil)))83 frame (JFrame. "Display Image")]84 (SwingUtilities/invokeLater85 (fn []86 (doto frame87 (-> (.getContentPane) (.add panel))88 (.pack)89 (.setLocationRelativeTo nil)90 (.setResizable true)91 (.setVisible true))))92 (fn [#^BufferedImage i]93 (reset! image i)94 (.setSize frame (+ 8 (.getWidth i)) (+ 28 (.getHeight i)))95 (.repaint panel 0 0 (.getWidth i) (.getHeight i)))))97 (defn points->image98 "Take a sparse collection of points and visuliaze it as a99 BufferedImage."100 [points]101 (let [xs (vec (map first points))102 ys (vec (map second points))103 x0 (apply min xs)104 y0 (apply min ys)105 width (- (apply max xs) x0)106 height (- (apply max ys) y0)107 image (BufferedImage. (inc width) (inc height)108 BufferedImage/TYPE_BYTE_BINARY)]109 (dorun110 (for [index (range (count points))]111 (.setRGB image (- (xs index) x0) (- (ys index) y0) -1)))113 image))118 ;;(defn visualize [points]120 (defn test-data121 []122 (vec123 (for [a (range 0 100 2)124 b (range 0 100 2)]125 (vector a b))126 ))128 (defn average [coll]129 (/ (reduce + coll) (count coll)))131 (defn collapse-1d132 "One dimensional analogue of collapse"133 [center line]134 (let [length (count line)135 num-above (count (filter (partial < center) line))136 num-below (- length num-above)]137 (range (- center num-below)138 (+ center num-above))139 ))141 (defn collapse142 "Take a set of pairs of integers and collapse them into a143 contigous bitmap."144 [points]145 (let146 [num-points (count points)147 center (vector148 (average (map first points))149 (average (map first points)))150 flattened151 (reduce152 concat153 (map154 (fn [column]155 (map vector156 (map first column)157 (collapse-1d (second center)158 (map second column))))159 (partition-by first (sort-by first points))))160 squeezed161 (reduce162 concat163 (map164 (fn [row]165 (map vector166 (collapse-1d (first center)167 (map first row))168 (map second row)))169 (partition-by second (sort-by second flattened))))]170 squeezed171 ))175 (defn load-bullet []176 (let [sim (world (Node.) {} no-op no-op)]177 (.enqueue178 sim179 (fn []180 (.stop sim)))181 (.start sim)))183 (defn load-blender-model184 "Load a .blend file using an asset folder relative path."185 [^String model]186 (.loadModel187 (doto (asset-manager)188 (.registerLoader BlenderModelLoader (into-array String ["blend"])))189 model))191 (defn meta-data [blender-node key]192 (if-let [data (.getUserData blender-node "properties")]193 (.findValue data key)194 nil))196 (defn blender-to-jme197 "Convert from Blender coordinates to JME coordinates"198 [#^Vector3f in]199 (Vector3f. (.getX in)200 (.getZ in)201 (- (.getY in))))203 (defn jme-to-blender204 "Convert from JME coordinates to Blender coordinates"205 [#^Vector3f in]206 (Vector3f. (.getX in)207 (- (.getZ in))208 (.getY in)))210 (defn joint-targets211 "Return the two closest two objects to the joint object, ordered212 from bottom to top according to the joint's rotation."213 [#^Node parts #^Node joint]214 ;;(println (meta-data joint "joint"))215 (.getWorldRotation joint)216 (loop [radius (float 0.01)]217 (let [results (CollisionResults.)]218 (.collideWith219 parts220 (BoundingBox. (.getWorldTranslation joint)221 radius radius radius)222 results)223 (let [targets224 (distinct225 (map #(.getGeometry %) results))]226 (if (>= (count targets) 2)227 (sort-by228 #(let [v229 (jme-to-blender230 (.mult231 (.inverse (.getWorldRotation joint))232 (.subtract (.getWorldTranslation %)233 (.getWorldTranslation joint))))]234 (println-repl (.getName %) ":" v)235 (.dot (Vector3f. 1 1 1)236 v))237 (take 2 targets))238 (recur (float (* radius 2))))))))240 (defn world-to-local241 "Convert the world coordinates into coordinates relative to the242 object (i.e. local coordinates), taking into account the rotation243 of object."244 [#^Spatial object world-coordinate]245 (let [out (Vector3f.)]246 (.worldToLocal object world-coordinate out) out))248 (defn local-to-world249 "Convert the local coordinates into coordinates into world relative250 coordinates"251 [#^Spatial object local-coordinate]252 (let [world-coordinate (Vector3f.)]253 (.localToWorld object local-coordinate world-coordinate)254 world-coordinate))257 (defmulti joint-dispatch258 "Translate blender pseudo-joints into real JME joints."259 (fn [constraints & _]260 (:type constraints)))262 (defmethod joint-dispatch :point263 [constraints control-a control-b pivot-a pivot-b rotation]264 (println-repl "creating POINT2POINT joint")265 (Point2PointJoint.266 control-a267 control-b268 pivot-a269 pivot-b))271 (defmethod joint-dispatch :hinge272 [constraints control-a control-b pivot-a pivot-b rotation]273 (println-repl "creating HINGE joint")274 (let [axis275 (if-let276 [axis (:axis constraints)]277 axis278 Vector3f/UNIT_X)279 [limit-1 limit-2] (:limit constraints)280 hinge-axis281 (.mult282 rotation283 (blender-to-jme axis))]284 (doto285 (HingeJoint.286 control-a287 control-b288 pivot-a289 pivot-b290 hinge-axis291 hinge-axis)292 (.setLimit limit-1 limit-2))))294 (defmethod joint-dispatch :cone295 [constraints control-a control-b pivot-a pivot-b rotation]296 (let [limit-xz (:limit-xz constraints)297 limit-xy (:limit-xy constraints)298 twist (:twist constraints)]300 (println-repl "creating CONE joint")301 (println-repl rotation)302 (println-repl303 "UNIT_X --> " (.mult rotation (Vector3f. 1 0 0)))304 (println-repl305 "UNIT_Y --> " (.mult rotation (Vector3f. 0 1 0)))306 (println-repl307 "UNIT_Z --> " (.mult rotation (Vector3f. 0 0 1)))308 (doto309 (ConeJoint.310 control-a311 control-b312 pivot-a313 pivot-b314 rotation315 rotation)316 (.setLimit (float limit-xz)317 (float limit-xy)318 (float twist)))))320 (defn connect321 "here are some examples:322 {:type :point}323 {:type :hinge :limit [0 (/ Math/PI 2)] :axis (Vector3f. 0 1 0)}324 (:axis defaults to (Vector3f. 1 0 0) if not provided for hinge joints)326 {:type :cone :limit-xz 0]327 :limit-xy 0]328 :twist 0]} (use XZY rotation mode in blender!)"329 [#^Node obj-a #^Node obj-b #^Node joint]330 (let [control-a (.getControl obj-a RigidBodyControl)331 control-b (.getControl obj-b RigidBodyControl)332 joint-center (.getWorldTranslation joint)333 joint-rotation (.toRotationMatrix (.getWorldRotation joint))334 pivot-a (world-to-local obj-a joint-center)335 pivot-b (world-to-local obj-b joint-center)]337 (if-let [constraints338 (map-vals339 eval340 (read-string341 (meta-data joint "joint")))]342 ;; A side-effect of creating a joint registers343 ;; it with both physics objects which in turn344 ;; will register the joint with the physics system345 ;; when the simulation is started.346 (do347 (println-repl "creating joint between"348 (.getName obj-a) "and" (.getName obj-b))349 (joint-dispatch constraints350 control-a control-b351 pivot-a pivot-b352 joint-rotation))353 (println-repl "could not find joint meta-data!"))))355 (defn assemble-creature [#^Node pieces joints]356 (dorun357 (map358 (fn [geom]359 (let [physics-control360 (RigidBodyControl.361 (HullCollisionShape.362 (.getMesh geom))363 (if-let [mass (meta-data geom "mass")]364 (do365 (println-repl366 "setting" (.getName geom) "mass to" (float mass))367 (float mass))368 (float 1)))]370 (.addControl geom physics-control)))371 (filter #(isa? (class %) Geometry )372 (node-seq pieces))))373 (dorun374 (map375 (fn [joint]376 (let [[obj-a obj-b]377 (joint-targets pieces joint)]378 (connect obj-a obj-b joint)))379 joints))380 pieces)382 (defn blender-creature [blender-path]383 (let [model (load-blender-model blender-path)384 joints385 (if-let [joint-node (.getChild model "joints")]386 (seq (.getChildren joint-node))387 (do (println-repl "could not find joints node")388 []))]389 (assemble-creature model joints)))391 (def hand "Models/creature1/one.blend")393 (def worm "Models/creature1/try-again.blend")395 (def touch "Models/creature1/touch.blend")397 (defn worm-model [] (load-blender-model worm))399 (defn x-ray [#^ColorRGBA color]400 (doto (Material. (asset-manager)401 "Common/MatDefs/Misc/Unshaded.j3md")402 (.setColor "Color" color)403 (-> (.getAdditionalRenderState)404 (.setDepthTest false))))406 (defn test-creature [thing]407 (let [x-axis408 (box 1 0.01 0.01 :physical? false :color ColorRGBA/Red)409 y-axis410 (box 0.01 1 0.01 :physical? false :color ColorRGBA/Green)411 z-axis412 (box 0.01 0.01 1 :physical? false :color ColorRGBA/Blue)]413 (world414 (nodify [(blender-creature thing)415 (box 10 2 10 :position (Vector3f. 0 -9 0)416 :color ColorRGBA/Gray :mass 0)417 x-axis y-axis z-axis418 ])419 standard-debug-controls420 (fn [world]421 (light-up-everything world)422 (enable-debug world)423 ;;(com.aurellem.capture.Capture/captureVideo424 ;; world (file-str "/home/r/proj/ai-videos/hand"))425 (.setTimer world (NanoTimer.))426 (set-gravity world (Vector3f. 0 0 0))427 (speed-up world)428 )429 no-op430 ;;(let [timer (atom 0)]431 ;; (fn [_ _]432 ;; (swap! timer inc)433 ;; (if (= (rem @timer 60) 0)434 ;; (println-repl (float (/ @timer 60))))))435 )))437 (defn colorful []438 (.getChild (worm-model) "worm-21"))440 (import jme3tools.converters.ImageToAwt)442 (import ij.ImagePlus)444 (defn triangle-indices445 "Get the triangle vertex indices of a given triangle from a given446 mesh."447 [#^Mesh mesh triangle-index]448 (let [indices (int-array 3)]449 (.getTriangle mesh triangle-index indices)450 (vec indices)))452 (defn uv-coord453 "Get the uv-coordinates of the vertex named by vertex-index"454 [#^Mesh mesh vertex-index]455 (let [UV-buffer456 (.getData457 (.getBuffer458 mesh459 VertexBuffer$Type/TexCoord))]460 (Vector2f.461 (.get UV-buffer (* vertex-index 2))462 (.get UV-buffer (+ 1 (* vertex-index 2))))))464 (defn tri-uv-coord465 "Get the uv-cooridnates of the triangle's verticies."466 [#^Mesh mesh #^Triangle triangle]467 (map (partial uv-coord mesh)468 (triangle-indices mesh (.getIndex triangle))))470 (defn touch-receptor-image471 "Return the touch-sensor distribution image in ImagePlus format, or472 nil if it does not exist."473 [#^Geometry obj]474 (let [mat (.getMaterial obj)]475 (if-let [texture-param476 (.getTextureParam477 mat478 MaterialHelper/TEXTURE_TYPE_DIFFUSE)]479 (let480 [texture481 (.getTextureValue texture-param)482 im (.getImage texture)]483 (ImagePlus.484 "UV-map"485 (ImageToAwt/convert im false false 0))))))487 (import ij.process.ImageProcessor)488 (import java.awt.image.BufferedImage)490 (defprotocol Frame491 (frame [this]))493 (extend-type BufferedImage494 Frame495 (frame [image]496 (merge497 (apply498 hash-map499 (interleave500 (doall (for [x (range (.getWidth image)) y (range (.getHeight image))]501 (vector x y)))502 (doall (for [x (range (.getWidth image)) y (range (.getHeight image))]503 (let [data (.getRGB image x y)]504 (hash-map :r (bit-shift-right (bit-and 0xff0000 data) 16)505 :g (bit-shift-right (bit-and 0x00ff00 data) 8)506 :b (bit-and 0x0000ff data)))))))507 {:width (.getWidth image) :height (.getHeight image)})))510 (extend-type ImagePlus511 Frame512 (frame [image+]513 (frame (.getBufferedImage image+))))516 (def white -1)518 (defn filter-pixels519 "List the coordinates of all pixels matching pred."520 {:author "Dylan Holmes"}521 [pred #^ImageProcessor ip]522 (let523 [width (.getWidth ip)524 height (.getHeight ip)]525 ((fn accumulate [x y matches]526 (cond527 (>= y height) matches528 (>= x width) (recur 0 (inc y) matches)529 (pred (.getPixel ip x y))530 (recur (inc x) y (conj matches (Vector2f. x y)))531 :else (recur (inc x) y matches)))532 0 0 [])))534 (defn white-coordinates535 "List the coordinates of all the white pixels in an image."536 [#^ImageProcessor ip]537 (filter-pixels #(= % white) ip))539 (defn same-side? [p1 p2 ref p]540 (<=541 0542 (.dot543 (.cross (.subtract p2 p1) (.subtract p p1))544 (.cross (.subtract p2 p1) (.subtract ref p1)))))547 (defn triangle->matrix4f548 "Converts the triangle into a 4x4 matrix of vertices: The first549 three columns contain the vertices of the triangle; the last550 contains the unit normal of the triangle. The bottom row is filled551 with 1s."552 [#^Triangle t]553 (let [mat (Matrix4f.)554 [vert-1 vert-2 vert-3]555 ((comp vec map) #(.get t %) (range 3))556 unit-normal (do (.calculateNormal t)(.getNormal t))557 vertices [vert-1 vert-2 vert-3 unit-normal]]559 (dorun560 (for [row (range 4) col (range 3)]561 (do562 (.set mat col row (.get (vertices row)col))563 (.set mat 3 row 1))))564 mat))566 (defn triangle-transformation567 "Returns the affine transformation that converts each vertex in the568 first triangle into the corresponding vertex in the second569 triangle."570 [#^Triangle tri-1 #^Triangle tri-2]571 (.mult572 (triangle->matrix4f tri-2)573 (.invert (triangle->matrix4f tri-1))))575 (def death (Triangle.576 (Vector3f. 1 1 1)577 (Vector3f. 1 2 3)578 (Vector3f. 5 6 7)))580 (def death-2 (Triangle.581 (Vector3f. 2 2 2)582 (Vector3f. 1 1 1)583 (Vector3f. 0 1 0)))585 (defn vector2f->vector3f [v]586 (Vector3f. (.getX v) (.getY v) 0))589 (extend-type Triangle590 Textual591 (text [t]592 (println "Triangle: " \newline (.get1 t) \newline593 (.get2 t) \newline (.get3 t))))596 (defn map-triangle [f #^Triangle tri]597 (Triangle.598 (f 0 (.get1 tri))599 (f 1 (.get2 tri))600 (f 2 (.get3 tri))))602 (defn triangle-seq [#^Triangle tri]603 [(.get1 tri) (.get2 tri) (.get3 tri)])605 (defn vector3f-seq [#^Vector3f v]606 [(.getX v) (.getY v) (.getZ v)])608 (defn inside-triangle?609 "Is the point inside the triangle? Now what do we do?610 You might want to hold on there"611 {:author "Dylan Holmes"}612 [tri p]613 (let [[vert-1 vert-2 vert-3] (triangle-seq tri)]614 (and615 (same-side? vert-1 vert-2 vert-3 p)616 (same-side? vert-2 vert-3 vert-1 p)617 (same-side? vert-3 vert-1 vert-2 p))))619 (defn uv-triangle620 "Convert the mesh triangle into the cooresponding triangle in621 UV-space. Z-component of these triangles is always zero."622 [#^Mesh mesh #^Triangle tri]623 (apply #(Triangle. %1 %2 %3)624 (map vector2f->vector3f625 (tri-uv-coord mesh tri))))627 (defn pixel-triangle628 "Convert the mesh triange into the corresponding triangle in629 UV-pixel-space. Z compenent will be zero."630 [#^Mesh mesh #^Triangle tri width height]631 (map-triangle (fn [_ v]632 (Vector3f. (* width (.getX v))633 (* height (.getY v))634 0))635 (uv-triangle mesh tri)))637 (def rasterize pixel-triangle)640 (defn triangle-bounds641 "Dimensions of the bounding square of the triangle in the form642 [x y width height].643 Assumes that the triangle lies in the XY plane."644 [#^Triangle tri]645 (let [verts (map vector3f-seq (triangle-seq tri))646 x (apply min (map first verts))647 y (apply min (map second verts))]649 [x y650 (- (apply max (map first verts)) x)651 (- (apply max (map second verts)) y)652 ]))655 (defn locate-feelers656 "Search the geometry's tactile UV image for touch sensors, returning657 their positions in geometry-relative coordinates."658 [#^Geometry geo]659 (if-let [image (touch-receptor-image geo)]660 (let [mesh (.getMesh geo)661 tris (triangles geo)664 width (.getWidth image)665 height (.getHeight image)667 ;; for each triangle668 sensor-coords669 (fn [tri]670 ;; translate triangle to uv-pixel-space671 (let [uv-tri672 (pixel-triangle mesh tri width height)673 bounds (vec (triangle-bounds uv-tri))]675 ;; get that part of the picture677 (apply #(.setRoi image %1 %2 %3 %4) bounds)678 (let [cutout (.crop (.getProcessor image))679 ;; extract white pixels inside triangle680 cutout-tri681 (map-triangle682 (fn [_ v]683 (.subtract684 v685 (Vector3f. (bounds 0) (bounds 1) (float 0))))686 uv-tri)687 whites (filter (partial inside-triangle? cutout-tri)688 (map vector2f->vector3f689 (white-coordinates cutout)))690 ;; translate pixel coordinates to world-space691 transform (triangle-transformation cutout-tri tri)]692 (map #(.mult transform %) whites))))]693 (vec (map sensor-coords tris)))694 (repeat (count (triangles geo)) [])))696 (defn enable-touch [#^Geometry geo]697 (let [feeler-coords (locate-feelers geo)698 tris (triangles geo)699 limit 0.1]700 (fn [node]701 (let [sensor-origins702 (map703 #(map (partial local-to-world geo) %)704 feeler-coords)705 triangle-normals706 (map (partial get-ray-direction geo)707 tris)708 rays709 (flatten710 (map (fn [origins norm]711 (map #(doto (Ray. % norm)712 (.setLimit limit)) origins))713 sensor-origins triangle-normals))]714 (for [ray rays]715 (do716 (let [results (CollisionResults.)]717 (.collideWith node ray results)718 (let [touch-objects719 (set720 (filter #(not (= geo %))721 (map #(.getGeometry %) results)))]722 (if (> (count touch-objects) 0)723 1 0)))))))))725 (defn touch [#^Node pieces]726 (let [touch-components727 (map enable-touch728 (filter #(isa? (class %) Geometry)729 (node-seq pieces)))]730 (fn [node]731 (reduce into [] (map #(% node) touch-components)))))733 (defn all-names []734 (concat735 (re-split #"\n" (slurp (file-str736 "/home/r/proj/names/dist.female.first")))737 (re-split #"\n" (slurp (file-str738 "/home/r/proj/names/dist.male.first")))739 (re-split #"\n" (slurp (file-str740 "/home/r/proj/names/dist.all.last")))))750 (defrecord LulzLoader [])751 (defprotocol Lulzable (load-lulz [this]))752 (extend-type LulzLoader753 Lulzable754 (load-lulz [this] (println "the lulz have arrived!")))757 (defn world-setup [joint]758 (let [joint-position (Vector3f. 0 0 0)759 joint-rotation760 (.toRotationMatrix761 (.mult762 (doto (Quaternion.)763 (.fromAngleAxis764 (* 1 (/ Math/PI 4))765 (Vector3f. -1 0 0)))766 (doto (Quaternion.)767 (.fromAngleAxis768 (* 1 (/ Math/PI 2))769 (Vector3f. 0 0 1)))))770 top-position (.mult joint-rotation (Vector3f. 8 0 0))772 origin (doto773 (sphere 0.1 :physical? false :color ColorRGBA/Cyan774 :position top-position))775 top (doto776 (sphere 0.1 :physical? false :color ColorRGBA/Yellow777 :position top-position)779 (.addControl780 (RigidBodyControl.781 (CapsuleCollisionShape. 0.5 1.5 1) (float 20))))782 bottom (doto783 (sphere 0.1 :physical? false :color ColorRGBA/DarkGray784 :position (Vector3f. 0 0 0))785 (.addControl786 (RigidBodyControl.787 (CapsuleCollisionShape. 0.5 1.5 1) (float 0))))788 table (box 10 2 10 :position (Vector3f. 0 -20 0)789 :color ColorRGBA/Gray :mass 0)790 a (.getControl top RigidBodyControl)791 b (.getControl bottom RigidBodyControl)]793 (cond794 (= joint :cone)796 (doto (ConeJoint.797 a b798 (world-to-local top joint-position)799 (world-to-local bottom joint-position)800 joint-rotation801 joint-rotation802 )805 (.setLimit (* (/ 10) Math/PI)806 (* (/ 4) Math/PI)807 0)))808 [origin top bottom table]))810 (defn test-joint [joint]811 (let [[origin top bottom floor] (world-setup joint)812 control (.getControl top RigidBodyControl)813 move-up? (atom false)814 move-down? (atom false)815 move-left? (atom false)816 move-right? (atom false)817 roll-left? (atom false)818 roll-right? (atom false)819 timer (atom 0)]821 (world822 (nodify [top bottom floor origin])823 (merge standard-debug-controls824 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))825 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))826 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))827 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))828 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))829 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})831 (fn [world]832 (light-up-everything world)833 (enable-debug world)834 (set-gravity world (Vector3f. 0 0 0))835 )837 (fn [world _]838 (if (zero? (rem (swap! timer inc) 100))839 (do840 ;; (println-repl @timer)841 (.attachChild (.getRootNode world)842 (sphere 0.05 :color ColorRGBA/Yellow843 :position (.getWorldTranslation top)844 :physical? false))845 (.attachChild (.getRootNode world)846 (sphere 0.05 :color ColorRGBA/LightGray847 :position (.getWorldTranslation bottom)848 :physical? false))))850 (if @move-up?851 (.applyTorque control852 (.mult (.getPhysicsRotation control)853 (Vector3f. 0 0 10))))854 (if @move-down?855 (.applyTorque control856 (.mult (.getPhysicsRotation control)857 (Vector3f. 0 0 -10))))858 (if @move-left?859 (.applyTorque control860 (.mult (.getPhysicsRotation control)861 (Vector3f. 0 10 0))))862 (if @move-right?863 (.applyTorque control864 (.mult (.getPhysicsRotation control)865 (Vector3f. 0 -10 0))))866 (if @roll-left?867 (.applyTorque control868 (.mult (.getPhysicsRotation control)869 (Vector3f. -1 0 0))))870 (if @roll-right?871 (.applyTorque control872 (.mult (.getPhysicsRotation control)873 (Vector3f. 1 0 0))))))))876 (defn locate-feelers*877 "Search the geometry's tactile UV image for touch sensors, returning878 their positions in geometry-relative coordinates."879 [#^Geometry geo]880 (let [uv-image (touch-receptor-image geo)881 width (.getWidth uv-image)882 height (.getHeight uv-image)884 mesh (.getMesh geo)885 mesh-tris (triangles geo)887 ;; for each triangle888 sensor-coords889 (fn [tri]890 ;; translate triangle to uv-pixel-space891 (let [uv-tri892 (rasterize mesh tri width height)893 bounds (vec (triangle-bounds uv-tri))]895 ;; get that part of the picture897 (apply (partial (memfn setRoi) uv-image) bounds)898 (let [cutout (.crop (.getProcessor uv-image))899 ;; extract white pixels inside triangle900 cutout-tri901 (map-triangle902 (fn [_ v]903 (.subtract904 v905 (Vector3f. (bounds 0) (bounds 1) (float 0))))906 uv-tri)907 whites (filter (partial inside-triangle? cutout-tri)908 (map vector2f->vector3f909 (white-coordinates cutout)))910 ;; translate pixel coordinates to world-space911 transform (triangle-transformation cutout-tri tri)]912 (map #(.mult transform %) whites))))]916 (for [mesh-tri mesh-tris]918 (let [uv-tri (rasterize mesh mesh-tri width height)919 bounding-box (vec (triangle-bounds uv-tri))]920 (apply (partial (memfn setRoi) uv-image) bounding-box)921 ))922 (vec (map sensor-coords mesh-tris))))925 (defn tactile-coords [#^Geometry obj]926 (let [mesh (.getMesh obj)927 num-triangles (.getTriangleCount mesh)928 num-verticies (.getVertexCount mesh)929 uv-coord (partial uv-coord mesh)930 triangle-indices (partial triangle-indices mesh)931 receptors (touch-receptor-image obj)932 tris (triangles obj)933 ]934 (map935 (fn [[tri-1 tri-2 tri-3]]936 (let [width (.getWidth receptors)937 height (.getHeight receptors)938 uv-1 (uv-coord tri-1)939 uv-2 (uv-coord tri-2)940 uv-3 (uv-coord tri-3)941 x-coords (map #(.getX %) [uv-1 uv-2 uv-3])942 y-coords (map #(.getY %) [uv-1 uv-2 uv-3])943 max-x (Math/ceil (* width (apply max x-coords)))944 min-x (Math/floor (* width (apply min x-coords)))945 max-y (Math/ceil (* height (apply max y-coords)))946 min-y (Math/floor (* height (apply min y-coords)))948 image-1 (Vector2f. (* width (.getX uv-1))949 (* height (.getY uv-1)))950 image-2 (Vector2f. (* width (.getX uv-2))951 (* height (.getY uv-2)))952 image-3 (Vector2f. (* width (.getX uv-3))953 (* height (.getY uv-3)))954 left-corner955 (Vector2f. min-x min-y)956 ]958 (.setRoi receptors min-x min-y (- max-x min-x) (- max-y min-y))959 (let [processor (.crop (.getProcessor receptors))]960 (map961 #(.add left-corner %)963 (filter964 (partial965 inside-triangle?966 (.subtract image-1 left-corner)967 (.subtract image-2 left-corner)968 (.subtract image-3 left-corner))969 (white-coordinates processor))))970 )) (map triangle-indices (range num-triangles)))))972 #+end_src974 #+results: body-1975 : #'cortex.silly/test-joint978 * COMMENT purgatory979 #+begin_src clojure980 (defn bullet-trans []981 (let [obj-a (sphere 0.5 :color ColorRGBA/Red982 :position (Vector3f. -10 5 0))983 obj-b (sphere 0.5 :color ColorRGBA/Blue984 :position (Vector3f. -10 -5 0)985 :mass 0)986 control-a (.getControl obj-a RigidBodyControl)987 control-b (.getControl obj-b RigidBodyControl)988 swivel989 (.toRotationMatrix990 (doto (Quaternion.)991 (.fromAngleAxis (/ Math/PI 2)992 Vector3f/UNIT_X)))]993 (doto994 (ConeJoint.995 control-a control-b996 (Vector3f. 0 5 0)997 (Vector3f. 0 -5 0)998 swivel swivel)999 (.setLimit (* 0.6 (/ Math/PI 4))1000 (/ Math/PI 4)1001 (* Math/PI 0.8)))1002 (world (nodify1003 [obj-a obj-b])1004 standard-debug-controls1005 enable-debug1006 no-op)))1009 (defn bullet-trans* []1010 (let [obj-a (box 1.5 0.5 0.5 :color ColorRGBA/Red1011 :position (Vector3f. 5 0 0)1012 :mass 90)1013 obj-b (sphere 0.5 :color ColorRGBA/Blue1014 :position (Vector3f. -5 0 0)1015 :mass 0)1016 control-a (.getControl obj-a RigidBodyControl)1017 control-b (.getControl obj-b RigidBodyControl)1018 move-up? (atom nil)1019 move-down? (atom nil)1020 move-left? (atom nil)1021 move-right? (atom nil)1022 roll-left? (atom nil)1023 roll-right? (atom nil)1024 force 1001025 swivel1026 (.toRotationMatrix1027 (doto (Quaternion.)1028 (.fromAngleAxis (/ Math/PI 2)1029 Vector3f/UNIT_X)))1030 x-move1031 (doto (Matrix3f.)1032 (.fromStartEndVectors Vector3f/UNIT_X1033 (.normalize (Vector3f. 1 1 0))))1035 timer (atom 0)]1036 (doto1037 (ConeJoint.1038 control-a control-b1039 (Vector3f. -8 0 0)1040 (Vector3f. 2 0 0)1041 ;;swivel swivel1042 ;;Matrix3f/IDENTITY Matrix3f/IDENTITY1043 x-move Matrix3f/IDENTITY1044 )1045 (.setCollisionBetweenLinkedBodys false)1046 (.setLimit (* 1 (/ Math/PI 4)) ;; twist1047 (* 1 (/ Math/PI 4)) ;; swing span in X-Y plane1048 (* 0 (/ Math/PI 4)))) ;; swing span in Y-Z plane1049 (world (nodify1050 [obj-a obj-b])1051 (merge standard-debug-controls1052 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))1053 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))1054 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))1055 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))1056 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))1057 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})1059 (fn [world]1060 (enable-debug world)1061 (set-gravity world Vector3f/ZERO)1062 )1064 (fn [world _]1066 (if @move-up?1067 (.applyForce control-a1068 (Vector3f. force 0 0)1069 (Vector3f. 0 0 0)))1070 (if @move-down?1071 (.applyForce control-a1072 (Vector3f. (- force) 0 0)1073 (Vector3f. 0 0 0)))1074 (if @move-left?1075 (.applyForce control-a1076 (Vector3f. 0 force 0)1077 (Vector3f. 0 0 0)))1078 (if @move-right?1079 (.applyForce control-a1080 (Vector3f. 0 (- force) 0)1081 (Vector3f. 0 0 0)))1083 (if @roll-left?1084 (.applyForce control-a1085 (Vector3f. 0 0 force)1086 (Vector3f. 0 0 0)))1087 (if @roll-right?1088 (.applyForce control-a1089 (Vector3f. 0 0 (- force))1090 (Vector3f. 0 0 0)))1092 (if (zero? (rem (swap! timer inc) 100))1093 (.attachChild1094 (.getRootNode world)1095 (sphere 0.05 :color ColorRGBA/Yellow1096 :physical? false :position1097 (.getWorldTranslation obj-a)))))1098 )1099 ))1101 (defn transform-trianglesdsd1102 "Transform that converts each vertex in the first triangle1103 into the corresponding vertex in the second triangle."1104 [#^Triangle tri-1 #^Triangle tri-2]1105 (let [in [(.get1 tri-1)1106 (.get2 tri-1)1107 (.get3 tri-1)]1108 out [(.get1 tri-2)1109 (.get2 tri-2)1110 (.get3 tri-2)]]1111 (let [translate (doto (Matrix4f.) (.setTranslation (.negate (in 0))))1112 in* [(.mult translate (in 0))1113 (.mult translate (in 1))1114 (.mult translate (in 2))]1115 final-translation1116 (doto (Matrix4f.)1117 (.setTranslation (out 1)))1119 rotate-11120 (doto (Matrix3f.)1121 (.fromStartEndVectors1122 (.normalize1123 (.subtract1124 (in* 1) (in* 0)))1125 (.normalize1126 (.subtract1127 (out 1) (out 0)))))1128 in** [(.mult rotate-1 (in* 0))1129 (.mult rotate-1 (in* 1))1130 (.mult rotate-1 (in* 2))]1131 scale-factor-11132 (.mult1133 (.normalize1134 (.subtract1135 (out 1)1136 (out 0)))1137 (/ (.length1138 (.subtract (out 1)1139 (out 0)))1140 (.length1141 (.subtract (in** 1)1142 (in** 0)))))1143 scale-1 (doto (Matrix4f.) (.setScale scale-factor-1))1144 in*** [(.mult scale-1 (in** 0))1145 (.mult scale-1 (in** 1))1146 (.mult scale-1 (in** 2))]1152 ]1154 (dorun (map println in))1155 (println)1156 (dorun (map println in*))1157 (println)1158 (dorun (map println in**))1159 (println)1160 (dorun (map println in***))1161 (println)1163 ))))1168 #+end_src1171 * COMMENT generate source1172 #+begin_src clojure :tangle ../src/cortex/silly.clj1173 <<body-1>>1174 #+end_src