Mercurial > cortex
view org/test-creature.org @ 103:85ee8bb80edf
can now visuliaze touch data
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 14 Jan 2012 21:15:44 -0700 |
parents | 7eeb940bcbc8 |
children | ee302b65213b |
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 - [X] get an overall bitmap-like image for touch12 - [X] 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))))750 (defn debug-window751 "creates function that offers a debug view of sensor data"752 []753 (let [vi (view-image)]754 (fn755 [[coords sensor-data]]756 (let [image (points->image coords)]757 (dorun758 (for [i (range (count coords))]759 (.setRGB image ((coords i) 0) ((coords i) 1)760 ({0 -16777216761 1 -1} (sensor-data i)))))762 (vi image)))))765 (defn all-names []766 (concat767 (re-split #"\n" (slurp (file-str768 "/home/r/proj/names/dist.female.first")))769 (re-split #"\n" (slurp (file-str770 "/home/r/proj/names/dist.male.first")))771 (re-split #"\n" (slurp (file-str772 "/home/r/proj/names/dist.all.last")))))782 (defrecord LulzLoader [])783 (defprotocol Lulzable (load-lulz [this]))784 (extend-type LulzLoader785 Lulzable786 (load-lulz [this] (println "the lulz have arrived!")))789 (defn world-setup [joint]790 (let [joint-position (Vector3f. 0 0 0)791 joint-rotation792 (.toRotationMatrix793 (.mult794 (doto (Quaternion.)795 (.fromAngleAxis796 (* 1 (/ Math/PI 4))797 (Vector3f. -1 0 0)))798 (doto (Quaternion.)799 (.fromAngleAxis800 (* 1 (/ Math/PI 2))801 (Vector3f. 0 0 1)))))802 top-position (.mult joint-rotation (Vector3f. 8 0 0))804 origin (doto805 (sphere 0.1 :physical? false :color ColorRGBA/Cyan806 :position top-position))807 top (doto808 (sphere 0.1 :physical? false :color ColorRGBA/Yellow809 :position top-position)811 (.addControl812 (RigidBodyControl.813 (CapsuleCollisionShape. 0.5 1.5 1) (float 20))))814 bottom (doto815 (sphere 0.1 :physical? false :color ColorRGBA/DarkGray816 :position (Vector3f. 0 0 0))817 (.addControl818 (RigidBodyControl.819 (CapsuleCollisionShape. 0.5 1.5 1) (float 0))))820 table (box 10 2 10 :position (Vector3f. 0 -20 0)821 :color ColorRGBA/Gray :mass 0)822 a (.getControl top RigidBodyControl)823 b (.getControl bottom RigidBodyControl)]825 (cond826 (= joint :cone)828 (doto (ConeJoint.829 a b830 (world-to-local top joint-position)831 (world-to-local bottom joint-position)832 joint-rotation833 joint-rotation834 )837 (.setLimit (* (/ 10) Math/PI)838 (* (/ 4) Math/PI)839 0)))840 [origin top bottom table]))842 (defn test-joint [joint]843 (let [[origin top bottom floor] (world-setup joint)844 control (.getControl top RigidBodyControl)845 move-up? (atom false)846 move-down? (atom false)847 move-left? (atom false)848 move-right? (atom false)849 roll-left? (atom false)850 roll-right? (atom false)851 timer (atom 0)]853 (world854 (nodify [top bottom floor origin])855 (merge standard-debug-controls856 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))857 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))858 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))859 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))860 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))861 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})863 (fn [world]864 (light-up-everything world)865 (enable-debug world)866 (set-gravity world (Vector3f. 0 0 0))867 )869 (fn [world _]870 (if (zero? (rem (swap! timer inc) 100))871 (do872 ;; (println-repl @timer)873 (.attachChild (.getRootNode world)874 (sphere 0.05 :color ColorRGBA/Yellow875 :position (.getWorldTranslation top)876 :physical? false))877 (.attachChild (.getRootNode world)878 (sphere 0.05 :color ColorRGBA/LightGray879 :position (.getWorldTranslation bottom)880 :physical? false))))882 (if @move-up?883 (.applyTorque control884 (.mult (.getPhysicsRotation control)885 (Vector3f. 0 0 10))))886 (if @move-down?887 (.applyTorque control888 (.mult (.getPhysicsRotation control)889 (Vector3f. 0 0 -10))))890 (if @move-left?891 (.applyTorque control892 (.mult (.getPhysicsRotation control)893 (Vector3f. 0 10 0))))894 (if @move-right?895 (.applyTorque control896 (.mult (.getPhysicsRotation control)897 (Vector3f. 0 -10 0))))898 (if @roll-left?899 (.applyTorque control900 (.mult (.getPhysicsRotation control)901 (Vector3f. -1 0 0))))902 (if @roll-right?903 (.applyTorque control904 (.mult (.getPhysicsRotation control)905 (Vector3f. 1 0 0))))))))908 (defn locate-feelers*909 "Search the geometry's tactile UV image for touch sensors, returning910 their positions in geometry-relative coordinates."911 [#^Geometry geo]912 (let [uv-image (touch-receptor-image geo)913 width (.getWidth uv-image)914 height (.getHeight uv-image)916 mesh (.getMesh geo)917 mesh-tris (triangles geo)919 ;; for each triangle920 sensor-coords921 (fn [tri]922 ;; translate triangle to uv-pixel-space923 (let [uv-tri924 (rasterize mesh tri width height)925 bounds (vec (triangle-bounds uv-tri))]927 ;; get that part of the picture929 (apply (partial (memfn setRoi) uv-image) bounds)930 (let [cutout (.crop (.getProcessor uv-image))931 ;; extract white pixels inside triangle932 cutout-tri933 (map-triangle934 (fn [_ v]935 (.subtract936 v937 (Vector3f. (bounds 0) (bounds 1) (float 0))))938 uv-tri)939 whites (filter (partial inside-triangle? cutout-tri)940 (map vector2f->vector3f941 (white-coordinates cutout)))942 ;; translate pixel coordinates to world-space943 transform (triangle-transformation cutout-tri tri)]944 (map #(.mult transform %) whites))))]946 (for [mesh-tri mesh-tris]948 (let [uv-tri (rasterize mesh mesh-tri width height)949 bounding-box (vec (triangle-bounds uv-tri))]950 (apply (partial (memfn setRoi) uv-image) bounding-box)951 ))952 (vec (map sensor-coords mesh-tris))))955 (defn tactile-coords [#^Geometry obj]956 (let [mesh (.getMesh obj)957 num-triangles (.getTriangleCount mesh)958 num-verticies (.getVertexCount mesh)959 uv-coord (partial uv-coord mesh)960 triangle-indices (partial triangle-indices mesh)961 receptors (touch-receptor-image obj)962 tris (triangles obj)963 ]964 (map965 (fn [[tri-1 tri-2 tri-3]]966 (let [width (.getWidth receptors)967 height (.getHeight receptors)968 uv-1 (uv-coord tri-1)969 uv-2 (uv-coord tri-2)970 uv-3 (uv-coord tri-3)971 x-coords (map #(.getX %) [uv-1 uv-2 uv-3])972 y-coords (map #(.getY %) [uv-1 uv-2 uv-3])973 max-x (Math/ceil (* width (apply max x-coords)))974 min-x (Math/floor (* width (apply min x-coords)))975 max-y (Math/ceil (* height (apply max y-coords)))976 min-y (Math/floor (* height (apply min y-coords)))978 image-1 (Vector2f. (* width (.getX uv-1))979 (* height (.getY uv-1)))980 image-2 (Vector2f. (* width (.getX uv-2))981 (* height (.getY uv-2)))982 image-3 (Vector2f. (* width (.getX uv-3))983 (* height (.getY uv-3)))984 left-corner985 (Vector2f. min-x min-y)986 ]988 (.setRoi receptors min-x min-y (- max-x min-x) (- max-y min-y))989 (let [processor (.crop (.getProcessor receptors))]990 (map991 #(.add left-corner %)993 (filter994 (partial995 inside-triangle?996 (.subtract image-1 left-corner)997 (.subtract image-2 left-corner)998 (.subtract image-3 left-corner))999 (white-coordinates processor))))1000 )) (map triangle-indices (range num-triangles)))))1002 #+end_src1004 #+results: body-11005 : #'cortex.silly/test-joint1008 * COMMENT purgatory1009 #+begin_src clojure1010 (defn bullet-trans []1011 (let [obj-a (sphere 0.5 :color ColorRGBA/Red1012 :position (Vector3f. -10 5 0))1013 obj-b (sphere 0.5 :color ColorRGBA/Blue1014 :position (Vector3f. -10 -5 0)1015 :mass 0)1016 control-a (.getControl obj-a RigidBodyControl)1017 control-b (.getControl obj-b RigidBodyControl)1018 swivel1019 (.toRotationMatrix1020 (doto (Quaternion.)1021 (.fromAngleAxis (/ Math/PI 2)1022 Vector3f/UNIT_X)))]1023 (doto1024 (ConeJoint.1025 control-a control-b1026 (Vector3f. 0 5 0)1027 (Vector3f. 0 -5 0)1028 swivel swivel)1029 (.setLimit (* 0.6 (/ Math/PI 4))1030 (/ Math/PI 4)1031 (* Math/PI 0.8)))1032 (world (nodify1033 [obj-a obj-b])1034 standard-debug-controls1035 enable-debug1036 no-op)))1039 (defn bullet-trans* []1040 (let [obj-a (box 1.5 0.5 0.5 :color ColorRGBA/Red1041 :position (Vector3f. 5 0 0)1042 :mass 90)1043 obj-b (sphere 0.5 :color ColorRGBA/Blue1044 :position (Vector3f. -5 0 0)1045 :mass 0)1046 control-a (.getControl obj-a RigidBodyControl)1047 control-b (.getControl obj-b RigidBodyControl)1048 move-up? (atom nil)1049 move-down? (atom nil)1050 move-left? (atom nil)1051 move-right? (atom nil)1052 roll-left? (atom nil)1053 roll-right? (atom nil)1054 force 1001055 swivel1056 (.toRotationMatrix1057 (doto (Quaternion.)1058 (.fromAngleAxis (/ Math/PI 2)1059 Vector3f/UNIT_X)))1060 x-move1061 (doto (Matrix3f.)1062 (.fromStartEndVectors Vector3f/UNIT_X1063 (.normalize (Vector3f. 1 1 0))))1065 timer (atom 0)]1066 (doto1067 (ConeJoint.1068 control-a control-b1069 (Vector3f. -8 0 0)1070 (Vector3f. 2 0 0)1071 ;;swivel swivel1072 ;;Matrix3f/IDENTITY Matrix3f/IDENTITY1073 x-move Matrix3f/IDENTITY1074 )1075 (.setCollisionBetweenLinkedBodys false)1076 (.setLimit (* 1 (/ Math/PI 4)) ;; twist1077 (* 1 (/ Math/PI 4)) ;; swing span in X-Y plane1078 (* 0 (/ Math/PI 4)))) ;; swing span in Y-Z plane1079 (world (nodify1080 [obj-a obj-b])1081 (merge standard-debug-controls1082 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))1083 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))1084 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))1085 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))1086 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))1087 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})1089 (fn [world]1090 (enable-debug world)1091 (set-gravity world Vector3f/ZERO)1092 )1094 (fn [world _]1096 (if @move-up?1097 (.applyForce control-a1098 (Vector3f. force 0 0)1099 (Vector3f. 0 0 0)))1100 (if @move-down?1101 (.applyForce control-a1102 (Vector3f. (- force) 0 0)1103 (Vector3f. 0 0 0)))1104 (if @move-left?1105 (.applyForce control-a1106 (Vector3f. 0 force 0)1107 (Vector3f. 0 0 0)))1108 (if @move-right?1109 (.applyForce control-a1110 (Vector3f. 0 (- force) 0)1111 (Vector3f. 0 0 0)))1113 (if @roll-left?1114 (.applyForce control-a1115 (Vector3f. 0 0 force)1116 (Vector3f. 0 0 0)))1117 (if @roll-right?1118 (.applyForce control-a1119 (Vector3f. 0 0 (- force))1120 (Vector3f. 0 0 0)))1122 (if (zero? (rem (swap! timer inc) 100))1123 (.attachChild1124 (.getRootNode world)1125 (sphere 0.05 :color ColorRGBA/Yellow1126 :physical? false :position1127 (.getWorldTranslation obj-a)))))1128 )1129 ))1131 (defn transform-trianglesdsd1132 "Transform that converts each vertex in the first triangle1133 into the corresponding vertex in the second triangle."1134 [#^Triangle tri-1 #^Triangle tri-2]1135 (let [in [(.get1 tri-1)1136 (.get2 tri-1)1137 (.get3 tri-1)]1138 out [(.get1 tri-2)1139 (.get2 tri-2)1140 (.get3 tri-2)]]1141 (let [translate (doto (Matrix4f.) (.setTranslation (.negate (in 0))))1142 in* [(.mult translate (in 0))1143 (.mult translate (in 1))1144 (.mult translate (in 2))]1145 final-translation1146 (doto (Matrix4f.)1147 (.setTranslation (out 1)))1149 rotate-11150 (doto (Matrix3f.)1151 (.fromStartEndVectors1152 (.normalize1153 (.subtract1154 (in* 1) (in* 0)))1155 (.normalize1156 (.subtract1157 (out 1) (out 0)))))1158 in** [(.mult rotate-1 (in* 0))1159 (.mult rotate-1 (in* 1))1160 (.mult rotate-1 (in* 2))]1161 scale-factor-11162 (.mult1163 (.normalize1164 (.subtract1165 (out 1)1166 (out 0)))1167 (/ (.length1168 (.subtract (out 1)1169 (out 0)))1170 (.length1171 (.subtract (in** 1)1172 (in** 0)))))1173 scale-1 (doto (Matrix4f.) (.setScale scale-factor-1))1174 in*** [(.mult scale-1 (in** 0))1175 (.mult scale-1 (in** 1))1176 (.mult scale-1 (in** 2))]1182 ]1184 (dorun (map println in))1185 (println)1186 (dorun (map println in*))1187 (println)1188 (dorun (map println in**))1189 (println)1190 (dorun (map println in***))1191 (println)1193 ))))1198 #+end_src1201 * COMMENT generate source1202 #+begin_src clojure :tangle ../src/cortex/silly.clj1203 <<body-1>>1204 #+end_src