Mercurial > cortex
view org/test-creature.org @ 115:247860e25536
added eye to creature in blender
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Thu, 19 Jan 2012 22:26:16 -0700 |
parents | 9d0fe7f54e14 |
children | 947bef5d6670 |
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.org9 * objectives10 - [X] get an overall bitmap-like image for touch11 - [X] write code to visuliaze this bitmap12 - [ ] directly change the UV-pixels to show touch sensor activation13 - [ ] write an explination for why b&w bitmaps for senses is appropiate14 - [ ] clean up touch code and write visulazation test15 - [ ] do the same for eyes17 * Intro18 So far, I've made the following senses --19 - Vision20 - Hearing21 - Touch22 - Proprioception24 And one effector:25 - Movement27 However, the code so far has only enabled these senses, but has not28 actually implemented them. For example, there is still a lot of work29 to be done for vision. I need to be able to create an /eyeball/ in30 simulation that can be moved around and see the world from different31 angles. I also need to determine weather to use log-polar or cartesian32 for the visual input, and I need to determine how/wether to33 disceritise the visual input.35 I also want to be able to visualize both the sensors and the36 effectors in pretty pictures. This semi-retarted creature will be my37 first attempt at bringing everything together.39 * The creature's body41 Still going to do an eve-like body in blender, but due to problems42 importing the joints, etc into jMonkeyEngine3, I'm going to do all43 the connecting here in clojure code, using the names of the individual44 components and trial and error. Later, I'll maybe make some sort of45 creature-building modifications to blender that support whatever46 discreitized senses I'm going to make.48 #+name: body-149 #+begin_src clojure50 (ns cortex.silly51 "let's play!"52 {:author "Robert McIntyre"})54 ;; TODO remove this!55 (require 'cortex.import)56 (cortex.import/mega-import-jme3)57 (use '(cortex world util body hearing touch vision))59 (rlm.rlm-commands/help)60 (import java.awt.image.BufferedImage)61 (import javax.swing.JPanel)62 (import javax.swing.SwingUtilities)63 (import java.awt.Dimension)64 (import javax.swing.JFrame)65 (import java.awt.Dimension)66 (import com.aurellem.capture.RatchetTimer)67 (declare joint-create)68 (use 'clojure.contrib.def)70 (defn points->image71 "Take a sparse collection of points and visuliaze it as a72 BufferedImage."74 ;; TODO maybe parallelize this since it's easy76 [points]77 (if (empty? points)78 (BufferedImage. 1 1 BufferedImage/TYPE_BYTE_BINARY)79 (let [xs (vec (map first points))80 ys (vec (map second points))81 x0 (apply min xs)82 y0 (apply min ys)83 width (- (apply max xs) x0)84 height (- (apply max ys) y0)85 image (BufferedImage. (inc width) (inc height)86 BufferedImage/TYPE_BYTE_BINARY)]87 (dorun88 (for [index (range (count points))]89 (.setRGB image (- (xs index) x0) (- (ys index) y0) -1)))91 image)))93 (defn average [coll]94 (/ (reduce + coll) (count coll)))96 (defn collapse-1d97 "One dimensional analogue of collapse"98 [center line]99 (let [length (count line)100 num-above (count (filter (partial < center) line))101 num-below (- length num-above)]102 (range (- center num-below)103 (+ center num-above))))105 (defn collapse106 "Take a set of pairs of integers and collapse them into a107 contigous bitmap."108 [points]109 (if (empty? points) []110 (let111 [num-points (count points)112 center (vector113 (int (average (map first points)))114 (int (average (map first points))))115 flattened116 (reduce117 concat118 (map119 (fn [column]120 (map vector121 (map first column)122 (collapse-1d (second center)123 (map second column))))124 (partition-by first (sort-by first points))))125 squeezed126 (reduce127 concat128 (map129 (fn [row]130 (map vector131 (collapse-1d (first center)132 (map first row))133 (map second row)))134 (partition-by second (sort-by second flattened))))135 relocate136 (let [min-x (apply min (map first squeezed))137 min-y (apply min (map second squeezed))]138 (map (fn [[x y]]139 [(- x min-x)140 (- y min-y)])141 squeezed))]142 relocate)))144 (defn load-bullet []145 (let [sim (world (Node.) {} no-op no-op)]146 (doto sim147 (.enqueue148 (fn []149 (.stop sim)))150 (.start))))152 (defn load-blender-model153 "Load a .blend file using an asset folder relative path."154 [^String model]155 (.loadModel156 (doto (asset-manager)157 (.registerLoader BlenderModelLoader (into-array String ["blend"])))158 model))160 (defn meta-data [blender-node key]161 (if-let [data (.getUserData blender-node "properties")]162 (.findValue data key)163 nil))165 (defn blender-to-jme166 "Convert from Blender coordinates to JME coordinates"167 [#^Vector3f in]168 (Vector3f. (.getX in)169 (.getZ in)170 (- (.getY in))))172 (defn jme-to-blender173 "Convert from JME coordinates to Blender coordinates"174 [#^Vector3f in]175 (Vector3f. (.getX in)176 (- (.getZ in))177 (.getY in)))179 (defn joint-targets180 "Return the two closest two objects to the joint object, ordered181 from bottom to top according to the joint's rotation."182 [#^Node parts #^Node joint]183 ;;(println (meta-data joint "joint"))184 (.getWorldRotation joint)185 (loop [radius (float 0.01)]186 (let [results (CollisionResults.)]187 (.collideWith188 parts189 (BoundingBox. (.getWorldTranslation joint)190 radius radius radius)191 results)192 (let [targets193 (distinct194 (map #(.getGeometry %) results))]195 (if (>= (count targets) 2)196 (sort-by197 #(let [v198 (jme-to-blender199 (.mult200 (.inverse (.getWorldRotation joint))201 (.subtract (.getWorldTranslation %)202 (.getWorldTranslation joint))))]203 (println-repl (.getName %) ":" v)204 (.dot (Vector3f. 1 1 1)205 v))206 (take 2 targets))207 (recur (float (* radius 2))))))))209 (defn world-to-local210 "Convert the world coordinates into coordinates relative to the211 object (i.e. local coordinates), taking into account the rotation212 of object."213 [#^Spatial object world-coordinate]214 (let [out (Vector3f.)]215 (.worldToLocal object world-coordinate out) out))217 (defn local-to-world218 "Convert the local coordinates into coordinates into world relative219 coordinates"220 [#^Spatial object local-coordinate]221 (let [world-coordinate (Vector3f.)]222 (.localToWorld object local-coordinate world-coordinate)223 world-coordinate))225 (defmulti joint-dispatch226 "Translate blender pseudo-joints into real JME joints."227 (fn [constraints & _]228 (:type constraints)))230 (defmethod joint-dispatch :point231 [constraints control-a control-b pivot-a pivot-b rotation]232 (println-repl "creating POINT2POINT joint")233 (Point2PointJoint.234 control-a235 control-b236 pivot-a237 pivot-b))239 (defmethod joint-dispatch :hinge240 [constraints control-a control-b pivot-a pivot-b rotation]241 (println-repl "creating HINGE joint")242 (let [axis243 (if-let244 [axis (:axis constraints)]245 axis246 Vector3f/UNIT_X)247 [limit-1 limit-2] (:limit constraints)248 hinge-axis249 (.mult250 rotation251 (blender-to-jme axis))]252 (doto253 (HingeJoint.254 control-a255 control-b256 pivot-a257 pivot-b258 hinge-axis259 hinge-axis)260 (.setLimit limit-1 limit-2))))262 (defmethod joint-dispatch :cone263 [constraints control-a control-b pivot-a pivot-b rotation]264 (let [limit-xz (:limit-xz constraints)265 limit-xy (:limit-xy constraints)266 twist (:twist constraints)]268 (println-repl "creating CONE joint")269 (println-repl rotation)270 (println-repl271 "UNIT_X --> " (.mult rotation (Vector3f. 1 0 0)))272 (println-repl273 "UNIT_Y --> " (.mult rotation (Vector3f. 0 1 0)))274 (println-repl275 "UNIT_Z --> " (.mult rotation (Vector3f. 0 0 1)))276 (doto277 (ConeJoint.278 control-a279 control-b280 pivot-a281 pivot-b282 rotation283 rotation)284 (.setLimit (float limit-xz)285 (float limit-xy)286 (float twist)))))288 (defn connect289 "here are some examples:290 {:type :point}291 {:type :hinge :limit [0 (/ Math/PI 2)] :axis (Vector3f. 0 1 0)}292 (:axis defaults to (Vector3f. 1 0 0) if not provided for hinge joints)294 {:type :cone :limit-xz 0]295 :limit-xy 0]296 :twist 0]} (use XZY rotation mode in blender!)"297 [#^Node obj-a #^Node obj-b #^Node joint]298 (let [control-a (.getControl obj-a RigidBodyControl)299 control-b (.getControl obj-b RigidBodyControl)300 joint-center (.getWorldTranslation joint)301 joint-rotation (.toRotationMatrix (.getWorldRotation joint))302 pivot-a (world-to-local obj-a joint-center)303 pivot-b (world-to-local obj-b joint-center)]305 (if-let [constraints306 (map-vals307 eval308 (read-string309 (meta-data joint "joint")))]310 ;; A side-effect of creating a joint registers311 ;; it with both physics objects which in turn312 ;; will register the joint with the physics system313 ;; when the simulation is started.314 (do315 (println-repl "creating joint between"316 (.getName obj-a) "and" (.getName obj-b))317 (joint-dispatch constraints318 control-a control-b319 pivot-a pivot-b320 joint-rotation))321 (println-repl "could not find joint meta-data!"))))323 (defn assemble-creature [#^Node pieces joints]324 (dorun325 (map326 (fn [geom]327 (let [physics-control328 (RigidBodyControl.329 (HullCollisionShape.330 (.getMesh geom))331 (if-let [mass (meta-data geom "mass")]332 (do333 (println-repl334 "setting" (.getName geom) "mass to" (float mass))335 (float mass))336 (float 1)))]338 (.addControl geom physics-control)))339 (filter #(isa? (class %) Geometry )340 (node-seq pieces))))341 (dorun342 (map343 (fn [joint]344 (let [[obj-a obj-b]345 (joint-targets pieces joint)]346 (connect obj-a obj-b joint)))347 joints))348 pieces)350 (defn blender-creature [blender-path]351 (let [model (load-blender-model blender-path)352 joints353 (if-let [joint-node (.getChild model "joints")]354 (seq (.getChildren joint-node))355 (do (println-repl "could not find joints node")356 []))]357 (assemble-creature model joints)))359 (def hand "Models/creature1/one.blend")361 (def worm "Models/creature1/try-again.blend")363 (def touch "Models/creature1/touch.blend")365 (defn worm-model [] (load-blender-model worm))367 (defn x-ray [#^ColorRGBA color]368 (doto (Material. (asset-manager)369 "Common/MatDefs/Misc/Unshaded.j3md")370 (.setColor "Color" color)371 (-> (.getAdditionalRenderState)372 (.setDepthTest false))))374 (defn colorful []375 (.getChild (worm-model) "worm-21"))377 (import jme3tools.converters.ImageToAwt)379 (import ij.ImagePlus)381 ;; Every Mesh has many triangles, each with its own index.382 ;; Every vertex has its own index as well.384 (defn tactile-sensor-image385 "Return the touch-sensor distribution image in BufferedImage format,386 or nil if it does not exist."387 [#^Geometry obj]388 (if-let [image-path (meta-data obj "touch")]389 (ImageToAwt/convert390 (.getImage391 (.loadTexture392 (asset-manager)393 image-path))394 false false 0)))396 (import ij.process.ImageProcessor)397 (import java.awt.image.BufferedImage)399 (def white -1)401 (defn filter-pixels402 "List the coordinates of all pixels matching pred, within the bounds403 provided. Bounds -> [x0 y0 width height]"404 {:author "Dylan Holmes"}405 ([pred #^BufferedImage image]406 (filter-pixels pred image [0 0 (.getWidth image) (.getHeight image)]))407 ([pred #^BufferedImage image [x0 y0 width height]]408 ((fn accumulate [x y matches]409 (cond410 (>= y (+ height y0)) matches411 (>= x (+ width x0)) (recur 0 (inc y) matches)412 (pred (.getRGB image x y))413 (recur (inc x) y (conj matches [x y]))414 :else (recur (inc x) y matches)))415 x0 y0 [])))417 (defn white-coordinates418 "Coordinates of all the white pixels in a subset of the image."419 ([#^BufferedImage image bounds]420 (filter-pixels #(= % white) image bounds))421 ([#^BufferedImage image]422 (filter-pixels #(= % white) image)))424 (defn triangle425 "Get the triangle specified by triangle-index from the mesh within426 bounds."427 [#^Mesh mesh triangle-index]428 (let [scratch (Triangle.)]429 (.getTriangle mesh triangle-index scratch)430 scratch))432 (defn triangle-vertex-indices433 "Get the triangle vertex indices of a given triangle from a given434 mesh."435 [#^Mesh mesh triangle-index]436 (let [indices (int-array 3)]437 (.getTriangle mesh triangle-index indices)438 (vec indices)))440 (defn vertex-UV-coord441 "Get the uv-coordinates of the vertex named by vertex-index"442 [#^Mesh mesh vertex-index]443 (let [UV-buffer444 (.getData445 (.getBuffer446 mesh447 VertexBuffer$Type/TexCoord))]448 [(.get UV-buffer (* vertex-index 2))449 (.get UV-buffer (+ 1 (* vertex-index 2)))]))451 (defn triangle-UV-coord452 "Get the uv-cooridnates of the triangle's verticies."453 [#^Mesh mesh width height triangle-index]454 (map (fn [[u v]] (vector (* width u) (* height v)))455 (map (partial vertex-UV-coord mesh)456 (triangle-vertex-indices mesh triangle-index))))458 (defn same-side?459 "Given the points p1 and p2 and the reference point ref, is point p460 on the same side of the line that goes through p1 and p2 as ref is?"461 [p1 p2 ref p]462 (<=463 0464 (.dot465 (.cross (.subtract p2 p1) (.subtract p p1))466 (.cross (.subtract p2 p1) (.subtract ref p1)))))468 (defn triangle-seq [#^Triangle tri]469 [(.get1 tri) (.get2 tri) (.get3 tri)])471 (defn vector3f-seq [#^Vector3f v]472 [(.getX v) (.getY v) (.getZ v)])474 (defn inside-triangle?475 "Is the point inside the triangle?"476 {:author "Dylan Holmes"}477 [#^Triangle tri #^Vector3f p]478 (let [[vert-1 vert-2 vert-3] (triangle-seq tri)]479 (and480 (same-side? vert-1 vert-2 vert-3 p)481 (same-side? vert-2 vert-3 vert-1 p)482 (same-side? vert-3 vert-1 vert-2 p))))484 (defn triangle->matrix4f485 "Converts the triangle into a 4x4 matrix: The first three columns486 contain the vertices of the triangle; the last contains the unit487 normal of the triangle. The bottom row is filled with 1s."488 [#^Triangle t]489 (let [mat (Matrix4f.)490 [vert-1 vert-2 vert-3]491 ((comp vec map) #(.get t %) (range 3))492 unit-normal (do (.calculateNormal t)(.getNormal t))493 vertices [vert-1 vert-2 vert-3 unit-normal]]494 (dorun495 (for [row (range 4) col (range 3)]496 (do497 (.set mat col row (.get (vertices row)col))498 (.set mat 3 row 1))))499 mat))501 (defn triangle-transformation502 "Returns the affine transformation that converts each vertex in the503 first triangle into the corresponding vertex in the second504 triangle."505 [#^Triangle tri-1 #^Triangle tri-2]506 (.mult507 (triangle->matrix4f tri-2)508 (.invert (triangle->matrix4f tri-1))))510 (defn point->vector2f [[u v]]511 (Vector2f. u v))513 (defn vector2f->vector3f [v]514 (Vector3f. (.getX v) (.getY v) 0))516 (defn map-triangle [f #^Triangle tri]517 (Triangle.518 (f 0 (.get1 tri))519 (f 1 (.get2 tri))520 (f 2 (.get3 tri))))522 (defn points->triangle523 "Convert a list of points into a triangle."524 [points]525 (apply #(Triangle. %1 %2 %3)526 (map (fn [point]527 (let [point (vec point)]528 (Vector3f. (get point 0 0)529 (get point 1 0)530 (get point 2 0))))531 (take 3 points))))533 (defn convex-bounds534 "Dimensions of the smallest integer bounding square of the list of535 2D verticies in the form: [x y width height]."536 [uv-verts]537 (let [xs (map first uv-verts)538 ys (map second uv-verts)539 x0 (Math/floor (apply min xs))540 y0 (Math/floor (apply min ys))541 x1 (Math/ceil (apply max xs))542 y1 (Math/ceil (apply max ys))]543 [x0 y0 (- x1 x0) (- y1 y0)]))545 (defn sensors-in-triangle546 "Find the locations of the touch sensors within a triangle in both547 UV and gemoetry relative coordinates."548 [image mesh tri-index]549 (let [width (.getWidth image)550 height (.getHeight image)551 UV-vertex-coords (triangle-UV-coord mesh width height tri-index)552 bounds (convex-bounds UV-vertex-coords)554 cutout-triangle (points->triangle UV-vertex-coords)555 UV-sensor-coords556 (filter (comp (partial inside-triangle? cutout-triangle)557 (fn [[u v]] (Vector3f. u v 0)))558 (white-coordinates image bounds))559 UV->geometry (triangle-transformation560 cutout-triangle561 (triangle mesh tri-index))562 geometry-sensor-coords563 (map (fn [[u v]] (.mult UV->geometry (Vector3f. u v 0)))564 UV-sensor-coords)]565 {:UV UV-sensor-coords :geometry geometry-sensor-coords}))567 (defn-memo locate-feelers568 "Search the geometry's tactile UV image for touch sensors, returning569 their positions in geometry-relative coordinates."570 [#^Geometry geo]571 (let [mesh (.getMesh geo)572 num-triangles (.getTriangleCount mesh)]573 (if-let [image (tactile-sensor-image geo)]574 (map575 (partial sensors-in-triangle image mesh)576 (range num-triangles))577 (repeat (.getTriangleCount mesh) {:UV nil :geometry nil}))))579 (use 'clojure.contrib.def)581 (defn-memo touch-topology [#^Gemoetry geo]582 (vec (collapse (reduce concat (map :UV (locate-feelers geo))))))584 (defn-memo feeler-coordinates [#^Geometry geo]585 (vec (map :geometry (locate-feelers geo))))587 (defn enable-touch [#^Geometry geo]588 (let [feeler-coords (feeler-coordinates geo)589 tris (triangles geo)590 limit 0.1591 ;;results (CollisionResults.)592 ]593 (if (empty? (touch-topology geo))594 nil595 (fn [node]596 (let [sensor-origins597 (map598 #(map (partial local-to-world geo) %)599 feeler-coords)600 triangle-normals601 (map (partial get-ray-direction geo)602 tris)603 rays604 (flatten605 (map (fn [origins norm]606 (map #(doto (Ray. % norm)607 (.setLimit limit)) origins))608 sensor-origins triangle-normals))]609 (vector610 (touch-topology geo)611 (vec612 (for [ray rays]613 (do614 (let [results (CollisionResults.)]615 (.collideWith node ray results)616 (let [touch-objects617 (set618 (filter #(not (= geo %))619 (map #(.getGeometry %) results)))]620 (if (> (count touch-objects) 0)621 1 0))))))))))))623 (defn touch [#^Node pieces]624 (filter (comp not nil?)625 (map enable-touch626 (filter #(isa? (class %) Geometry)627 (node-seq pieces)))))630 ;; human eye transmits 62kb/s to brain Bandwidth is 8.75 Mb/s631 ;; http://en.wikipedia.org/wiki/Retina633 (defn test-eye []634 (.getChild (worm-model) "worm-11"))637 (defn retina-sensor-image638 "Return a map of pixel selection functions to BufferedImages639 describing the distribution of light-sensitive components on this640 geometry's surface. Each function creates an integer from the rgb641 values found in the pixel. :red, :green, :blue, :gray are already642 defined as extracting the red green blue and average components643 respectively."644 [#^Geometry eye]645 (if-let [eye-map (meta-data eye "eye")]646 (map-vals647 #(ImageToAwt/convert648 (.getImage (.loadTexture (asset-manager) %))649 false false 0)650 (read-string651 eye-map))))654 (defn enable-vision656 ;; need to create a camera based on uv image,657 ;; update this camera every frame based on the position of this658 ;; geometry. (maybe can get cam to follow the object)660 ;; use a stack for the continuation to grab the image.663 [#^Geometry eye]666 ;; Here's how vision will work.668 ;; Make the continuation in scene-processor take FrameBuffer,669 ;; byte-buffer, BufferedImage already sized to the correct670 ;; dimensions. the continuation will decide wether to "mix" them671 ;; into the BufferedImage, lazily ignore them, or mix them halfway672 ;; and call c/graphics card routines.674 ;; (vision creature) will take an optional :skip argument which will675 ;; inform the continuations in scene processor to skip the given676 ;; number of cycles; 0 means that no cycles will be skipped.678 ;; (vision creature) will return [init-functions sensor-functions].679 ;; The init-functions are each single-arg functions that take the680 ;; world and register the cameras and must each be called before the681 ;; corresponding sensor-functions. Each init-function returns the682 ;; viewport for that eye which can be manipulated, saved, etc. Each683 ;; sensor-function is a thunk and will return data in the same684 ;; format as the tactile-sensor functions; the structure is685 ;; [topology, sensor-data]. Internally, these sensor-functions686 ;; maintain a reference to sensor-data which is periodically updated687 ;; by the continuation function established by its init-function.688 ;; They can be queried every cycle, but their information may not689 ;; necessairly be different every cycle.691 ;; Each eye in the creature in blender will work the same way as692 ;; joints -- a one dimensional object with no geometry whose local693 ;; coordinate system determines the orientation of the resulting694 ;; eye. All eyes will have a parent named "eyes" just as all joints695 ;; have a parent named "joints". The resulting camera will be a696 ;; ChaseCamera or a CameraNode bound to the geo that is closest to697 ;; the eye marker. The eye marker will contain the metadata for the698 ;; eye, and will be moved by it's bound geometry. The dimensions of699 ;; the eye's camera are equal to the dimensions of the eye's "UV"700 ;; map.703 )705 (defn debug-window706 "creates function that offers a debug view of sensor data"707 []708 (let [vi (view-image)]709 (fn710 [[coords sensor-data]]711 (let [image (points->image coords)]712 (dorun713 (for [i (range (count coords))]714 (.setRGB image ((coords i) 0) ((coords i) 1)715 ({0 -16777216716 1 -1} (sensor-data i)))))717 (vi image)))))720 ;;(defn test-touch [world creature]723 (defn test-creature [thing]724 (let [x-axis725 (box 1 0.01 0.01 :physical? false :color ColorRGBA/Red)726 y-axis727 (box 0.01 1 0.01 :physical? false :color ColorRGBA/Green)728 z-axis729 (box 0.01 0.01 1 :physical? false :color ColorRGBA/Blue)730 creature (blender-creature thing)731 touch-nerves (touch creature)732 touch-debug-windows (map (fn [_] (debug-window)) touch-nerves)733 ]734 (world735 (nodify [creature736 (box 10 2 10 :position (Vector3f. 0 -9 0)737 :color ColorRGBA/Gray :mass 0)738 x-axis y-axis z-axis739 ])740 standard-debug-controls741 (fn [world]742 (light-up-everything world)743 (enable-debug world)744 ;;(com.aurellem.capture.Capture/captureVideo745 ;; world (file-str "/home/r/proj/ai-videos/hand"))746 ;;(.setTimer world (RatchetTimer. 60))747 ;;(speed-up world)748 ;;(set-gravity world (Vector3f. 0 0 0))749 )750 (fn [world tpf]751 ;;(dorun752 ;; (map #(%1 %2) touch-nerves (repeat (.getRootNode world))))754 (dorun755 (map #(%1 (%2 (.getRootNode world)))756 touch-debug-windows touch-nerves)757 )759 )760 ;;(let [timer (atom 0)]761 ;; (fn [_ _]762 ;; (swap! timer inc)763 ;; (if (= (rem @timer 60) 0)764 ;; (println-repl (float (/ @timer 60))))))765 )))775 ;;; experiments in collisions779 (defn collision-test []780 (let [b-radius 1781 b-position (Vector3f. 0 0 0)782 obj-b (box 1 1 1 :color ColorRGBA/Blue783 :position b-position784 :mass 0)785 node (nodify [obj-b])786 bounds-b787 (doto (Picture.)788 (.setHeight 50)789 (.setWidth 50)790 (.setImage (asset-manager)791 "Models/creature1/hand.png"792 false793 ))795 ;;(Ray. (Vector3f. 0 -5 0) (.normalize (Vector3f. 0 1 0)))797 collisions798 (let [cr (CollisionResults.)]799 (.collideWith node bounds-b cr)800 (println (map #(.getContactPoint %) cr))801 cr)803 ;;collision-points804 ;;(map #(sphere 0.1 :position (.getContactPoint %))805 ;; collisions)807 ;;node (nodify (conj collision-points obj-b))809 sim810 (world node811 {"key-space"812 (fn [_ value]813 (if value814 (let [cr (CollisionResults.)]815 (.collideWith node bounds-b cr)816 (println-repl (map #(.getContactPoint %) cr))817 cr)))}818 no-op819 no-op)821 ]822 sim824 ))829 #+end_src831 #+results: body-1832 : #'cortex.silly/test-creature835 * COMMENT purgatory836 #+begin_src clojure837 (defn bullet-trans []838 (let [obj-a (sphere 0.5 :color ColorRGBA/Red839 :position (Vector3f. -10 5 0))840 obj-b (sphere 0.5 :color ColorRGBA/Blue841 :position (Vector3f. -10 -5 0)842 :mass 0)843 control-a (.getControl obj-a RigidBodyControl)844 control-b (.getControl obj-b RigidBodyControl)845 swivel846 (.toRotationMatrix847 (doto (Quaternion.)848 (.fromAngleAxis (/ Math/PI 2)849 Vector3f/UNIT_X)))]850 (doto851 (ConeJoint.852 control-a control-b853 (Vector3f. 0 5 0)854 (Vector3f. 0 -5 0)855 swivel swivel)856 (.setLimit (* 0.6 (/ Math/PI 4))857 (/ Math/PI 4)858 (* Math/PI 0.8)))859 (world (nodify860 [obj-a obj-b])861 standard-debug-controls862 enable-debug863 no-op)))866 (defn bullet-trans* []867 (let [obj-a (box 1.5 0.5 0.5 :color ColorRGBA/Red868 :position (Vector3f. 5 0 0)869 :mass 90)870 obj-b (sphere 0.5 :color ColorRGBA/Blue871 :position (Vector3f. -5 0 0)872 :mass 0)873 control-a (.getControl obj-a RigidBodyControl)874 control-b (.getControl obj-b RigidBodyControl)875 move-up? (atom nil)876 move-down? (atom nil)877 move-left? (atom nil)878 move-right? (atom nil)879 roll-left? (atom nil)880 roll-right? (atom nil)881 force 100882 swivel883 (.toRotationMatrix884 (doto (Quaternion.)885 (.fromAngleAxis (/ Math/PI 2)886 Vector3f/UNIT_X)))887 x-move888 (doto (Matrix3f.)889 (.fromStartEndVectors Vector3f/UNIT_X890 (.normalize (Vector3f. 1 1 0))))892 timer (atom 0)]893 (doto894 (ConeJoint.895 control-a control-b896 (Vector3f. -8 0 0)897 (Vector3f. 2 0 0)898 ;;swivel swivel899 ;;Matrix3f/IDENTITY Matrix3f/IDENTITY900 x-move Matrix3f/IDENTITY901 )902 (.setCollisionBetweenLinkedBodys false)903 (.setLimit (* 1 (/ Math/PI 4)) ;; twist904 (* 1 (/ Math/PI 4)) ;; swing span in X-Y plane905 (* 0 (/ Math/PI 4)))) ;; swing span in Y-Z plane906 (world (nodify907 [obj-a obj-b])908 (merge standard-debug-controls909 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))910 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))911 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))912 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))913 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))914 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})916 (fn [world]917 (enable-debug world)918 (set-gravity world Vector3f/ZERO)919 )921 (fn [world _]923 (if @move-up?924 (.applyForce control-a925 (Vector3f. force 0 0)926 (Vector3f. 0 0 0)))927 (if @move-down?928 (.applyForce control-a929 (Vector3f. (- force) 0 0)930 (Vector3f. 0 0 0)))931 (if @move-left?932 (.applyForce control-a933 (Vector3f. 0 force 0)934 (Vector3f. 0 0 0)))935 (if @move-right?936 (.applyForce control-a937 (Vector3f. 0 (- force) 0)938 (Vector3f. 0 0 0)))940 (if @roll-left?941 (.applyForce control-a942 (Vector3f. 0 0 force)943 (Vector3f. 0 0 0)))944 (if @roll-right?945 (.applyForce control-a946 (Vector3f. 0 0 (- force))947 (Vector3f. 0 0 0)))949 (if (zero? (rem (swap! timer inc) 100))950 (.attachChild951 (.getRootNode world)952 (sphere 0.05 :color ColorRGBA/Yellow953 :physical? false :position954 (.getWorldTranslation obj-a)))))955 )956 ))958 (defn transform-trianglesdsd959 "Transform that converts each vertex in the first triangle960 into the corresponding vertex in the second triangle."961 [#^Triangle tri-1 #^Triangle tri-2]962 (let [in [(.get1 tri-1)963 (.get2 tri-1)964 (.get3 tri-1)]965 out [(.get1 tri-2)966 (.get2 tri-2)967 (.get3 tri-2)]]968 (let [translate (doto (Matrix4f.) (.setTranslation (.negate (in 0))))969 in* [(.mult translate (in 0))970 (.mult translate (in 1))971 (.mult translate (in 2))]972 final-translation973 (doto (Matrix4f.)974 (.setTranslation (out 1)))976 rotate-1977 (doto (Matrix3f.)978 (.fromStartEndVectors979 (.normalize980 (.subtract981 (in* 1) (in* 0)))982 (.normalize983 (.subtract984 (out 1) (out 0)))))985 in** [(.mult rotate-1 (in* 0))986 (.mult rotate-1 (in* 1))987 (.mult rotate-1 (in* 2))]988 scale-factor-1989 (.mult990 (.normalize991 (.subtract992 (out 1)993 (out 0)))994 (/ (.length995 (.subtract (out 1)996 (out 0)))997 (.length998 (.subtract (in** 1)999 (in** 0)))))1000 scale-1 (doto (Matrix4f.) (.setScale scale-factor-1))1001 in*** [(.mult scale-1 (in** 0))1002 (.mult scale-1 (in** 1))1003 (.mult scale-1 (in** 2))]1009 ]1011 (dorun (map println in))1012 (println)1013 (dorun (map println in*))1014 (println)1015 (dorun (map println in**))1016 (println)1017 (dorun (map println in***))1018 (println)1020 ))))1023 (defn world-setup [joint]1024 (let [joint-position (Vector3f. 0 0 0)1025 joint-rotation1026 (.toRotationMatrix1027 (.mult1028 (doto (Quaternion.)1029 (.fromAngleAxis1030 (* 1 (/ Math/PI 4))1031 (Vector3f. -1 0 0)))1032 (doto (Quaternion.)1033 (.fromAngleAxis1034 (* 1 (/ Math/PI 2))1035 (Vector3f. 0 0 1)))))1036 top-position (.mult joint-rotation (Vector3f. 8 0 0))1038 origin (doto1039 (sphere 0.1 :physical? false :color ColorRGBA/Cyan1040 :position top-position))1041 top (doto1042 (sphere 0.1 :physical? false :color ColorRGBA/Yellow1043 :position top-position)1045 (.addControl1046 (RigidBodyControl.1047 (CapsuleCollisionShape. 0.5 1.5 1) (float 20))))1048 bottom (doto1049 (sphere 0.1 :physical? false :color ColorRGBA/DarkGray1050 :position (Vector3f. 0 0 0))1051 (.addControl1052 (RigidBodyControl.1053 (CapsuleCollisionShape. 0.5 1.5 1) (float 0))))1054 table (box 10 2 10 :position (Vector3f. 0 -20 0)1055 :color ColorRGBA/Gray :mass 0)1056 a (.getControl top RigidBodyControl)1057 b (.getControl bottom RigidBodyControl)]1059 (cond1060 (= joint :cone)1062 (doto (ConeJoint.1063 a b1064 (world-to-local top joint-position)1065 (world-to-local bottom joint-position)1066 joint-rotation1067 joint-rotation1068 )1071 (.setLimit (* (/ 10) Math/PI)1072 (* (/ 4) Math/PI)1073 0)))1074 [origin top bottom table]))1076 (defn test-joint [joint]1077 (let [[origin top bottom floor] (world-setup joint)1078 control (.getControl top RigidBodyControl)1079 move-up? (atom false)1080 move-down? (atom false)1081 move-left? (atom false)1082 move-right? (atom false)1083 roll-left? (atom false)1084 roll-right? (atom false)1085 timer (atom 0)]1087 (world1088 (nodify [top bottom floor origin])1089 (merge standard-debug-controls1090 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))1091 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))1092 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))1093 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))1094 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))1095 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})1097 (fn [world]1098 (light-up-everything world)1099 (enable-debug world)1100 (set-gravity world (Vector3f. 0 0 0))1101 )1103 (fn [world _]1104 (if (zero? (rem (swap! timer inc) 100))1105 (do1106 ;; (println-repl @timer)1107 (.attachChild (.getRootNode world)1108 (sphere 0.05 :color ColorRGBA/Yellow1109 :position (.getWorldTranslation top)1110 :physical? false))1111 (.attachChild (.getRootNode world)1112 (sphere 0.05 :color ColorRGBA/LightGray1113 :position (.getWorldTranslation bottom)1114 :physical? false))))1116 (if @move-up?1117 (.applyTorque control1118 (.mult (.getPhysicsRotation control)1119 (Vector3f. 0 0 10))))1120 (if @move-down?1121 (.applyTorque control1122 (.mult (.getPhysicsRotation control)1123 (Vector3f. 0 0 -10))))1124 (if @move-left?1125 (.applyTorque control1126 (.mult (.getPhysicsRotation control)1127 (Vector3f. 0 10 0))))1128 (if @move-right?1129 (.applyTorque control1130 (.mult (.getPhysicsRotation control)1131 (Vector3f. 0 -10 0))))1132 (if @roll-left?1133 (.applyTorque control1134 (.mult (.getPhysicsRotation control)1135 (Vector3f. -1 0 0))))1136 (if @roll-right?1137 (.applyTorque control1138 (.mult (.getPhysicsRotation control)1139 (Vector3f. 1 0 0))))))))1143 (defprotocol Frame1144 (frame [this]))1146 (extend-type BufferedImage1147 Frame1148 (frame [image]1149 (merge1150 (apply1151 hash-map1152 (interleave1153 (doall (for [x (range (.getWidth image)) y (range (.getHeight image))]1154 (vector x y)))1155 (doall (for [x (range (.getWidth image)) y (range (.getHeight image))]1156 (let [data (.getRGB image x y)]1157 (hash-map :r (bit-shift-right (bit-and 0xff0000 data) 16)1158 :g (bit-shift-right (bit-and 0x00ff00 data) 8)1159 :b (bit-and 0x0000ff data)))))))1160 {:width (.getWidth image) :height (.getHeight image)})))1163 (extend-type ImagePlus1164 Frame1165 (frame [image+]1166 (frame (.getBufferedImage image+))))1169 #+end_src1172 * COMMENT generate source1173 #+begin_src clojure :tangle ../src/cortex/silly.clj1174 <<body-1>>1175 #+end_src