Mercurial > cortex
view org/test-creature.org @ 100:940074adc1d5
can visualize a collection of points now.
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 14 Jan 2012 01:19:18 -0700 |
parents | b7a3ba5e879b |
children | 65332841b7d9 |
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 (map first points)102 ys (map second points)103 width (- (apply max xs) (apply min xs))104 height (- (apply max ys) (apply min ys))105 image (BufferedImage. width height106 BufferedImage/TYPE_BYTE_BINARY)110 ))115 ;;(defn visualize [points]119 (defn collapse120 "Take a set of pairs of integers and collapse them into a121 contigous bitmap."122 [points]123 (let [center [0 0]]125 )136 (defn load-bullet []137 (let [sim (world (Node.) {} no-op no-op)]138 (.enqueue139 sim140 (fn []141 (.stop sim)))142 (.start sim)))144 (defn load-blender-model145 "Load a .blend file using an asset folder relative path."146 [^String model]147 (.loadModel148 (doto (asset-manager)149 (.registerLoader BlenderModelLoader (into-array String ["blend"])))150 model))152 (defn meta-data [blender-node key]153 (if-let [data (.getUserData blender-node "properties")]154 (.findValue data key)155 nil))157 (defn blender-to-jme158 "Convert from Blender coordinates to JME coordinates"159 [#^Vector3f in]160 (Vector3f. (.getX in)161 (.getZ in)162 (- (.getY in))))164 (defn jme-to-blender165 "Convert from JME coordinates to Blender coordinates"166 [#^Vector3f in]167 (Vector3f. (.getX in)168 (- (.getZ in))169 (.getY in)))171 (defn joint-targets172 "Return the two closest two objects to the joint object, ordered173 from bottom to top according to the joint's rotation."174 [#^Node parts #^Node joint]175 ;;(println (meta-data joint "joint"))176 (.getWorldRotation joint)177 (loop [radius (float 0.01)]178 (let [results (CollisionResults.)]179 (.collideWith180 parts181 (BoundingBox. (.getWorldTranslation joint)182 radius radius radius)183 results)184 (let [targets185 (distinct186 (map #(.getGeometry %) results))]187 (if (>= (count targets) 2)188 (sort-by189 #(let [v190 (jme-to-blender191 (.mult192 (.inverse (.getWorldRotation joint))193 (.subtract (.getWorldTranslation %)194 (.getWorldTranslation joint))))]195 (println-repl (.getName %) ":" v)196 (.dot (Vector3f. 1 1 1)197 v))198 (take 2 targets))199 (recur (float (* radius 2))))))))201 (defn world-to-local202 "Convert the world coordinates into coordinates relative to the203 object (i.e. local coordinates), taking into account the rotation204 of object."205 [#^Spatial object world-coordinate]206 (let [out (Vector3f.)]207 (.worldToLocal object world-coordinate out) out))209 (defn local-to-world210 "Convert the local coordinates into coordinates into world relative211 coordinates"212 [#^Spatial object local-coordinate]213 (let [world-coordinate (Vector3f.)]214 (.localToWorld object local-coordinate world-coordinate)215 world-coordinate))218 (defmulti joint-dispatch219 "Translate blender pseudo-joints into real JME joints."220 (fn [constraints & _]221 (:type constraints)))223 (defmethod joint-dispatch :point224 [constraints control-a control-b pivot-a pivot-b rotation]225 (println-repl "creating POINT2POINT joint")226 (Point2PointJoint.227 control-a228 control-b229 pivot-a230 pivot-b))232 (defmethod joint-dispatch :hinge233 [constraints control-a control-b pivot-a pivot-b rotation]234 (println-repl "creating HINGE joint")235 (let [axis236 (if-let237 [axis (:axis constraints)]238 axis239 Vector3f/UNIT_X)240 [limit-1 limit-2] (:limit constraints)241 hinge-axis242 (.mult243 rotation244 (blender-to-jme axis))]245 (doto246 (HingeJoint.247 control-a248 control-b249 pivot-a250 pivot-b251 hinge-axis252 hinge-axis)253 (.setLimit limit-1 limit-2))))255 (defmethod joint-dispatch :cone256 [constraints control-a control-b pivot-a pivot-b rotation]257 (let [limit-xz (:limit-xz constraints)258 limit-xy (:limit-xy constraints)259 twist (:twist constraints)]261 (println-repl "creating CONE joint")262 (println-repl rotation)263 (println-repl264 "UNIT_X --> " (.mult rotation (Vector3f. 1 0 0)))265 (println-repl266 "UNIT_Y --> " (.mult rotation (Vector3f. 0 1 0)))267 (println-repl268 "UNIT_Z --> " (.mult rotation (Vector3f. 0 0 1)))269 (doto270 (ConeJoint.271 control-a272 control-b273 pivot-a274 pivot-b275 rotation276 rotation)277 (.setLimit (float limit-xz)278 (float limit-xy)279 (float twist)))))281 (defn connect282 "here are some examples:283 {:type :point}284 {:type :hinge :limit [0 (/ Math/PI 2)] :axis (Vector3f. 0 1 0)}285 (:axis defaults to (Vector3f. 1 0 0) if not provided for hinge joints)287 {:type :cone :limit-xz 0]288 :limit-xy 0]289 :twist 0]} (use XZY rotation mode in blender!)"290 [#^Node obj-a #^Node obj-b #^Node joint]291 (let [control-a (.getControl obj-a RigidBodyControl)292 control-b (.getControl obj-b RigidBodyControl)293 joint-center (.getWorldTranslation joint)294 joint-rotation (.toRotationMatrix (.getWorldRotation joint))295 pivot-a (world-to-local obj-a joint-center)296 pivot-b (world-to-local obj-b joint-center)]298 (if-let [constraints299 (map-vals300 eval301 (read-string302 (meta-data joint "joint")))]303 ;; A side-effect of creating a joint registers304 ;; it with both physics objects which in turn305 ;; will register the joint with the physics system306 ;; when the simulation is started.307 (do308 (println-repl "creating joint between"309 (.getName obj-a) "and" (.getName obj-b))310 (joint-dispatch constraints311 control-a control-b312 pivot-a pivot-b313 joint-rotation))314 (println-repl "could not find joint meta-data!"))))316 (defn assemble-creature [#^Node pieces joints]317 (dorun318 (map319 (fn [geom]320 (let [physics-control321 (RigidBodyControl.322 (HullCollisionShape.323 (.getMesh geom))324 (if-let [mass (meta-data geom "mass")]325 (do326 (println-repl327 "setting" (.getName geom) "mass to" (float mass))328 (float mass))329 (float 1)))]331 (.addControl geom physics-control)))332 (filter #(isa? (class %) Geometry )333 (node-seq pieces))))334 (dorun335 (map336 (fn [joint]337 (let [[obj-a obj-b]338 (joint-targets pieces joint)]339 (connect obj-a obj-b joint)))340 joints))341 pieces)343 (defn blender-creature [blender-path]344 (let [model (load-blender-model blender-path)345 joints346 (if-let [joint-node (.getChild model "joints")]347 (seq (.getChildren joint-node))348 (do (println-repl "could not find joints node")349 []))]350 (assemble-creature model joints)))352 (def hand "Models/creature1/one.blend")354 (def worm "Models/creature1/try-again.blend")356 (def touch "Models/creature1/touch.blend")358 (defn worm-model [] (load-blender-model worm))360 (defn x-ray [#^ColorRGBA color]361 (doto (Material. (asset-manager)362 "Common/MatDefs/Misc/Unshaded.j3md")363 (.setColor "Color" color)364 (-> (.getAdditionalRenderState)365 (.setDepthTest false))))367 (defn test-creature [thing]368 (let [x-axis369 (box 1 0.01 0.01 :physical? false :color ColorRGBA/Red)370 y-axis371 (box 0.01 1 0.01 :physical? false :color ColorRGBA/Green)372 z-axis373 (box 0.01 0.01 1 :physical? false :color ColorRGBA/Blue)]374 (world375 (nodify [(blender-creature thing)376 (box 10 2 10 :position (Vector3f. 0 -9 0)377 :color ColorRGBA/Gray :mass 0)378 x-axis y-axis z-axis379 ])380 standard-debug-controls381 (fn [world]382 (light-up-everything world)383 (enable-debug world)384 ;;(com.aurellem.capture.Capture/captureVideo385 ;; world (file-str "/home/r/proj/ai-videos/hand"))386 (.setTimer world (NanoTimer.))387 (set-gravity world (Vector3f. 0 0 0))388 (speed-up world)389 )390 no-op391 ;;(let [timer (atom 0)]392 ;; (fn [_ _]393 ;; (swap! timer inc)394 ;; (if (= (rem @timer 60) 0)395 ;; (println-repl (float (/ @timer 60))))))396 )))398 (defn colorful []399 (.getChild (worm-model) "worm-21"))401 (import jme3tools.converters.ImageToAwt)403 (import ij.ImagePlus)405 (defn triangle-indices406 "Get the triangle vertex indices of a given triangle from a given407 mesh."408 [#^Mesh mesh triangle-index]409 (let [indices (int-array 3)]410 (.getTriangle mesh triangle-index indices)411 (vec indices)))413 (defn uv-coord414 "Get the uv-coordinates of the vertex named by vertex-index"415 [#^Mesh mesh vertex-index]416 (let [UV-buffer417 (.getData418 (.getBuffer419 mesh420 VertexBuffer$Type/TexCoord))]421 (Vector2f.422 (.get UV-buffer (* vertex-index 2))423 (.get UV-buffer (+ 1 (* vertex-index 2))))))425 (defn tri-uv-coord426 "Get the uv-cooridnates of the triangle's verticies."427 [#^Mesh mesh #^Triangle triangle]428 (map (partial uv-coord mesh)429 (triangle-indices mesh (.getIndex triangle))))431 (defn touch-receptor-image432 "Return the touch-sensor distribution image in ImagePlus format, or433 nil if it does not exist."434 [#^Geometry obj]435 (let [mat (.getMaterial obj)]436 (if-let [texture-param437 (.getTextureParam438 mat439 MaterialHelper/TEXTURE_TYPE_DIFFUSE)]440 (let441 [texture442 (.getTextureValue texture-param)443 im (.getImage texture)]444 (ImagePlus.445 "UV-map"446 (ImageToAwt/convert im false false 0))))))448 (import ij.process.ImageProcessor)449 (import java.awt.image.BufferedImage)451 (defprotocol Frame452 (frame [this]))454 (extend-type BufferedImage455 Frame456 (frame [image]457 (merge458 (apply459 hash-map460 (interleave461 (doall (for [x (range (.getWidth image)) y (range (.getHeight image))]462 (vector x y)))463 (doall (for [x (range (.getWidth image)) y (range (.getHeight image))]464 (let [data (.getRGB image x y)]465 (hash-map :r (bit-shift-right (bit-and 0xff0000 data) 16)466 :g (bit-shift-right (bit-and 0x00ff00 data) 8)467 :b (bit-and 0x0000ff data)))))))468 {:width (.getWidth image) :height (.getHeight image)})))471 (extend-type ImagePlus472 Frame473 (frame [image+]474 (frame (.getBufferedImage image+))))477 (def white -1)479 (defn filter-pixels480 "List the coordinates of all pixels matching pred."481 {:author "Dylan Holmes"}482 [pred #^ImageProcessor ip]483 (let484 [width (.getWidth ip)485 height (.getHeight ip)]486 ((fn accumulate [x y matches]487 (cond488 (>= y height) matches489 (>= x width) (recur 0 (inc y) matches)490 (pred (.getPixel ip x y))491 (recur (inc x) y (conj matches (Vector2f. x y)))492 :else (recur (inc x) y matches)))493 0 0 [])))495 (defn white-coordinates496 "List the coordinates of all the white pixels in an image."497 [#^ImageProcessor ip]498 (filter-pixels #(= % white) ip))500 (defn same-side? [p1 p2 ref p]501 (<=502 0503 (.dot504 (.cross (.subtract p2 p1) (.subtract p p1))505 (.cross (.subtract p2 p1) (.subtract ref p1)))))508 (defn triangle->matrix4f509 "Converts the triangle into a 4x4 matrix of vertices: The first510 three columns contain the vertices of the triangle; the last511 contains the unit normal of the triangle. The bottom row is filled512 with 1s."513 [#^Triangle t]514 (let [mat (Matrix4f.)515 [vert-1 vert-2 vert-3]516 ((comp vec map) #(.get t %) (range 3))517 unit-normal (do (.calculateNormal t)(.getNormal t))518 vertices [vert-1 vert-2 vert-3 unit-normal]]520 (dorun521 (for [row (range 4) col (range 3)]522 (do523 (.set mat col row (.get (vertices row)col))524 (.set mat 3 row 1))))525 mat))527 (defn triangle-transformation528 "Returns the affine transformation that converts each vertex in the529 first triangle into the corresponding vertex in the second530 triangle."531 [#^Triangle tri-1 #^Triangle tri-2]532 (.mult533 (triangle->matrix4f tri-2)534 (.invert (triangle->matrix4f tri-1))))536 (def death (Triangle.537 (Vector3f. 1 1 1)538 (Vector3f. 1 2 3)539 (Vector3f. 5 6 7)))541 (def death-2 (Triangle.542 (Vector3f. 2 2 2)543 (Vector3f. 1 1 1)544 (Vector3f. 0 1 0)))546 (defn vector2f->vector3f [v]547 (Vector3f. (.getX v) (.getY v) 0))550 (extend-type Triangle551 Textual552 (text [t]553 (println "Triangle: " \newline (.get1 t) \newline554 (.get2 t) \newline (.get3 t))))557 (defn map-triangle [f #^Triangle tri]558 (Triangle.559 (f 0 (.get1 tri))560 (f 1 (.get2 tri))561 (f 2 (.get3 tri))))563 (defn triangle-seq [#^Triangle tri]564 [(.get1 tri) (.get2 tri) (.get3 tri)])566 (defn vector3f-seq [#^Vector3f v]567 [(.getX v) (.getY v) (.getZ v)])569 (defn inside-triangle?570 "Is the point inside the triangle? Now what do we do?571 You might want to hold on there"572 {:author "Dylan Holmes"}573 [tri p]574 (let [[vert-1 vert-2 vert-3] (triangle-seq tri)]575 (and576 (same-side? vert-1 vert-2 vert-3 p)577 (same-side? vert-2 vert-3 vert-1 p)578 (same-side? vert-3 vert-1 vert-2 p))))580 (defn uv-triangle581 "Convert the mesh triangle into the cooresponding triangle in582 UV-space. Z-component of these triangles is always zero."583 [#^Mesh mesh #^Triangle tri]584 (apply #(Triangle. %1 %2 %3)585 (map vector2f->vector3f586 (tri-uv-coord mesh tri))))588 (defn pixel-triangle589 "Convert the mesh triange into the corresponding triangle in590 UV-pixel-space. Z compenent will be zero."591 [#^Mesh mesh #^Triangle tri width height]592 (map-triangle (fn [_ v]593 (Vector3f. (* width (.getX v))594 (* height (.getY v))595 0))596 (uv-triangle mesh tri)))598 (def rasterize pixel-triangle)601 (defn triangle-bounds602 "Dimensions of the bounding square of the triangle in the form603 [x y width height].604 Assumes that the triangle lies in the XY plane."605 [#^Triangle tri]606 (let [verts (map vector3f-seq (triangle-seq tri))607 x (apply min (map first verts))608 y (apply min (map second verts))]610 [x y611 (- (apply max (map first verts)) x)612 (- (apply max (map second verts)) y)613 ]))616 (defn locate-feelers617 "Search the geometry's tactile UV image for touch sensors, returning618 their positions in geometry-relative coordinates."619 [#^Geometry geo]620 (if-let [image (touch-receptor-image geo)]621 (let [mesh (.getMesh geo)622 tris (triangles geo)625 width (.getWidth image)626 height (.getHeight image)628 ;; for each triangle629 sensor-coords630 (fn [tri]631 ;; translate triangle to uv-pixel-space632 (let [uv-tri633 (pixel-triangle mesh tri width height)634 bounds (vec (triangle-bounds uv-tri))]636 ;; get that part of the picture638 (apply #(.setRoi image %1 %2 %3 %4) bounds)639 (let [cutout (.crop (.getProcessor image))640 ;; extract white pixels inside triangle641 cutout-tri642 (map-triangle643 (fn [_ v]644 (.subtract645 v646 (Vector3f. (bounds 0) (bounds 1) (float 0))))647 uv-tri)648 whites (filter (partial inside-triangle? cutout-tri)649 (map vector2f->vector3f650 (white-coordinates cutout)))651 ;; translate pixel coordinates to world-space652 transform (triangle-transformation cutout-tri tri)]653 (map #(.mult transform %) whites))))]654 (vec (map sensor-coords tris)))655 (repeat (count (triangles geo)) [])))657 (defn enable-touch [#^Geometry geo]658 (let [feeler-coords (locate-feelers geo)659 tris (triangles geo)660 limit 0.1]661 (fn [node]662 (let [sensor-origins663 (map664 #(map (partial local-to-world geo) %)665 feeler-coords)666 triangle-normals667 (map (partial get-ray-direction geo)668 tris)669 rays670 (flatten671 (map (fn [origins norm]672 (map #(doto (Ray. % norm)673 (.setLimit limit)) origins))674 sensor-origins triangle-normals))]675 (for [ray rays]676 (do677 (let [results (CollisionResults.)]678 (.collideWith node ray results)679 (let [touch-objects680 (set681 (filter #(not (= geo %))682 (map #(.getGeometry %) results)))]683 (if (> (count touch-objects) 0)684 1 0)))))))))686 (defn touch [#^Node pieces]687 (let [touch-components688 (map enable-touch689 (filter #(isa? (class %) Geometry)690 (node-seq pieces)))]691 (fn [node]692 (reduce into [] (map #(% node) touch-components)))))694 (defn all-names []695 (concat696 (re-split #"\n" (slurp (file-str697 "/home/r/proj/names/dist.female.first")))698 (re-split #"\n" (slurp (file-str699 "/home/r/proj/names/dist.male.first")))700 (re-split #"\n" (slurp (file-str701 "/home/r/proj/names/dist.all.last")))))711 (defrecord LulzLoader [])712 (defprotocol Lulzable (load-lulz [this]))713 (extend-type LulzLoader714 Lulzable715 (load-lulz [this] (println "the lulz have arrived!")))718 (defn world-setup [joint]719 (let [joint-position (Vector3f. 0 0 0)720 joint-rotation721 (.toRotationMatrix722 (.mult723 (doto (Quaternion.)724 (.fromAngleAxis725 (* 1 (/ Math/PI 4))726 (Vector3f. -1 0 0)))727 (doto (Quaternion.)728 (.fromAngleAxis729 (* 1 (/ Math/PI 2))730 (Vector3f. 0 0 1)))))731 top-position (.mult joint-rotation (Vector3f. 8 0 0))733 origin (doto734 (sphere 0.1 :physical? false :color ColorRGBA/Cyan735 :position top-position))736 top (doto737 (sphere 0.1 :physical? false :color ColorRGBA/Yellow738 :position top-position)740 (.addControl741 (RigidBodyControl.742 (CapsuleCollisionShape. 0.5 1.5 1) (float 20))))743 bottom (doto744 (sphere 0.1 :physical? false :color ColorRGBA/DarkGray745 :position (Vector3f. 0 0 0))746 (.addControl747 (RigidBodyControl.748 (CapsuleCollisionShape. 0.5 1.5 1) (float 0))))749 table (box 10 2 10 :position (Vector3f. 0 -20 0)750 :color ColorRGBA/Gray :mass 0)751 a (.getControl top RigidBodyControl)752 b (.getControl bottom RigidBodyControl)]754 (cond755 (= joint :cone)757 (doto (ConeJoint.758 a b759 (world-to-local top joint-position)760 (world-to-local bottom joint-position)761 joint-rotation762 joint-rotation763 )766 (.setLimit (* (/ 10) Math/PI)767 (* (/ 4) Math/PI)768 0)))769 [origin top bottom table]))771 (defn test-joint [joint]772 (let [[origin top bottom floor] (world-setup joint)773 control (.getControl top RigidBodyControl)774 move-up? (atom false)775 move-down? (atom false)776 move-left? (atom false)777 move-right? (atom false)778 roll-left? (atom false)779 roll-right? (atom false)780 timer (atom 0)]782 (world783 (nodify [top bottom floor origin])784 (merge standard-debug-controls785 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))786 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))787 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))788 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))789 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))790 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})792 (fn [world]793 (light-up-everything world)794 (enable-debug world)795 (set-gravity world (Vector3f. 0 0 0))796 )798 (fn [world _]799 (if (zero? (rem (swap! timer inc) 100))800 (do801 ;; (println-repl @timer)802 (.attachChild (.getRootNode world)803 (sphere 0.05 :color ColorRGBA/Yellow804 :position (.getWorldTranslation top)805 :physical? false))806 (.attachChild (.getRootNode world)807 (sphere 0.05 :color ColorRGBA/LightGray808 :position (.getWorldTranslation bottom)809 :physical? false))))811 (if @move-up?812 (.applyTorque control813 (.mult (.getPhysicsRotation control)814 (Vector3f. 0 0 10))))815 (if @move-down?816 (.applyTorque control817 (.mult (.getPhysicsRotation control)818 (Vector3f. 0 0 -10))))819 (if @move-left?820 (.applyTorque control821 (.mult (.getPhysicsRotation control)822 (Vector3f. 0 10 0))))823 (if @move-right?824 (.applyTorque control825 (.mult (.getPhysicsRotation control)826 (Vector3f. 0 -10 0))))827 (if @roll-left?828 (.applyTorque control829 (.mult (.getPhysicsRotation control)830 (Vector3f. -1 0 0))))831 (if @roll-right?832 (.applyTorque control833 (.mult (.getPhysicsRotation control)834 (Vector3f. 1 0 0))))))))837 (defn locate-feelers*838 "Search the geometry's tactile UV image for touch sensors, returning839 their positions in geometry-relative coordinates."840 [#^Geometry geo]841 (let [uv-image (touch-receptor-image geo)842 width (.getWidth uv-image)843 height (.getHeight uv-image)845 mesh (.getMesh geo)846 mesh-tris (triangles geo)848 ;; for each triangle849 sensor-coords850 (fn [tri]851 ;; translate triangle to uv-pixel-space852 (let [uv-tri853 (rasterize mesh tri width height)854 bounds (vec (triangle-bounds uv-tri))]856 ;; get that part of the picture858 (apply (partial (memfn setRoi) uv-image) bounds)859 (let [cutout (.crop (.getProcessor uv-image))860 ;; extract white pixels inside triangle861 cutout-tri862 (map-triangle863 (fn [_ v]864 (.subtract865 v866 (Vector3f. (bounds 0) (bounds 1) (float 0))))867 uv-tri)868 whites (filter (partial inside-triangle? cutout-tri)869 (map vector2f->vector3f870 (white-coordinates cutout)))871 ;; translate pixel coordinates to world-space872 transform (triangle-transformation cutout-tri tri)]873 (map #(.mult transform %) whites))))]877 (for [mesh-tri mesh-tris]879 (let [uv-tri (rasterize mesh mesh-tri width height)880 bounding-box (vec (triangle-bounds uv-tri))]881 (apply (partial (memfn setRoi) uv-image) bounding-box)882 ))883 (vec (map sensor-coords mesh-tris))))886 (defn tactile-coords [#^Geometry obj]887 (let [mesh (.getMesh obj)888 num-triangles (.getTriangleCount mesh)889 num-verticies (.getVertexCount mesh)890 uv-coord (partial uv-coord mesh)891 triangle-indices (partial triangle-indices mesh)892 receptors (touch-receptor-image obj)893 tris (triangles obj)894 ]895 (map896 (fn [[tri-1 tri-2 tri-3]]897 (let [width (.getWidth receptors)898 height (.getHeight receptors)899 uv-1 (uv-coord tri-1)900 uv-2 (uv-coord tri-2)901 uv-3 (uv-coord tri-3)902 x-coords (map #(.getX %) [uv-1 uv-2 uv-3])903 y-coords (map #(.getY %) [uv-1 uv-2 uv-3])904 max-x (Math/ceil (* width (apply max x-coords)))905 min-x (Math/floor (* width (apply min x-coords)))906 max-y (Math/ceil (* height (apply max y-coords)))907 min-y (Math/floor (* height (apply min y-coords)))909 image-1 (Vector2f. (* width (.getX uv-1))910 (* height (.getY uv-1)))911 image-2 (Vector2f. (* width (.getX uv-2))912 (* height (.getY uv-2)))913 image-3 (Vector2f. (* width (.getX uv-3))914 (* height (.getY uv-3)))915 left-corner916 (Vector2f. min-x min-y)917 ]919 (.setRoi receptors min-x min-y (- max-x min-x) (- max-y min-y))920 (let [processor (.crop (.getProcessor receptors))]921 (map922 #(.add left-corner %)924 (filter925 (partial926 inside-triangle?927 (.subtract image-1 left-corner)928 (.subtract image-2 left-corner)929 (.subtract image-3 left-corner))930 (white-coordinates processor))))931 )) (map triangle-indices (range num-triangles)))))933 #+end_src935 #+results: body-1936 : #'cortex.silly/test-joint939 * COMMENT purgatory940 #+begin_src clojure941 (defn bullet-trans []942 (let [obj-a (sphere 0.5 :color ColorRGBA/Red943 :position (Vector3f. -10 5 0))944 obj-b (sphere 0.5 :color ColorRGBA/Blue945 :position (Vector3f. -10 -5 0)946 :mass 0)947 control-a (.getControl obj-a RigidBodyControl)948 control-b (.getControl obj-b RigidBodyControl)949 swivel950 (.toRotationMatrix951 (doto (Quaternion.)952 (.fromAngleAxis (/ Math/PI 2)953 Vector3f/UNIT_X)))]954 (doto955 (ConeJoint.956 control-a control-b957 (Vector3f. 0 5 0)958 (Vector3f. 0 -5 0)959 swivel swivel)960 (.setLimit (* 0.6 (/ Math/PI 4))961 (/ Math/PI 4)962 (* Math/PI 0.8)))963 (world (nodify964 [obj-a obj-b])965 standard-debug-controls966 enable-debug967 no-op)))970 (defn bullet-trans* []971 (let [obj-a (box 1.5 0.5 0.5 :color ColorRGBA/Red972 :position (Vector3f. 5 0 0)973 :mass 90)974 obj-b (sphere 0.5 :color ColorRGBA/Blue975 :position (Vector3f. -5 0 0)976 :mass 0)977 control-a (.getControl obj-a RigidBodyControl)978 control-b (.getControl obj-b RigidBodyControl)979 move-up? (atom nil)980 move-down? (atom nil)981 move-left? (atom nil)982 move-right? (atom nil)983 roll-left? (atom nil)984 roll-right? (atom nil)985 force 100986 swivel987 (.toRotationMatrix988 (doto (Quaternion.)989 (.fromAngleAxis (/ Math/PI 2)990 Vector3f/UNIT_X)))991 x-move992 (doto (Matrix3f.)993 (.fromStartEndVectors Vector3f/UNIT_X994 (.normalize (Vector3f. 1 1 0))))996 timer (atom 0)]997 (doto998 (ConeJoint.999 control-a control-b1000 (Vector3f. -8 0 0)1001 (Vector3f. 2 0 0)1002 ;;swivel swivel1003 ;;Matrix3f/IDENTITY Matrix3f/IDENTITY1004 x-move Matrix3f/IDENTITY1005 )1006 (.setCollisionBetweenLinkedBodys false)1007 (.setLimit (* 1 (/ Math/PI 4)) ;; twist1008 (* 1 (/ Math/PI 4)) ;; swing span in X-Y plane1009 (* 0 (/ Math/PI 4)))) ;; swing span in Y-Z plane1010 (world (nodify1011 [obj-a obj-b])1012 (merge standard-debug-controls1013 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))1014 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))1015 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))1016 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))1017 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))1018 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})1020 (fn [world]1021 (enable-debug world)1022 (set-gravity world Vector3f/ZERO)1023 )1025 (fn [world _]1027 (if @move-up?1028 (.applyForce control-a1029 (Vector3f. force 0 0)1030 (Vector3f. 0 0 0)))1031 (if @move-down?1032 (.applyForce control-a1033 (Vector3f. (- force) 0 0)1034 (Vector3f. 0 0 0)))1035 (if @move-left?1036 (.applyForce control-a1037 (Vector3f. 0 force 0)1038 (Vector3f. 0 0 0)))1039 (if @move-right?1040 (.applyForce control-a1041 (Vector3f. 0 (- force) 0)1042 (Vector3f. 0 0 0)))1044 (if @roll-left?1045 (.applyForce control-a1046 (Vector3f. 0 0 force)1047 (Vector3f. 0 0 0)))1048 (if @roll-right?1049 (.applyForce control-a1050 (Vector3f. 0 0 (- force))1051 (Vector3f. 0 0 0)))1053 (if (zero? (rem (swap! timer inc) 100))1054 (.attachChild1055 (.getRootNode world)1056 (sphere 0.05 :color ColorRGBA/Yellow1057 :physical? false :position1058 (.getWorldTranslation obj-a)))))1059 )1060 ))1062 (defn transform-trianglesdsd1063 "Transform that converts each vertex in the first triangle1064 into the corresponding vertex in the second triangle."1065 [#^Triangle tri-1 #^Triangle tri-2]1066 (let [in [(.get1 tri-1)1067 (.get2 tri-1)1068 (.get3 tri-1)]1069 out [(.get1 tri-2)1070 (.get2 tri-2)1071 (.get3 tri-2)]]1072 (let [translate (doto (Matrix4f.) (.setTranslation (.negate (in 0))))1073 in* [(.mult translate (in 0))1074 (.mult translate (in 1))1075 (.mult translate (in 2))]1076 final-translation1077 (doto (Matrix4f.)1078 (.setTranslation (out 1)))1080 rotate-11081 (doto (Matrix3f.)1082 (.fromStartEndVectors1083 (.normalize1084 (.subtract1085 (in* 1) (in* 0)))1086 (.normalize1087 (.subtract1088 (out 1) (out 0)))))1089 in** [(.mult rotate-1 (in* 0))1090 (.mult rotate-1 (in* 1))1091 (.mult rotate-1 (in* 2))]1092 scale-factor-11093 (.mult1094 (.normalize1095 (.subtract1096 (out 1)1097 (out 0)))1098 (/ (.length1099 (.subtract (out 1)1100 (out 0)))1101 (.length1102 (.subtract (in** 1)1103 (in** 0)))))1104 scale-1 (doto (Matrix4f.) (.setScale scale-factor-1))1105 in*** [(.mult scale-1 (in** 0))1106 (.mult scale-1 (in** 1))1107 (.mult scale-1 (in** 2))]1113 ]1115 (dorun (map println in))1116 (println)1117 (dorun (map println in*))1118 (println)1119 (dorun (map println in**))1120 (println)1121 (dorun (map println in***))1122 (println)1124 ))))1129 #+end_src1132 * COMMENT generate source1133 #+begin_src clojure :tangle ../src/cortex/silly.clj1134 <<body-1>>1135 #+end_src