Mercurial > cortex
view org/test-creature.org @ 102:7eeb940bcbc8
data format for touch implemented
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 14 Jan 2012 20:44:13 -0700 |
parents | 65332841b7d9 |
children | 85ee8bb80edf |
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."101 ;; TODO maybe parallelize this since it's easy103 [points]104 (let [xs (vec (map first points))105 ys (vec (map second points))106 x0 (apply min xs)107 y0 (apply min ys)108 width (- (apply max xs) x0)109 height (- (apply max ys) y0)110 image (BufferedImage. (inc width) (inc height)111 BufferedImage/TYPE_BYTE_BINARY)]112 (dorun113 (for [index (range (count points))]114 (.setRGB image (- (xs index) x0) (- (ys index) y0) -1)))116 image))118 (defn test-data119 []120 (vec121 (for [a (range 0 1000 2)122 b (range 0 1000 2)]123 (vector a b))124 ))126 (defn average [coll]127 (/ (reduce + coll) (count coll)))129 (defn collapse-1d130 "One dimensional analogue of collapse"131 [center line]132 (let [length (count line)133 num-above (count (filter (partial < center) line))134 num-below (- length num-above)]135 (range (- center num-below)136 (+ center num-above))137 ))139 (defn collapse140 "Take a set of pairs of integers and collapse them into a141 contigous bitmap."142 [points]143 (let144 [num-points (count points)145 center (vector146 (int (average (map first points)))147 (int (average (map first points))))148 flattened149 (reduce150 concat151 (map152 (fn [column]153 (map vector154 (map first column)155 (collapse-1d (second center)156 (map second column))))157 (partition-by first (sort-by first points))))158 squeezed159 (reduce160 concat161 (map162 (fn [row]163 (map vector164 (collapse-1d (first center)165 (map first row))166 (map second row)))167 (partition-by second (sort-by second flattened))))168 ;;vi (view-image)169 relocate170 (let [min-x (apply min (map first squeezed))171 min-y (apply min (map second squeezed))]172 (map (fn [[x y]]173 [(- x min-x)174 (- y min-y)])175 squeezed))176 ]177 ;;(vi (points->image points))178 ;;(Thread/sleep 1000)179 ;;(vi (points->image flattened))180 ;;(Thread/sleep 1000)181 ;;(vi (points->image squeezed))182 relocate183 ))185 (defn load-bullet []186 (let [sim (world (Node.) {} no-op no-op)]187 (doto sim188 (.enqueue189 (fn []190 (.stop sim)))191 (.start))))193 (defn load-blender-model194 "Load a .blend file using an asset folder relative path."195 [^String model]196 (.loadModel197 (doto (asset-manager)198 (.registerLoader BlenderModelLoader (into-array String ["blend"])))199 model))201 (defn meta-data [blender-node key]202 (if-let [data (.getUserData blender-node "properties")]203 (.findValue data key)204 nil))206 (defn blender-to-jme207 "Convert from Blender coordinates to JME coordinates"208 [#^Vector3f in]209 (Vector3f. (.getX in)210 (.getZ in)211 (- (.getY in))))213 (defn jme-to-blender214 "Convert from JME coordinates to Blender coordinates"215 [#^Vector3f in]216 (Vector3f. (.getX in)217 (- (.getZ in))218 (.getY in)))220 (defn joint-targets221 "Return the two closest two objects to the joint object, ordered222 from bottom to top according to the joint's rotation."223 [#^Node parts #^Node joint]224 ;;(println (meta-data joint "joint"))225 (.getWorldRotation joint)226 (loop [radius (float 0.01)]227 (let [results (CollisionResults.)]228 (.collideWith229 parts230 (BoundingBox. (.getWorldTranslation joint)231 radius radius radius)232 results)233 (let [targets234 (distinct235 (map #(.getGeometry %) results))]236 (if (>= (count targets) 2)237 (sort-by238 #(let [v239 (jme-to-blender240 (.mult241 (.inverse (.getWorldRotation joint))242 (.subtract (.getWorldTranslation %)243 (.getWorldTranslation joint))))]244 (println-repl (.getName %) ":" v)245 (.dot (Vector3f. 1 1 1)246 v))247 (take 2 targets))248 (recur (float (* radius 2))))))))250 (defn world-to-local251 "Convert the world coordinates into coordinates relative to the252 object (i.e. local coordinates), taking into account the rotation253 of object."254 [#^Spatial object world-coordinate]255 (let [out (Vector3f.)]256 (.worldToLocal object world-coordinate out) out))258 (defn local-to-world259 "Convert the local coordinates into coordinates into world relative260 coordinates"261 [#^Spatial object local-coordinate]262 (let [world-coordinate (Vector3f.)]263 (.localToWorld object local-coordinate world-coordinate)264 world-coordinate))267 (defmulti joint-dispatch268 "Translate blender pseudo-joints into real JME joints."269 (fn [constraints & _]270 (:type constraints)))272 (defmethod joint-dispatch :point273 [constraints control-a control-b pivot-a pivot-b rotation]274 (println-repl "creating POINT2POINT joint")275 (Point2PointJoint.276 control-a277 control-b278 pivot-a279 pivot-b))281 (defmethod joint-dispatch :hinge282 [constraints control-a control-b pivot-a pivot-b rotation]283 (println-repl "creating HINGE joint")284 (let [axis285 (if-let286 [axis (:axis constraints)]287 axis288 Vector3f/UNIT_X)289 [limit-1 limit-2] (:limit constraints)290 hinge-axis291 (.mult292 rotation293 (blender-to-jme axis))]294 (doto295 (HingeJoint.296 control-a297 control-b298 pivot-a299 pivot-b300 hinge-axis301 hinge-axis)302 (.setLimit limit-1 limit-2))))304 (defmethod joint-dispatch :cone305 [constraints control-a control-b pivot-a pivot-b rotation]306 (let [limit-xz (:limit-xz constraints)307 limit-xy (:limit-xy constraints)308 twist (:twist constraints)]310 (println-repl "creating CONE joint")311 (println-repl rotation)312 (println-repl313 "UNIT_X --> " (.mult rotation (Vector3f. 1 0 0)))314 (println-repl315 "UNIT_Y --> " (.mult rotation (Vector3f. 0 1 0)))316 (println-repl317 "UNIT_Z --> " (.mult rotation (Vector3f. 0 0 1)))318 (doto319 (ConeJoint.320 control-a321 control-b322 pivot-a323 pivot-b324 rotation325 rotation)326 (.setLimit (float limit-xz)327 (float limit-xy)328 (float twist)))))330 (defn connect331 "here are some examples:332 {:type :point}333 {:type :hinge :limit [0 (/ Math/PI 2)] :axis (Vector3f. 0 1 0)}334 (:axis defaults to (Vector3f. 1 0 0) if not provided for hinge joints)336 {:type :cone :limit-xz 0]337 :limit-xy 0]338 :twist 0]} (use XZY rotation mode in blender!)"339 [#^Node obj-a #^Node obj-b #^Node joint]340 (let [control-a (.getControl obj-a RigidBodyControl)341 control-b (.getControl obj-b RigidBodyControl)342 joint-center (.getWorldTranslation joint)343 joint-rotation (.toRotationMatrix (.getWorldRotation joint))344 pivot-a (world-to-local obj-a joint-center)345 pivot-b (world-to-local obj-b joint-center)]347 (if-let [constraints348 (map-vals349 eval350 (read-string351 (meta-data joint "joint")))]352 ;; A side-effect of creating a joint registers353 ;; it with both physics objects which in turn354 ;; will register the joint with the physics system355 ;; when the simulation is started.356 (do357 (println-repl "creating joint between"358 (.getName obj-a) "and" (.getName obj-b))359 (joint-dispatch constraints360 control-a control-b361 pivot-a pivot-b362 joint-rotation))363 (println-repl "could not find joint meta-data!"))))365 (defn assemble-creature [#^Node pieces joints]366 (dorun367 (map368 (fn [geom]369 (let [physics-control370 (RigidBodyControl.371 (HullCollisionShape.372 (.getMesh geom))373 (if-let [mass (meta-data geom "mass")]374 (do375 (println-repl376 "setting" (.getName geom) "mass to" (float mass))377 (float mass))378 (float 1)))]380 (.addControl geom physics-control)))381 (filter #(isa? (class %) Geometry )382 (node-seq pieces))))383 (dorun384 (map385 (fn [joint]386 (let [[obj-a obj-b]387 (joint-targets pieces joint)]388 (connect obj-a obj-b joint)))389 joints))390 pieces)392 (defn blender-creature [blender-path]393 (let [model (load-blender-model blender-path)394 joints395 (if-let [joint-node (.getChild model "joints")]396 (seq (.getChildren joint-node))397 (do (println-repl "could not find joints node")398 []))]399 (assemble-creature model joints)))401 (def hand "Models/creature1/one.blend")403 (def worm "Models/creature1/try-again.blend")405 (def touch "Models/creature1/touch.blend")407 (defn worm-model [] (load-blender-model worm))409 (defn x-ray [#^ColorRGBA color]410 (doto (Material. (asset-manager)411 "Common/MatDefs/Misc/Unshaded.j3md")412 (.setColor "Color" color)413 (-> (.getAdditionalRenderState)414 (.setDepthTest false))))416 (defn test-creature [thing]417 (let [x-axis418 (box 1 0.01 0.01 :physical? false :color ColorRGBA/Red)419 y-axis420 (box 0.01 1 0.01 :physical? false :color ColorRGBA/Green)421 z-axis422 (box 0.01 0.01 1 :physical? false :color ColorRGBA/Blue)]423 (world424 (nodify [(blender-creature thing)425 (box 10 2 10 :position (Vector3f. 0 -9 0)426 :color ColorRGBA/Gray :mass 0)427 x-axis y-axis z-axis428 ])429 standard-debug-controls430 (fn [world]431 (light-up-everything world)432 (enable-debug world)433 ;;(com.aurellem.capture.Capture/captureVideo434 ;; world (file-str "/home/r/proj/ai-videos/hand"))435 (.setTimer world (NanoTimer.))436 (set-gravity world (Vector3f. 0 0 0))437 (speed-up world)438 )439 no-op440 ;;(let [timer (atom 0)]441 ;; (fn [_ _]442 ;; (swap! timer inc)443 ;; (if (= (rem @timer 60) 0)444 ;; (println-repl (float (/ @timer 60))))))445 )))447 (defn colorful []448 (.getChild (worm-model) "worm-21"))450 (import jme3tools.converters.ImageToAwt)452 (import ij.ImagePlus)454 (defn triangle-indices455 "Get the triangle vertex indices of a given triangle from a given456 mesh."457 [#^Mesh mesh triangle-index]458 (let [indices (int-array 3)]459 (.getTriangle mesh triangle-index indices)460 (vec indices)))462 (defn uv-coord463 "Get the uv-coordinates of the vertex named by vertex-index"464 [#^Mesh mesh vertex-index]465 (let [UV-buffer466 (.getData467 (.getBuffer468 mesh469 VertexBuffer$Type/TexCoord))]470 (Vector2f.471 (.get UV-buffer (* vertex-index 2))472 (.get UV-buffer (+ 1 (* vertex-index 2))))))474 (defn tri-uv-coord475 "Get the uv-cooridnates of the triangle's verticies."476 [#^Mesh mesh #^Triangle triangle]477 (map (partial uv-coord mesh)478 (triangle-indices mesh (.getIndex triangle))))480 (defn touch-receptor-image481 "Return the touch-sensor distribution image in ImagePlus format, or482 nil if it does not exist."483 [#^Geometry obj]484 (let [mat (.getMaterial obj)]485 (if-let [texture-param486 (.getTextureParam487 mat488 MaterialHelper/TEXTURE_TYPE_DIFFUSE)]489 (let490 [texture491 (.getTextureValue texture-param)492 im (.getImage texture)]493 (ImagePlus.494 "UV-map"495 (ImageToAwt/convert im false false 0))))))497 (import ij.process.ImageProcessor)498 (import java.awt.image.BufferedImage)500 (defprotocol Frame501 (frame [this]))503 (extend-type BufferedImage504 Frame505 (frame [image]506 (merge507 (apply508 hash-map509 (interleave510 (doall (for [x (range (.getWidth image)) y (range (.getHeight image))]511 (vector x y)))512 (doall (for [x (range (.getWidth image)) y (range (.getHeight image))]513 (let [data (.getRGB image x y)]514 (hash-map :r (bit-shift-right (bit-and 0xff0000 data) 16)515 :g (bit-shift-right (bit-and 0x00ff00 data) 8)516 :b (bit-and 0x0000ff data)))))))517 {:width (.getWidth image) :height (.getHeight image)})))520 (extend-type ImagePlus521 Frame522 (frame [image+]523 (frame (.getBufferedImage image+))))526 (def white -1)528 (defn filter-pixels529 "List the coordinates of all pixels matching pred."530 {:author "Dylan Holmes"}531 [pred #^ImageProcessor ip]532 (let533 [width (.getWidth ip)534 height (.getHeight ip)]535 ((fn accumulate [x y matches]536 (cond537 (>= y height) matches538 (>= x width) (recur 0 (inc y) matches)539 (pred (.getPixel ip x y))540 (recur (inc x) y (conj matches (Vector2f. x y)))541 :else (recur (inc x) y matches)))542 0 0 [])))544 (defn white-coordinates545 "List the coordinates of all the white pixels in an image."546 [#^ImageProcessor ip]547 (filter-pixels #(= % white) ip))549 (defn same-side?550 "Given the points p1 and p2 and the reference point ref, is point p551 on the same side of the line that goes through p1 and p2 as ref is?"552 [p1 p2 ref p]553 (<=554 0555 (.dot556 (.cross (.subtract p2 p1) (.subtract p p1))557 (.cross (.subtract p2 p1) (.subtract ref p1)))))559 (defn triangle->matrix4f560 "Converts the triangle into a 4x4 matrix of vertices: The first561 three columns contain the vertices of the triangle; the last562 contains the unit normal of the triangle. The bottom row is filled563 with 1s."564 [#^Triangle t]565 (let [mat (Matrix4f.)566 [vert-1 vert-2 vert-3]567 ((comp vec map) #(.get t %) (range 3))568 unit-normal (do (.calculateNormal t)(.getNormal t))569 vertices [vert-1 vert-2 vert-3 unit-normal]]570 (dorun571 (for [row (range 4) col (range 3)]572 (do573 (.set mat col row (.get (vertices row)col))574 (.set mat 3 row 1))))575 mat))577 (defn triangle-transformation578 "Returns the affine transformation that converts each vertex in the579 first triangle into the corresponding vertex in the second580 triangle."581 [#^Triangle tri-1 #^Triangle tri-2]582 (.mult583 (triangle->matrix4f tri-2)584 (.invert (triangle->matrix4f tri-1))))586 (def death (Triangle.587 (Vector3f. 1 1 1)588 (Vector3f. 1 2 3)589 (Vector3f. 5 6 7)))591 (def death-2 (Triangle.592 (Vector3f. 2 2 2)593 (Vector3f. 1 1 1)594 (Vector3f. 0 1 0)))596 (defn vector2f->vector3f [v]597 (Vector3f. (.getX v) (.getY v) 0))599 (extend-type Triangle600 Textual601 (text [t]602 (println "Triangle: " \newline (.get1 t) \newline603 (.get2 t) \newline (.get3 t))))605 (defn map-triangle [f #^Triangle tri]606 (Triangle.607 (f 0 (.get1 tri))608 (f 1 (.get2 tri))609 (f 2 (.get3 tri))))611 (defn triangle-seq [#^Triangle tri]612 [(.get1 tri) (.get2 tri) (.get3 tri)])614 (defn vector3f-seq [#^Vector3f v]615 [(.getX v) (.getY v) (.getZ v)])617 (defn inside-triangle?618 "Is the point inside the triangle? Now what do we do?619 You might want to hold on there"620 {:author "Dylan Holmes"}621 [tri p]622 (let [[vert-1 vert-2 vert-3] (triangle-seq tri)]623 (and624 (same-side? vert-1 vert-2 vert-3 p)625 (same-side? vert-2 vert-3 vert-1 p)626 (same-side? vert-3 vert-1 vert-2 p))))628 (defn uv-triangle629 "Convert the mesh triangle into the cooresponding triangle in630 UV-space. Z-component of these triangles is always zero."631 [#^Mesh mesh #^Triangle tri]632 (apply #(Triangle. %1 %2 %3)633 (map vector2f->vector3f634 (tri-uv-coord mesh tri))))636 (defn pixel-triangle637 "Convert the mesh triangle into the corresponding triangle in638 UV-pixel-space. Z compenent will be zero."639 [#^Mesh mesh #^Triangle tri width height]640 (map-triangle (fn [_ v]641 (Vector3f. (* width (.getX v))642 (* height (.getY v))643 0))644 (uv-triangle mesh tri)))646 (def rasterize pixel-triangle)649 (defn triangle-bounds650 "Dimensions of the bounding square of the triangle in the form651 [x y width height].652 Assumes that the triangle lies in the XY plane."653 [#^Triangle tri]654 (let [verts (map vector3f-seq (triangle-seq tri))655 x (apply min (map first verts))656 y (apply min (map second verts))]657 [x y658 (- (apply max (map first verts)) x)659 (- (apply max (map second verts)) y)660 ]))663 (defn locate-feelers664 "Search the geometry's tactile UV image for touch sensors, returning665 their positions in geometry-relative coordinates."666 [#^Geometry geo]667 (if-let [image (touch-receptor-image geo)]668 (let [mesh (.getMesh geo)669 tris (triangles geo)671 width (.getWidth image)672 height (.getHeight image)674 ;; for each triangle675 sensor-coords676 (fn [tri]677 ;; translate triangle to uv-pixel-space678 (let [uv-tri679 (pixel-triangle mesh tri width height)680 bounds (vec (triangle-bounds uv-tri))]682 ;; get that part of the picture684 (apply #(.setRoi image %1 %2 %3 %4) bounds)685 (let [cutout (.crop (.getProcessor image))686 ;; extract white pixels inside triangle687 cutout-tri688 (map-triangle689 (fn [_ v]690 (.subtract691 v692 (Vector3f. (bounds 0) (bounds 1) (float 0))))693 uv-tri)694 whites (filter (partial inside-triangle? cutout-tri)695 (map vector2f->vector3f696 (white-coordinates cutout)))697 ;; translate pixel coordinates to world-space698 transform (triangle-transformation cutout-tri tri)]699 (map #(.mult transform %) whites))))]700 (vec (map sensor-coords tris)))701 (repeat (count (triangles geo)) [])))703 (use 'clojure.contrib.def)705 (defn-memo touch-topology [#^Gemoetry geo]706 (let [feeler-coords707 (map708 #(vector (int (.getX %)) (int (.getY %)))709 (white-coordinates710 (.getProcessor (touch-receptor-image (colorful)))))]711 (vec (collapse feeler-coords))))713 (defn enable-touch [#^Geometry geo]714 (let [feeler-coords (locate-feelers geo)715 tris (triangles geo)716 limit 0.1]717 (fn [node]718 (let [sensor-origins719 (map720 #(map (partial local-to-world geo) %)721 feeler-coords)722 triangle-normals723 (map (partial get-ray-direction geo)724 tris)725 rays726 (flatten727 (map (fn [origins norm]728 (map #(doto (Ray. % norm)729 (.setLimit limit)) origins))730 sensor-origins triangle-normals))]731 (vector732 (touch-topology geo)733 (vec734 (for [ray rays]735 (do736 (let [results (CollisionResults.)]737 (.collideWith node ray results)738 (let [touch-objects739 (set740 (filter #(not (= geo %))741 (map #(.getGeometry %) results)))]742 (if (> (count touch-objects) 0)743 1 0)))))))))))745 (defn touch [#^Node pieces]746 (map enable-touch747 (filter #(isa? (class %) Geometry)748 (node-seq pieces))))751 (defn all-names []752 (concat753 (re-split #"\n" (slurp (file-str754 "/home/r/proj/names/dist.female.first")))755 (re-split #"\n" (slurp (file-str756 "/home/r/proj/names/dist.male.first")))757 (re-split #"\n" (slurp (file-str758 "/home/r/proj/names/dist.all.last")))))768 (defrecord LulzLoader [])769 (defprotocol Lulzable (load-lulz [this]))770 (extend-type LulzLoader771 Lulzable772 (load-lulz [this] (println "the lulz have arrived!")))775 (defn world-setup [joint]776 (let [joint-position (Vector3f. 0 0 0)777 joint-rotation778 (.toRotationMatrix779 (.mult780 (doto (Quaternion.)781 (.fromAngleAxis782 (* 1 (/ Math/PI 4))783 (Vector3f. -1 0 0)))784 (doto (Quaternion.)785 (.fromAngleAxis786 (* 1 (/ Math/PI 2))787 (Vector3f. 0 0 1)))))788 top-position (.mult joint-rotation (Vector3f. 8 0 0))790 origin (doto791 (sphere 0.1 :physical? false :color ColorRGBA/Cyan792 :position top-position))793 top (doto794 (sphere 0.1 :physical? false :color ColorRGBA/Yellow795 :position top-position)797 (.addControl798 (RigidBodyControl.799 (CapsuleCollisionShape. 0.5 1.5 1) (float 20))))800 bottom (doto801 (sphere 0.1 :physical? false :color ColorRGBA/DarkGray802 :position (Vector3f. 0 0 0))803 (.addControl804 (RigidBodyControl.805 (CapsuleCollisionShape. 0.5 1.5 1) (float 0))))806 table (box 10 2 10 :position (Vector3f. 0 -20 0)807 :color ColorRGBA/Gray :mass 0)808 a (.getControl top RigidBodyControl)809 b (.getControl bottom RigidBodyControl)]811 (cond812 (= joint :cone)814 (doto (ConeJoint.815 a b816 (world-to-local top joint-position)817 (world-to-local bottom joint-position)818 joint-rotation819 joint-rotation820 )823 (.setLimit (* (/ 10) Math/PI)824 (* (/ 4) Math/PI)825 0)))826 [origin top bottom table]))828 (defn test-joint [joint]829 (let [[origin top bottom floor] (world-setup joint)830 control (.getControl top RigidBodyControl)831 move-up? (atom false)832 move-down? (atom false)833 move-left? (atom false)834 move-right? (atom false)835 roll-left? (atom false)836 roll-right? (atom false)837 timer (atom 0)]839 (world840 (nodify [top bottom floor origin])841 (merge standard-debug-controls842 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))843 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))844 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))845 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))846 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))847 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})849 (fn [world]850 (light-up-everything world)851 (enable-debug world)852 (set-gravity world (Vector3f. 0 0 0))853 )855 (fn [world _]856 (if (zero? (rem (swap! timer inc) 100))857 (do858 ;; (println-repl @timer)859 (.attachChild (.getRootNode world)860 (sphere 0.05 :color ColorRGBA/Yellow861 :position (.getWorldTranslation top)862 :physical? false))863 (.attachChild (.getRootNode world)864 (sphere 0.05 :color ColorRGBA/LightGray865 :position (.getWorldTranslation bottom)866 :physical? false))))868 (if @move-up?869 (.applyTorque control870 (.mult (.getPhysicsRotation control)871 (Vector3f. 0 0 10))))872 (if @move-down?873 (.applyTorque control874 (.mult (.getPhysicsRotation control)875 (Vector3f. 0 0 -10))))876 (if @move-left?877 (.applyTorque control878 (.mult (.getPhysicsRotation control)879 (Vector3f. 0 10 0))))880 (if @move-right?881 (.applyTorque control882 (.mult (.getPhysicsRotation control)883 (Vector3f. 0 -10 0))))884 (if @roll-left?885 (.applyTorque control886 (.mult (.getPhysicsRotation control)887 (Vector3f. -1 0 0))))888 (if @roll-right?889 (.applyTorque control890 (.mult (.getPhysicsRotation control)891 (Vector3f. 1 0 0))))))))894 (defn locate-feelers*895 "Search the geometry's tactile UV image for touch sensors, returning896 their positions in geometry-relative coordinates."897 [#^Geometry geo]898 (let [uv-image (touch-receptor-image geo)899 width (.getWidth uv-image)900 height (.getHeight uv-image)902 mesh (.getMesh geo)903 mesh-tris (triangles geo)905 ;; for each triangle906 sensor-coords907 (fn [tri]908 ;; translate triangle to uv-pixel-space909 (let [uv-tri910 (rasterize mesh tri width height)911 bounds (vec (triangle-bounds uv-tri))]913 ;; get that part of the picture915 (apply (partial (memfn setRoi) uv-image) bounds)916 (let [cutout (.crop (.getProcessor uv-image))917 ;; extract white pixels inside triangle918 cutout-tri919 (map-triangle920 (fn [_ v]921 (.subtract922 v923 (Vector3f. (bounds 0) (bounds 1) (float 0))))924 uv-tri)925 whites (filter (partial inside-triangle? cutout-tri)926 (map vector2f->vector3f927 (white-coordinates cutout)))928 ;; translate pixel coordinates to world-space929 transform (triangle-transformation cutout-tri tri)]930 (map #(.mult transform %) whites))))]932 (for [mesh-tri mesh-tris]934 (let [uv-tri (rasterize mesh mesh-tri width height)935 bounding-box (vec (triangle-bounds uv-tri))]936 (apply (partial (memfn setRoi) uv-image) bounding-box)937 ))938 (vec (map sensor-coords mesh-tris))))941 (defn tactile-coords [#^Geometry obj]942 (let [mesh (.getMesh obj)943 num-triangles (.getTriangleCount mesh)944 num-verticies (.getVertexCount mesh)945 uv-coord (partial uv-coord mesh)946 triangle-indices (partial triangle-indices mesh)947 receptors (touch-receptor-image obj)948 tris (triangles obj)949 ]950 (map951 (fn [[tri-1 tri-2 tri-3]]952 (let [width (.getWidth receptors)953 height (.getHeight receptors)954 uv-1 (uv-coord tri-1)955 uv-2 (uv-coord tri-2)956 uv-3 (uv-coord tri-3)957 x-coords (map #(.getX %) [uv-1 uv-2 uv-3])958 y-coords (map #(.getY %) [uv-1 uv-2 uv-3])959 max-x (Math/ceil (* width (apply max x-coords)))960 min-x (Math/floor (* width (apply min x-coords)))961 max-y (Math/ceil (* height (apply max y-coords)))962 min-y (Math/floor (* height (apply min y-coords)))964 image-1 (Vector2f. (* width (.getX uv-1))965 (* height (.getY uv-1)))966 image-2 (Vector2f. (* width (.getX uv-2))967 (* height (.getY uv-2)))968 image-3 (Vector2f. (* width (.getX uv-3))969 (* height (.getY uv-3)))970 left-corner971 (Vector2f. min-x min-y)972 ]974 (.setRoi receptors min-x min-y (- max-x min-x) (- max-y min-y))975 (let [processor (.crop (.getProcessor receptors))]976 (map977 #(.add left-corner %)979 (filter980 (partial981 inside-triangle?982 (.subtract image-1 left-corner)983 (.subtract image-2 left-corner)984 (.subtract image-3 left-corner))985 (white-coordinates processor))))986 )) (map triangle-indices (range num-triangles)))))988 #+end_src990 #+results: body-1991 : #'cortex.silly/test-joint994 * COMMENT purgatory995 #+begin_src clojure996 (defn bullet-trans []997 (let [obj-a (sphere 0.5 :color ColorRGBA/Red998 :position (Vector3f. -10 5 0))999 obj-b (sphere 0.5 :color ColorRGBA/Blue1000 :position (Vector3f. -10 -5 0)1001 :mass 0)1002 control-a (.getControl obj-a RigidBodyControl)1003 control-b (.getControl obj-b RigidBodyControl)1004 swivel1005 (.toRotationMatrix1006 (doto (Quaternion.)1007 (.fromAngleAxis (/ Math/PI 2)1008 Vector3f/UNIT_X)))]1009 (doto1010 (ConeJoint.1011 control-a control-b1012 (Vector3f. 0 5 0)1013 (Vector3f. 0 -5 0)1014 swivel swivel)1015 (.setLimit (* 0.6 (/ Math/PI 4))1016 (/ Math/PI 4)1017 (* Math/PI 0.8)))1018 (world (nodify1019 [obj-a obj-b])1020 standard-debug-controls1021 enable-debug1022 no-op)))1025 (defn bullet-trans* []1026 (let [obj-a (box 1.5 0.5 0.5 :color ColorRGBA/Red1027 :position (Vector3f. 5 0 0)1028 :mass 90)1029 obj-b (sphere 0.5 :color ColorRGBA/Blue1030 :position (Vector3f. -5 0 0)1031 :mass 0)1032 control-a (.getControl obj-a RigidBodyControl)1033 control-b (.getControl obj-b RigidBodyControl)1034 move-up? (atom nil)1035 move-down? (atom nil)1036 move-left? (atom nil)1037 move-right? (atom nil)1038 roll-left? (atom nil)1039 roll-right? (atom nil)1040 force 1001041 swivel1042 (.toRotationMatrix1043 (doto (Quaternion.)1044 (.fromAngleAxis (/ Math/PI 2)1045 Vector3f/UNIT_X)))1046 x-move1047 (doto (Matrix3f.)1048 (.fromStartEndVectors Vector3f/UNIT_X1049 (.normalize (Vector3f. 1 1 0))))1051 timer (atom 0)]1052 (doto1053 (ConeJoint.1054 control-a control-b1055 (Vector3f. -8 0 0)1056 (Vector3f. 2 0 0)1057 ;;swivel swivel1058 ;;Matrix3f/IDENTITY Matrix3f/IDENTITY1059 x-move Matrix3f/IDENTITY1060 )1061 (.setCollisionBetweenLinkedBodys false)1062 (.setLimit (* 1 (/ Math/PI 4)) ;; twist1063 (* 1 (/ Math/PI 4)) ;; swing span in X-Y plane1064 (* 0 (/ Math/PI 4)))) ;; swing span in Y-Z plane1065 (world (nodify1066 [obj-a obj-b])1067 (merge standard-debug-controls1068 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))1069 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))1070 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))1071 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))1072 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))1073 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})1075 (fn [world]1076 (enable-debug world)1077 (set-gravity world Vector3f/ZERO)1078 )1080 (fn [world _]1082 (if @move-up?1083 (.applyForce control-a1084 (Vector3f. force 0 0)1085 (Vector3f. 0 0 0)))1086 (if @move-down?1087 (.applyForce control-a1088 (Vector3f. (- force) 0 0)1089 (Vector3f. 0 0 0)))1090 (if @move-left?1091 (.applyForce control-a1092 (Vector3f. 0 force 0)1093 (Vector3f. 0 0 0)))1094 (if @move-right?1095 (.applyForce control-a1096 (Vector3f. 0 (- force) 0)1097 (Vector3f. 0 0 0)))1099 (if @roll-left?1100 (.applyForce control-a1101 (Vector3f. 0 0 force)1102 (Vector3f. 0 0 0)))1103 (if @roll-right?1104 (.applyForce control-a1105 (Vector3f. 0 0 (- force))1106 (Vector3f. 0 0 0)))1108 (if (zero? (rem (swap! timer inc) 100))1109 (.attachChild1110 (.getRootNode world)1111 (sphere 0.05 :color ColorRGBA/Yellow1112 :physical? false :position1113 (.getWorldTranslation obj-a)))))1114 )1115 ))1117 (defn transform-trianglesdsd1118 "Transform that converts each vertex in the first triangle1119 into the corresponding vertex in the second triangle."1120 [#^Triangle tri-1 #^Triangle tri-2]1121 (let [in [(.get1 tri-1)1122 (.get2 tri-1)1123 (.get3 tri-1)]1124 out [(.get1 tri-2)1125 (.get2 tri-2)1126 (.get3 tri-2)]]1127 (let [translate (doto (Matrix4f.) (.setTranslation (.negate (in 0))))1128 in* [(.mult translate (in 0))1129 (.mult translate (in 1))1130 (.mult translate (in 2))]1131 final-translation1132 (doto (Matrix4f.)1133 (.setTranslation (out 1)))1135 rotate-11136 (doto (Matrix3f.)1137 (.fromStartEndVectors1138 (.normalize1139 (.subtract1140 (in* 1) (in* 0)))1141 (.normalize1142 (.subtract1143 (out 1) (out 0)))))1144 in** [(.mult rotate-1 (in* 0))1145 (.mult rotate-1 (in* 1))1146 (.mult rotate-1 (in* 2))]1147 scale-factor-11148 (.mult1149 (.normalize1150 (.subtract1151 (out 1)1152 (out 0)))1153 (/ (.length1154 (.subtract (out 1)1155 (out 0)))1156 (.length1157 (.subtract (in** 1)1158 (in** 0)))))1159 scale-1 (doto (Matrix4f.) (.setScale scale-factor-1))1160 in*** [(.mult scale-1 (in** 0))1161 (.mult scale-1 (in** 1))1162 (.mult scale-1 (in** 2))]1168 ]1170 (dorun (map println in))1171 (println)1172 (dorun (map println in*))1173 (println)1174 (dorun (map println in**))1175 (println)1176 (dorun (map println in***))1177 (println)1179 ))))1184 #+end_src1187 * COMMENT generate source1188 #+begin_src clojure :tangle ../src/cortex/silly.clj1189 <<body-1>>1190 #+end_src