annotate org/test-creature.org @ 155:95bf55614211

moved goals and deleted old test
author Robert McIntyre <rlm@mit.edu>
date Fri, 03 Feb 2012 06:04:30 -0700
parents bb235258f835
children e8df6e76c3e5
rev   line source
rlm@73 1 #+title: First attempt at a creature!
rlm@73 2 #+author: Robert McIntyre
rlm@73 3 #+email: rlm@mit.edu
rlm@73 4 #+description:
rlm@73 5 #+keywords: simulation, jMonkeyEngine3, clojure
rlm@73 6 #+SETUPFILE: ../../aurellem/org/setup.org
rlm@73 7 #+INCLUDE: ../../aurellem/org/level-0.org
rlm@73 8
rlm@129 9
rlm@129 10
rlm@99 11
rlm@73 12 * Intro
rlm@73 13 So far, I've made the following senses --
rlm@73 14 - Vision
rlm@73 15 - Hearing
rlm@73 16 - Touch
rlm@73 17 - Proprioception
rlm@73 18
rlm@73 19 And one effector:
rlm@73 20 - Movement
rlm@73 21
rlm@73 22 However, the code so far has only enabled these senses, but has not
rlm@73 23 actually implemented them. For example, there is still a lot of work
rlm@73 24 to be done for vision. I need to be able to create an /eyeball/ in
rlm@73 25 simulation that can be moved around and see the world from different
rlm@73 26 angles. I also need to determine weather to use log-polar or cartesian
rlm@73 27 for the visual input, and I need to determine how/wether to
rlm@73 28 disceritise the visual input.
rlm@73 29
rlm@73 30 I also want to be able to visualize both the sensors and the
rlm@104 31 effectors in pretty pictures. This semi-retarted creature will be my
rlm@73 32 first attempt at bringing everything together.
rlm@73 33
rlm@73 34 * The creature's body
rlm@73 35
rlm@73 36 Still going to do an eve-like body in blender, but due to problems
rlm@104 37 importing the joints, etc into jMonkeyEngine3, I'm going to do all
rlm@73 38 the connecting here in clojure code, using the names of the individual
rlm@73 39 components and trial and error. Later, I'll maybe make some sort of
rlm@73 40 creature-building modifications to blender that support whatever
rlm@73 41 discreitized senses I'm going to make.
rlm@73 42
rlm@73 43 #+name: body-1
rlm@73 44 #+begin_src clojure
rlm@73 45 (ns cortex.silly
rlm@73 46 "let's play!"
rlm@73 47 {:author "Robert McIntyre"})
rlm@73 48
rlm@73 49 ;; TODO remove this!
rlm@73 50 (require 'cortex.import)
rlm@73 51 (cortex.import/mega-import-jme3)
rlm@151 52 (use '(cortex world util body hearing touch vision sense))
rlm@73 53
rlm@73 54 (rlm.rlm-commands/help)
rlm@99 55 (import java.awt.image.BufferedImage)
rlm@99 56 (import javax.swing.JPanel)
rlm@99 57 (import javax.swing.SwingUtilities)
rlm@99 58 (import java.awt.Dimension)
rlm@99 59 (import javax.swing.JFrame)
rlm@99 60 (import java.awt.Dimension)
rlm@106 61 (import com.aurellem.capture.RatchetTimer)
rlm@99 62 (declare joint-create)
rlm@108 63 (use 'clojure.contrib.def)
rlm@73 64
rlm@73 65 (defn load-blender-model
rlm@73 66 "Load a .blend file using an asset folder relative path."
rlm@73 67 [^String model]
rlm@73 68 (.loadModel
rlm@73 69 (doto (asset-manager)
rlm@73 70 (.registerLoader BlenderModelLoader (into-array String ["blend"])))
rlm@73 71 model))
rlm@73 72
rlm@78 73 (defn blender-to-jme
rlm@78 74 "Convert from Blender coordinates to JME coordinates"
rlm@78 75 [#^Vector3f in]
rlm@78 76 (Vector3f. (.getX in)
rlm@78 77 (.getZ in)
rlm@78 78 (- (.getY in))))
rlm@74 79
rlm@87 80 (defn world-to-local
rlm@87 81 "Convert the world coordinates into coordinates relative to the
rlm@87 82 object (i.e. local coordinates), taking into account the rotation
rlm@87 83 of object."
rlm@87 84 [#^Spatial object world-coordinate]
rlm@153 85 (.worldToLocal object world-coordinate nil))
rlm@87 86
rlm@96 87 (defn local-to-world
rlm@96 88 "Convert the local coordinates into coordinates into world relative
rlm@96 89 coordinates"
rlm@96 90 [#^Spatial object local-coordinate]
rlm@153 91 (.localToWorld object local-coordinate nil))
rlm@96 92
rlm@87 93 (defmulti joint-dispatch
rlm@87 94 "Translate blender pseudo-joints into real JME joints."
rlm@88 95 (fn [constraints & _]
rlm@87 96 (:type constraints)))
rlm@87 97
rlm@87 98 (defmethod joint-dispatch :point
rlm@87 99 [constraints control-a control-b pivot-a pivot-b rotation]
rlm@87 100 (println-repl "creating POINT2POINT joint")
rlm@130 101 ;; bullet's point2point joints are BROKEN, so we must use the
rlm@130 102 ;; generic 6DOF joint instead of an actual Point2Point joint!
rlm@130 103
rlm@130 104 ;; should be able to do this:
rlm@130 105 (comment
rlm@130 106 (Point2PointJoint.
rlm@130 107 control-a
rlm@130 108 control-b
rlm@130 109 pivot-a
rlm@130 110 pivot-b))
rlm@130 111
rlm@130 112 ;; but instead we must do this:
rlm@130 113 (println-repl "substuting 6DOF joint for POINT2POINT joint!")
rlm@130 114 (doto
rlm@130 115 (SixDofJoint.
rlm@130 116 control-a
rlm@130 117 control-b
rlm@130 118 pivot-a
rlm@130 119 pivot-b
rlm@130 120 false)
rlm@130 121 (.setLinearLowerLimit Vector3f/ZERO)
rlm@130 122 (.setLinearUpperLimit Vector3f/ZERO)
rlm@130 123 ;;(.setAngularLowerLimit (Vector3f. 1 1 1))
rlm@130 124 ;;(.setAngularUpperLimit (Vector3f. 0 0 0))
rlm@130 125
rlm@130 126 ))
rlm@130 127
rlm@87 128
rlm@87 129 (defmethod joint-dispatch :hinge
rlm@87 130 [constraints control-a control-b pivot-a pivot-b rotation]
rlm@87 131 (println-repl "creating HINGE joint")
rlm@87 132 (let [axis
rlm@87 133 (if-let
rlm@87 134 [axis (:axis constraints)]
rlm@87 135 axis
rlm@87 136 Vector3f/UNIT_X)
rlm@87 137 [limit-1 limit-2] (:limit constraints)
rlm@87 138 hinge-axis
rlm@87 139 (.mult
rlm@87 140 rotation
rlm@87 141 (blender-to-jme axis))]
rlm@87 142 (doto
rlm@87 143 (HingeJoint.
rlm@87 144 control-a
rlm@87 145 control-b
rlm@87 146 pivot-a
rlm@87 147 pivot-b
rlm@87 148 hinge-axis
rlm@87 149 hinge-axis)
rlm@87 150 (.setLimit limit-1 limit-2))))
rlm@87 151
rlm@87 152 (defmethod joint-dispatch :cone
rlm@87 153 [constraints control-a control-b pivot-a pivot-b rotation]
rlm@87 154 (let [limit-xz (:limit-xz constraints)
rlm@87 155 limit-xy (:limit-xy constraints)
rlm@87 156 twist (:twist constraints)]
rlm@87 157
rlm@87 158 (println-repl "creating CONE joint")
rlm@87 159 (println-repl rotation)
rlm@87 160 (println-repl
rlm@87 161 "UNIT_X --> " (.mult rotation (Vector3f. 1 0 0)))
rlm@87 162 (println-repl
rlm@87 163 "UNIT_Y --> " (.mult rotation (Vector3f. 0 1 0)))
rlm@87 164 (println-repl
rlm@87 165 "UNIT_Z --> " (.mult rotation (Vector3f. 0 0 1)))
rlm@87 166 (doto
rlm@87 167 (ConeJoint.
rlm@87 168 control-a
rlm@87 169 control-b
rlm@87 170 pivot-a
rlm@87 171 pivot-b
rlm@87 172 rotation
rlm@87 173 rotation)
rlm@87 174 (.setLimit (float limit-xz)
rlm@87 175 (float limit-xy)
rlm@87 176 (float twist)))))
rlm@87 177
rlm@88 178 (defn connect
rlm@87 179 "here are some examples:
rlm@87 180 {:type :point}
rlm@87 181 {:type :hinge :limit [0 (/ Math/PI 2)] :axis (Vector3f. 0 1 0)}
rlm@87 182 (:axis defaults to (Vector3f. 1 0 0) if not provided for hinge joints)
rlm@87 183
rlm@89 184 {:type :cone :limit-xz 0]
rlm@89 185 :limit-xy 0]
rlm@89 186 :twist 0]} (use XZY rotation mode in blender!)"
rlm@87 187 [#^Node obj-a #^Node obj-b #^Node joint]
rlm@87 188 (let [control-a (.getControl obj-a RigidBodyControl)
rlm@87 189 control-b (.getControl obj-b RigidBodyControl)
rlm@87 190 joint-center (.getWorldTranslation joint)
rlm@87 191 joint-rotation (.toRotationMatrix (.getWorldRotation joint))
rlm@87 192 pivot-a (world-to-local obj-a joint-center)
rlm@87 193 pivot-b (world-to-local obj-b joint-center)]
rlm@89 194
rlm@87 195 (if-let [constraints
rlm@87 196 (map-vals
rlm@87 197 eval
rlm@87 198 (read-string
rlm@87 199 (meta-data joint "joint")))]
rlm@89 200 ;; A side-effect of creating a joint registers
rlm@89 201 ;; it with both physics objects which in turn
rlm@89 202 ;; will register the joint with the physics system
rlm@89 203 ;; when the simulation is started.
rlm@87 204 (do
rlm@87 205 (println-repl "creating joint between"
rlm@87 206 (.getName obj-a) "and" (.getName obj-b))
rlm@87 207 (joint-dispatch constraints
rlm@87 208 control-a control-b
rlm@87 209 pivot-a pivot-b
rlm@87 210 joint-rotation))
rlm@87 211 (println-repl "could not find joint meta-data!"))))
rlm@87 212
rlm@130 213
rlm@130 214
rlm@130 215
rlm@78 216 (defn assemble-creature [#^Node pieces joints]
rlm@78 217 (dorun
rlm@78 218 (map
rlm@78 219 (fn [geom]
rlm@78 220 (let [physics-control
rlm@78 221 (RigidBodyControl.
rlm@78 222 (HullCollisionShape.
rlm@78 223 (.getMesh geom))
rlm@78 224 (if-let [mass (meta-data geom "mass")]
rlm@78 225 (do
rlm@78 226 (println-repl
rlm@78 227 "setting" (.getName geom) "mass to" (float mass))
rlm@78 228 (float mass))
rlm@78 229 (float 1)))]
rlm@78 230
rlm@78 231 (.addControl geom physics-control)))
rlm@78 232 (filter #(isa? (class %) Geometry )
rlm@78 233 (node-seq pieces))))
rlm@78 234 (dorun
rlm@78 235 (map
rlm@78 236 (fn [joint]
rlm@133 237 (let [[obj-a obj-b] (joint-targets pieces joint)]
rlm@88 238 (connect obj-a obj-b joint)))
rlm@78 239 joints))
rlm@78 240 pieces)
rlm@74 241
rlm@116 242 (declare blender-creature)
rlm@74 243
rlm@78 244 (def hand "Models/creature1/one.blend")
rlm@74 245
rlm@78 246 (def worm "Models/creature1/try-again.blend")
rlm@78 247
rlm@90 248 (def touch "Models/creature1/touch.blend")
rlm@90 249
rlm@90 250 (defn worm-model [] (load-blender-model worm))
rlm@90 251
rlm@80 252 (defn x-ray [#^ColorRGBA color]
rlm@80 253 (doto (Material. (asset-manager)
rlm@80 254 "Common/MatDefs/Misc/Unshaded.j3md")
rlm@80 255 (.setColor "Color" color)
rlm@80 256 (-> (.getAdditionalRenderState)
rlm@80 257 (.setDepthTest false))))
rlm@80 258
rlm@91 259 (defn colorful []
rlm@91 260 (.getChild (worm-model) "worm-21"))
rlm@90 261
rlm@90 262 (import jme3tools.converters.ImageToAwt)
rlm@90 263
rlm@90 264 (import ij.ImagePlus)
rlm@90 265
rlm@108 266 ;; Every Mesh has many triangles, each with its own index.
rlm@108 267 ;; Every vertex has its own index as well.
rlm@90 268
rlm@108 269 (defn tactile-sensor-image
rlm@110 270 "Return the touch-sensor distribution image in BufferedImage format,
rlm@110 271 or nil if it does not exist."
rlm@91 272 [#^Geometry obj]
rlm@110 273 (if-let [image-path (meta-data obj "touch")]
rlm@110 274 (ImageToAwt/convert
rlm@110 275 (.getImage
rlm@110 276 (.loadTexture
rlm@110 277 (asset-manager)
rlm@110 278 image-path))
rlm@110 279 false false 0)))
rlm@110 280
rlm@91 281
rlm@108 282
rlm@108 283 (defn triangle
rlm@112 284 "Get the triangle specified by triangle-index from the mesh within
rlm@112 285 bounds."
rlm@108 286 [#^Mesh mesh triangle-index]
rlm@108 287 (let [scratch (Triangle.)]
rlm@108 288 (.getTriangle mesh triangle-index scratch)
rlm@108 289 scratch))
rlm@108 290
rlm@108 291 (defn triangle-vertex-indices
rlm@108 292 "Get the triangle vertex indices of a given triangle from a given
rlm@108 293 mesh."
rlm@108 294 [#^Mesh mesh triangle-index]
rlm@108 295 (let [indices (int-array 3)]
rlm@108 296 (.getTriangle mesh triangle-index indices)
rlm@108 297 (vec indices)))
rlm@108 298
rlm@108 299 (defn vertex-UV-coord
rlm@108 300 "Get the uv-coordinates of the vertex named by vertex-index"
rlm@108 301 [#^Mesh mesh vertex-index]
rlm@108 302 (let [UV-buffer
rlm@108 303 (.getData
rlm@108 304 (.getBuffer
rlm@108 305 mesh
rlm@108 306 VertexBuffer$Type/TexCoord))]
rlm@108 307 [(.get UV-buffer (* vertex-index 2))
rlm@108 308 (.get UV-buffer (+ 1 (* vertex-index 2)))]))
rlm@108 309
rlm@108 310 (defn triangle-UV-coord
rlm@108 311 "Get the uv-cooridnates of the triangle's verticies."
rlm@108 312 [#^Mesh mesh width height triangle-index]
rlm@108 313 (map (fn [[u v]] (vector (* width u) (* height v)))
rlm@108 314 (map (partial vertex-UV-coord mesh)
rlm@108 315 (triangle-vertex-indices mesh triangle-index))))
rlm@91 316
rlm@102 317 (defn same-side?
rlm@102 318 "Given the points p1 and p2 and the reference point ref, is point p
rlm@102 319 on the same side of the line that goes through p1 and p2 as ref is?"
rlm@102 320 [p1 p2 ref p]
rlm@91 321 (<=
rlm@91 322 0
rlm@91 323 (.dot
rlm@91 324 (.cross (.subtract p2 p1) (.subtract p p1))
rlm@91 325 (.cross (.subtract p2 p1) (.subtract ref p1)))))
rlm@91 326
rlm@108 327 (defn triangle-seq [#^Triangle tri]
rlm@108 328 [(.get1 tri) (.get2 tri) (.get3 tri)])
rlm@108 329
rlm@108 330 (defn vector3f-seq [#^Vector3f v]
rlm@108 331 [(.getX v) (.getY v) (.getZ v)])
rlm@108 332
rlm@108 333 (defn inside-triangle?
rlm@108 334 "Is the point inside the triangle?"
rlm@108 335 {:author "Dylan Holmes"}
rlm@108 336 [#^Triangle tri #^Vector3f p]
rlm@108 337 (let [[vert-1 vert-2 vert-3] (triangle-seq tri)]
rlm@108 338 (and
rlm@108 339 (same-side? vert-1 vert-2 vert-3 p)
rlm@108 340 (same-side? vert-2 vert-3 vert-1 p)
rlm@108 341 (same-side? vert-3 vert-1 vert-2 p))))
rlm@108 342
rlm@94 343 (defn triangle->matrix4f
rlm@108 344 "Converts the triangle into a 4x4 matrix: The first three columns
rlm@108 345 contain the vertices of the triangle; the last contains the unit
rlm@108 346 normal of the triangle. The bottom row is filled with 1s."
rlm@94 347 [#^Triangle t]
rlm@94 348 (let [mat (Matrix4f.)
rlm@94 349 [vert-1 vert-2 vert-3]
rlm@94 350 ((comp vec map) #(.get t %) (range 3))
rlm@94 351 unit-normal (do (.calculateNormal t)(.getNormal t))
rlm@94 352 vertices [vert-1 vert-2 vert-3 unit-normal]]
rlm@94 353 (dorun
rlm@94 354 (for [row (range 4) col (range 3)]
rlm@94 355 (do
rlm@94 356 (.set mat col row (.get (vertices row)col))
rlm@94 357 (.set mat 3 row 1))))
rlm@94 358 mat))
rlm@94 359
rlm@94 360 (defn triangle-transformation
rlm@94 361 "Returns the affine transformation that converts each vertex in the
rlm@94 362 first triangle into the corresponding vertex in the second
rlm@94 363 triangle."
rlm@94 364 [#^Triangle tri-1 #^Triangle tri-2]
rlm@94 365 (.mult
rlm@94 366 (triangle->matrix4f tri-2)
rlm@94 367 (.invert (triangle->matrix4f tri-1))))
rlm@94 368
rlm@108 369 (defn point->vector2f [[u v]]
rlm@108 370 (Vector2f. u v))
rlm@94 371
rlm@94 372 (defn vector2f->vector3f [v]
rlm@94 373 (Vector3f. (.getX v) (.getY v) 0))
rlm@94 374
rlm@94 375 (defn map-triangle [f #^Triangle tri]
rlm@94 376 (Triangle.
rlm@94 377 (f 0 (.get1 tri))
rlm@94 378 (f 1 (.get2 tri))
rlm@94 379 (f 2 (.get3 tri))))
rlm@94 380
rlm@108 381 (defn points->triangle
rlm@108 382 "Convert a list of points into a triangle."
rlm@108 383 [points]
rlm@108 384 (apply #(Triangle. %1 %2 %3)
rlm@108 385 (map (fn [point]
rlm@108 386 (let [point (vec point)]
rlm@108 387 (Vector3f. (get point 0 0)
rlm@108 388 (get point 1 0)
rlm@108 389 (get point 2 0))))
rlm@108 390 (take 3 points))))
rlm@94 391
rlm@108 392 (defn convex-bounds
rlm@128 393 ;;dylan
rlm@128 394 "Returns the smallest square containing the given
rlm@128 395 vertices, as a vector of integers [left top width height]."
rlm@128 396 ;; "Dimensions of the smallest integer bounding square of the list of
rlm@128 397 ;; 2D verticies in the form: [x y width height]."
rlm@108 398 [uv-verts]
rlm@108 399 (let [xs (map first uv-verts)
rlm@108 400 ys (map second uv-verts)
rlm@108 401 x0 (Math/floor (apply min xs))
rlm@108 402 y0 (Math/floor (apply min ys))
rlm@108 403 x1 (Math/ceil (apply max xs))
rlm@108 404 y1 (Math/ceil (apply max ys))]
rlm@108 405 [x0 y0 (- x1 x0) (- y1 y0)]))
rlm@93 406
rlm@106 407 (defn sensors-in-triangle
rlm@128 408 ;;dylan
rlm@128 409 "Locate the touch sensors in the triangle, returning a map of their UV and geometry-relative coordinates."
rlm@128 410 ;;"Find the locations of the touch sensors within a triangle in both
rlm@128 411 ;; UV and gemoetry relative coordinates."
rlm@107 412 [image mesh tri-index]
rlm@107 413 (let [width (.getWidth image)
rlm@108 414 height (.getHeight image)
rlm@108 415 UV-vertex-coords (triangle-UV-coord mesh width height tri-index)
rlm@108 416 bounds (convex-bounds UV-vertex-coords)
rlm@108 417
rlm@108 418 cutout-triangle (points->triangle UV-vertex-coords)
rlm@108 419 UV-sensor-coords
rlm@108 420 (filter (comp (partial inside-triangle? cutout-triangle)
rlm@108 421 (fn [[u v]] (Vector3f. u v 0)))
rlm@108 422 (white-coordinates image bounds))
rlm@108 423 UV->geometry (triangle-transformation
rlm@108 424 cutout-triangle
rlm@108 425 (triangle mesh tri-index))
rlm@108 426 geometry-sensor-coords
rlm@108 427 (map (fn [[u v]] (.mult UV->geometry (Vector3f. u v 0)))
rlm@108 428 UV-sensor-coords)]
rlm@108 429 {:UV UV-sensor-coords :geometry geometry-sensor-coords}))
rlm@107 430
rlm@108 431 (defn-memo locate-feelers
rlm@94 432 "Search the geometry's tactile UV image for touch sensors, returning
rlm@94 433 their positions in geometry-relative coordinates."
rlm@94 434 [#^Geometry geo]
rlm@108 435 (let [mesh (.getMesh geo)
rlm@108 436 num-triangles (.getTriangleCount mesh)]
rlm@108 437 (if-let [image (tactile-sensor-image geo)]
rlm@108 438 (map
rlm@108 439 (partial sensors-in-triangle image mesh)
rlm@108 440 (range num-triangles))
rlm@108 441 (repeat (.getTriangleCount mesh) {:UV nil :geometry nil}))))
rlm@102 442
rlm@102 443 (use 'clojure.contrib.def)
rlm@102 444
rlm@102 445 (defn-memo touch-topology [#^Gemoetry geo]
rlm@108 446 (vec (collapse (reduce concat (map :UV (locate-feelers geo))))))
rlm@108 447
rlm@108 448 (defn-memo feeler-coordinates [#^Geometry geo]
rlm@108 449 (vec (map :geometry (locate-feelers geo))))
rlm@102 450
rlm@97 451 (defn enable-touch [#^Geometry geo]
rlm@108 452 (let [feeler-coords (feeler-coordinates geo)
rlm@96 453 tris (triangles geo)
rlm@109 454 limit 0.1
rlm@109 455 ;;results (CollisionResults.)
rlm@109 456 ]
rlm@111 457 (if (empty? (touch-topology geo))
rlm@111 458 nil
rlm@111 459 (fn [node]
rlm@111 460 (let [sensor-origins
rlm@111 461 (map
rlm@111 462 #(map (partial local-to-world geo) %)
rlm@111 463 feeler-coords)
rlm@111 464 triangle-normals
rlm@111 465 (map (partial get-ray-direction geo)
rlm@111 466 tris)
rlm@111 467 rays
rlm@111 468 (flatten
rlm@111 469 (map (fn [origins norm]
rlm@111 470 (map #(doto (Ray. % norm)
rlm@97 471 (.setLimit limit)) origins))
rlm@111 472 sensor-origins triangle-normals))]
rlm@111 473 (vector
rlm@111 474 (touch-topology geo)
rlm@111 475 (vec
rlm@111 476 (for [ray rays]
rlm@111 477 (do
rlm@111 478 (let [results (CollisionResults.)]
rlm@111 479 (.collideWith node ray results)
rlm@111 480 (let [touch-objects
rlm@126 481 (filter #(not (= geo (.getGeometry %)))
rlm@126 482 results)]
rlm@126 483 (- 255
rlm@126 484 (if (empty? touch-objects) 255
rlm@126 485 (rem
rlm@126 486 (int
rlm@126 487 (* 255 (/ (.getDistance
rlm@126 488 (first touch-objects)) limit)))
rlm@126 489 256))))))))))))))
rlm@126 490
rlm@111 491
rlm@111 492 (defn touch [#^Node pieces]
rlm@111 493 (filter (comp not nil?)
rlm@111 494 (map enable-touch
rlm@111 495 (filter #(isa? (class %) Geometry)
rlm@111 496 (node-seq pieces)))))
rlm@94 497
rlm@109 498
rlm@111 499 (defn test-eye []
rlm@117 500 (.getChild
rlm@117 501 (.getChild (worm-model) "eyes")
rlm@117 502 "eye"))
rlm@111 503
rlm@111 504
rlm@123 505
rlm@123 506 ;; Ears work the same way as vision.
rlm@123 507
rlm@123 508 ;; (hearing creature) will return [init-functions
rlm@123 509 ;; sensor-functions]. The init functions each take the world and
rlm@123 510 ;; register a SoundProcessor that does foureier transforms on the
rlm@123 511 ;; incommong sound data, making it available to each sensor function.
rlm@123 512
rlm@123 513 (defn creature-ears
rlm@128 514 "Return the children of the creature's \"ears\" node."
rlm@128 515 ;;dylan
rlm@128 516 ;;"The ear nodes which are children of the \"ears\" node in the
rlm@128 517 ;;creature."
rlm@123 518 [#^Node creature]
rlm@123 519 (if-let [ear-node (.getChild creature "ears")]
rlm@123 520 (seq (.getChildren ear-node))
rlm@123 521 (do (println-repl "could not find ears node") [])))
rlm@123 522
rlm@116 523
rlm@128 524 ;;dylan (defn follow-sense, adjoin-sense, attach-stimuli,
rlm@128 525 ;;anchor-qualia, augment-organ, with-organ
rlm@117 526
rlm@117 527
rlm@123 528 (defn update-listener-velocity
rlm@123 529 "Update the listener's velocity every update loop."
rlm@123 530 [#^Spatial obj #^Listener lis]
rlm@123 531 (let [old-position (atom (.getLocation lis))]
rlm@123 532 (.addControl
rlm@123 533 obj
rlm@123 534 (proxy [AbstractControl] []
rlm@123 535 (controlUpdate [tpf]
rlm@123 536 (let [new-position (.getLocation lis)]
rlm@123 537 (.setVelocity
rlm@123 538 lis
rlm@123 539 (.mult (.subtract new-position @old-position)
rlm@123 540 (float (/ tpf))))
rlm@123 541 (reset! old-position new-position)))
rlm@123 542 (controlRender [_ _])))))
rlm@123 543
rlm@123 544 (import com.aurellem.capture.audio.AudioSendRenderer)
rlm@123 545
rlm@123 546 (defn attach-ear
rlm@123 547 [#^Application world #^Node creature #^Spatial ear continuation]
rlm@123 548 (let [target (closest-node creature ear)
rlm@123 549 lis (Listener.)
rlm@123 550 audio-renderer (.getAudioRenderer world)
rlm@123 551 sp (sound-processor continuation)]
rlm@123 552 (.setLocation lis (.getWorldTranslation ear))
rlm@123 553 (.setRotation lis (.getWorldRotation ear))
rlm@123 554 (bind-sense target lis)
rlm@123 555 (update-listener-velocity target lis)
rlm@123 556 (.addListener audio-renderer lis)
rlm@123 557 (.registerSoundProcessor audio-renderer lis sp)))
rlm@123 558
rlm@123 559 (defn enable-hearing
rlm@123 560 [#^Node creature #^Spatial ear]
rlm@123 561 (let [hearing-data (atom [])]
rlm@123 562 [(fn [world]
rlm@123 563 (attach-ear world creature ear
rlm@123 564 (fn [data]
rlm@123 565 (reset! hearing-data (vec data)))))
rlm@123 566 [(fn []
rlm@123 567 (let [data @hearing-data
rlm@123 568 topology
rlm@123 569 (vec (map #(vector % 0) (range 0 (count data))))
rlm@123 570 scaled-data
rlm@123 571 (vec
rlm@123 572 (map
rlm@123 573 #(rem (int (* 255 (/ (+ 1 %) 2))) 256)
rlm@123 574 data))]
rlm@123 575 [topology scaled-data]))
rlm@123 576 ]]))
rlm@123 577
rlm@123 578 (defn hearing
rlm@123 579 [#^Node creature]
rlm@123 580 (reduce
rlm@123 581 (fn [[init-a senses-a]
rlm@123 582 [init-b senses-b]]
rlm@123 583 [(conj init-a init-b)
rlm@123 584 (into senses-a senses-b)])
rlm@123 585 [[][]]
rlm@123 586 (for [ear (creature-ears creature)]
rlm@123 587 (enable-hearing creature ear))))
rlm@123 588
rlm@128 589
rlm@128 590
rlm@128 591
rlm@128 592
rlm@128 593
rlm@128 594 ;; lower level --- nodes
rlm@128 595 ;; closest-node "parse/compile-x" -> makes organ, which is spatial, fn pair
rlm@128 596
rlm@128 597 ;; higher level -- organs
rlm@128 598 ;;
rlm@128 599
rlm@128 600 ;; higher level --- sense/effector
rlm@128 601 ;; these are the functions that provide world i/o, chinese-room style
rlm@128 602
rlm@128 603
rlm@134 604
rlm@116 605
rlm@116 606 (defn blender-creature
rlm@116 607 "Return a creature with all joints in place."
rlm@116 608 [blender-path]
rlm@116 609 (let [model (load-blender-model blender-path)
rlm@134 610 joints (creature-joints model)]
rlm@134 611 (assemble-creature model joints)))
rlm@116 612
rlm@126 613 (defn gray-scale [num]
rlm@126 614 (+ num
rlm@126 615 (bit-shift-left num 8)
rlm@126 616 (bit-shift-left num 16)))
rlm@126 617
rlm@130 618 (defn debug-touch-window
rlm@103 619 "creates function that offers a debug view of sensor data"
rlm@103 620 []
rlm@103 621 (let [vi (view-image)]
rlm@103 622 (fn
rlm@103 623 [[coords sensor-data]]
rlm@103 624 (let [image (points->image coords)]
rlm@103 625 (dorun
rlm@103 626 (for [i (range (count coords))]
rlm@103 627 (.setRGB image ((coords i) 0) ((coords i) 1)
rlm@126 628 (gray-scale (sensor-data i)))))
rlm@126 629
rlm@126 630
rlm@103 631 (vi image)))))
rlm@103 632
rlm@118 633 (defn debug-vision-window
rlm@118 634 "creates function that offers a debug view of sensor data"
rlm@118 635 []
rlm@118 636 (let [vi (view-image)]
rlm@118 637 (fn
rlm@118 638 [[coords sensor-data]]
rlm@118 639 (let [image (points->image coords)]
rlm@118 640 (dorun
rlm@118 641 (for [i (range (count coords))]
rlm@118 642 (.setRGB image ((coords i) 0) ((coords i) 1)
rlm@118 643 (sensor-data i))))
rlm@118 644 (vi image)))))
rlm@118 645
rlm@123 646 (defn debug-hearing-window
rlm@123 647 "view audio data"
rlm@123 648 [height]
rlm@123 649 (let [vi (view-image)]
rlm@123 650 (fn [[coords sensor-data]]
rlm@123 651 (let [image (BufferedImage. (count coords) height
rlm@123 652 BufferedImage/TYPE_INT_RGB)]
rlm@123 653 (dorun
rlm@123 654 (for [x (range (count coords))]
rlm@123 655 (dorun
rlm@123 656 (for [y (range height)]
rlm@123 657 (let [raw-sensor (sensor-data x)]
rlm@126 658 (.setRGB image x y (gray-scale raw-sensor)))))))
rlm@126 659
rlm@123 660 (vi image)))))
rlm@123 661
rlm@123 662
rlm@123 663
rlm@106 664 ;;(defn test-touch [world creature]
rlm@83 665
rlm@78 666
rlm@123 667
rlm@123 668
rlm@130 669 ;; here's how motor-control/ proprioception will work: Each muscle is
rlm@130 670 ;; defined by a 1-D array of numbers (the "motor pool") each of which
rlm@130 671 ;; represent muscle fibers. A muscle also has a scalar :strength
rlm@130 672 ;; factor which determines how strong the muscle as a whole is.
rlm@130 673 ;; The effector function for a muscle takes a number < (count
rlm@130 674 ;; motor-pool) and that number is said to "activate" all the muscle
rlm@130 675 ;; fibers whose index is lower than the number. Each fiber will apply
rlm@130 676 ;; force in proportion to its value in the array. Lower values cause
rlm@130 677 ;; less force. The lower values can be put at the "beginning" of the
rlm@130 678 ;; 1-D array to simulate the layout of actual human muscles, which are
rlm@130 679 ;; capable of more percise movements when exerting less force.
rlm@129 680
rlm@130 681 ;; I don't know how to encode proprioception, so for now, just return
rlm@130 682 ;; a function for each joint that returns a triplet of floats which
rlm@130 683 ;; represent relative roll, pitch, and yaw. Write display code for
rlm@130 684 ;; this though.
rlm@130 685
rlm@147 686 (defn muscle-fiber-values
rlm@147 687 "get motor pool strengths"
rlm@130 688 [#^BufferedImage image]
rlm@147 689 (vec
rlm@147 690 (let [width (.getWidth image)]
rlm@147 691 (for [x (range width)]
rlm@147 692 (- 255
rlm@147 693 (bit-and
rlm@147 694 0x0000FF
rlm@147 695 (.getRGB image x 0)))))))
rlm@147 696
rlm@147 697
rlm@147 698 (defn creature-muscles
rlm@147 699 "Return the children of the creature's \"muscles\" node."
rlm@147 700 [#^Node creature]
rlm@147 701 (if-let [muscle-node (.getChild creature "muscles")]
rlm@147 702 (seq (.getChildren muscle-node))
rlm@147 703 (do (println-repl "could not find muscles node") [])))
rlm@147 704
rlm@147 705 (defn single-muscle [#^Node parts #^Node muscle]
rlm@147 706 (let [target (closest-node parts muscle)
rlm@147 707 axis
rlm@147 708 (.mult (.getWorldRotation muscle) Vector3f/UNIT_Y)
rlm@147 709 strength (meta-data muscle "strength")
rlm@147 710 image-name (read-string (meta-data muscle "muscle"))
rlm@147 711 image
rlm@147 712 (ImageToAwt/convert
rlm@147 713 (.getImage (.loadTexture (asset-manager) image-name))
rlm@147 714 false false 0)
rlm@147 715 fibers (muscle-fiber-values image)
rlm@147 716 fiber-integral (reductions + fibers)
rlm@147 717 force-index (vec
rlm@147 718 (map
rlm@147 719 #(float (* strength (/ % (last
rlm@147 720 fiber-integral))))
rlm@147 721 fiber-integral))
rlm@147 722 control (.getControl target RigidBodyControl)]
rlm@147 723 (fn [n]
rlm@147 724 (let [pool-index (min n (count fibers))]
rlm@148 725 (.applyTorque control (.mult axis (force-index n)))))))
rlm@147 726
rlm@147 727
rlm@147 728 (defn enable-muscles
rlm@147 729 "Must be called on a creature after RigidBodyControls have been
rlm@147 730 created."
rlm@147 731 [#^Node creature]
rlm@147 732 (let [muscles (creature-muscles creature)]
rlm@147 733 (for [muscle muscles]
rlm@147 734 (single-muscle creature muscle))))
rlm@130 735
rlm@106 736 (defn test-creature [thing]
rlm@106 737 (let [x-axis
rlm@106 738 (box 1 0.01 0.01 :physical? false :color ColorRGBA/Red)
rlm@106 739 y-axis
rlm@106 740 (box 0.01 1 0.01 :physical? false :color ColorRGBA/Green)
rlm@106 741 z-axis
rlm@106 742 (box 0.01 0.01 1 :physical? false :color ColorRGBA/Blue)
rlm@106 743 creature (blender-creature thing)
rlm@106 744 touch-nerves (touch creature)
rlm@130 745 touch-debug-windows (map (fn [_] (debug-touch-window)) touch-nerves)
rlm@121 746 [init-vision-fns vision-data] (vision creature)
rlm@121 747 vision-debug (map (fn [_] (debug-vision-window)) vision-data)
rlm@118 748 me (sphere 0.5 :color ColorRGBA/Blue :physical? false)
rlm@123 749 [init-hearing-fns hearing-senses] (hearing creature)
rlm@123 750 hearing-windows (map (fn [_] (debug-hearing-window 50))
rlm@123 751 hearing-senses)
rlm@124 752 bell (AudioNode. (asset-manager)
rlm@128 753 "Sounds/pure.wav" false)
rlm@130 754 prop (proprioception creature)
rlm@135 755 prop-debug (proprioception-debug-window)
rlm@148 756
rlm@148 757 muscle-fns (enable-muscles creature)
rlm@123 758 ;; dream
rlm@123 759
rlm@106 760 ]
rlm@143 761
rlm@143 762
rlm@143 763 (apply
rlm@143 764 world
rlm@143 765 (with-movement
rlm@143 766 (.getChild creature "worm-21")
rlm@143 767 ["key-r" "key-t"
rlm@143 768 "key-f" "key-g"
rlm@143 769 "key-v" "key-b"]
rlm@143 770 [10 10 10 10 1 1]
rlm@143 771 [(nodify [creature
rlm@143 772 (box 10 2 10 :position (Vector3f. 0 -9 0)
rlm@143 773 :color ColorRGBA/Gray :mass 0)
rlm@143 774 x-axis y-axis z-axis
rlm@143 775 me
rlm@143 776 ])
rlm@143 777 (merge standard-debug-controls
rlm@143 778 {"key-return"
rlm@143 779 (fn [_ value]
rlm@143 780 (if value
rlm@143 781 (do
rlm@143 782 (println-repl "play-sound")
rlm@148 783 (.play bell))))
rlm@148 784 "key-h"
rlm@148 785 (fn [_ value]
rlm@148 786 (if value
rlm@148 787 (do
rlm@148 788 (println-repl "muscle activating!")
rlm@148 789 ((first muscle-fns) 199))))
rlm@148 790
rlm@148 791 })
rlm@143 792 (fn [world]
rlm@143 793 (light-up-everything world)
rlm@143 794 (enable-debug world)
rlm@143 795 (dorun (map #(% world) init-vision-fns))
rlm@143 796 (dorun (map #(% world) init-hearing-fns))
rlm@143 797
rlm@143 798 (add-eye world
rlm@143 799 (attach-eye creature (test-eye))
rlm@143 800 (comp (view-image) BufferedImage!))
rlm@143 801
rlm@143 802 (add-eye world (.getCamera world) no-op)
rlm@145 803 ;;(set-gravity world (Vector3f. 0 0 0))
rlm@143 804 ;;(com.aurellem.capture.Capture/captureVideo
rlm@143 805 ;; world (file-str "/home/r/proj/ai-videos/hand"))
rlm@143 806 ;;(.setTimer world (RatchetTimer. 60))
rlm@143 807 (speed-up world)
rlm@148 808 (set-gravity world (Vector3f. 0 0 0))
rlm@143 809 )
rlm@143 810 (fn [world tpf]
rlm@143 811 ;;(dorun
rlm@143 812 ;; (map #(%1 %2) touch-nerves (repeat (.getRootNode world))))
rlm@143 813
rlm@143 814 (prop-debug (prop))
rlm@143 815
rlm@143 816 (dorun
rlm@143 817 (map #(%1 (%2 (.getRootNode world)))
rlm@143 818 touch-debug-windows touch-nerves))
rlm@143 819
rlm@143 820 (dorun
rlm@143 821 (map #(%1 (%2))
rlm@143 822 vision-debug vision-data))
rlm@143 823 (dorun
rlm@143 824 (map #(%1 (%2)) hearing-windows hearing-senses))
rlm@143 825
rlm@143 826
rlm@143 827 ;;(println-repl (vision-data))
rlm@143 828 (.setLocalTranslation me (.getLocation (.getCamera world)))
rlm@143 829
rlm@143 830
rlm@143 831 )]
rlm@106 832 ;;(let [timer (atom 0)]
rlm@106 833 ;; (fn [_ _]
rlm@106 834 ;; (swap! timer inc)
rlm@106 835 ;; (if (= (rem @timer 60) 0)
rlm@106 836 ;; (println-repl (float (/ @timer 60))))))
rlm@143 837 ))))
rlm@83 838
rlm@109 839
rlm@116 840
rlm@116 841 ;; the camera will stay in its initial position/rotation with relation
rlm@116 842 ;; to the spatial.
rlm@116 843
rlm@116 844
rlm@117 845 (defn follow-test
rlm@117 846 "show a camera that stays in the same relative position to a blue cube."
rlm@117 847 []
rlm@116 848 (let [camera-pos (Vector3f. 0 30 0)
rlm@116 849 rock (box 1 1 1 :color ColorRGBA/Blue
rlm@116 850 :position (Vector3f. 0 10 0)
rlm@116 851 :mass 30
rlm@116 852 )
rlm@118 853 rot (.getWorldRotation rock)
rlm@116 854
rlm@116 855 table (box 3 1 10 :color ColorRGBA/Gray :mass 0
rlm@116 856 :position (Vector3f. 0 -3 0))]
rlm@116 857
rlm@116 858 (world
rlm@116 859 (nodify [rock table])
rlm@116 860 standard-debug-controls
rlm@116 861 (fn [world]
rlm@116 862 (let
rlm@116 863 [cam (doto (.clone (.getCamera world))
rlm@116 864 (.setLocation camera-pos)
rlm@116 865 (.lookAt Vector3f/ZERO
rlm@116 866 Vector3f/UNIT_X))]
rlm@123 867 (bind-sense rock cam)
rlm@116 868
rlm@116 869 (.setTimer world (RatchetTimer. 60))
rlm@116 870 (add-eye world cam (comp (view-image) BufferedImage!))
rlm@116 871 (add-eye world (.getCamera world) no-op))
rlm@116 872 )
rlm@118 873 (fn [_ _] (println-repl rot)))))
rlm@116 874
rlm@118 875
rlm@123 876
rlm@87 877 #+end_src
rlm@83 878
rlm@87 879 #+results: body-1
rlm@133 880 : #'cortex.silly/follow-test
rlm@78 881
rlm@78 882
rlm@78 883 * COMMENT purgatory
rlm@78 884 #+begin_src clojure
rlm@74 885
rlm@77 886 (defn bullet-trans* []
rlm@77 887 (let [obj-a (box 1.5 0.5 0.5 :color ColorRGBA/Red
rlm@77 888 :position (Vector3f. 5 0 0)
rlm@77 889 :mass 90)
rlm@77 890 obj-b (sphere 0.5 :color ColorRGBA/Blue
rlm@77 891 :position (Vector3f. -5 0 0)
rlm@77 892 :mass 0)
rlm@77 893 control-a (.getControl obj-a RigidBodyControl)
rlm@77 894 control-b (.getControl obj-b RigidBodyControl)
rlm@77 895 move-up? (atom nil)
rlm@77 896 move-down? (atom nil)
rlm@77 897 move-left? (atom nil)
rlm@77 898 move-right? (atom nil)
rlm@77 899 roll-left? (atom nil)
rlm@77 900 roll-right? (atom nil)
rlm@77 901 force 100
rlm@77 902 swivel
rlm@77 903 (.toRotationMatrix
rlm@77 904 (doto (Quaternion.)
rlm@77 905 (.fromAngleAxis (/ Math/PI 2)
rlm@77 906 Vector3f/UNIT_X)))
rlm@77 907 x-move
rlm@77 908 (doto (Matrix3f.)
rlm@77 909 (.fromStartEndVectors Vector3f/UNIT_X
rlm@77 910 (.normalize (Vector3f. 1 1 0))))
rlm@77 911
rlm@77 912 timer (atom 0)]
rlm@77 913 (doto
rlm@77 914 (ConeJoint.
rlm@77 915 control-a control-b
rlm@77 916 (Vector3f. -8 0 0)
rlm@77 917 (Vector3f. 2 0 0)
rlm@77 918 ;;swivel swivel
rlm@77 919 ;;Matrix3f/IDENTITY Matrix3f/IDENTITY
rlm@77 920 x-move Matrix3f/IDENTITY
rlm@77 921 )
rlm@77 922 (.setCollisionBetweenLinkedBodys false)
rlm@77 923 (.setLimit (* 1 (/ Math/PI 4)) ;; twist
rlm@77 924 (* 1 (/ Math/PI 4)) ;; swing span in X-Y plane
rlm@77 925 (* 0 (/ Math/PI 4)))) ;; swing span in Y-Z plane
rlm@77 926 (world (nodify
rlm@77 927 [obj-a obj-b])
rlm@77 928 (merge standard-debug-controls
rlm@77 929 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
rlm@77 930 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
rlm@77 931 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
rlm@77 932 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
rlm@77 933 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
rlm@77 934 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
rlm@77 935
rlm@77 936 (fn [world]
rlm@77 937 (enable-debug world)
rlm@77 938 (set-gravity world Vector3f/ZERO)
rlm@77 939 )
rlm@77 940
rlm@77 941 (fn [world _]
rlm@77 942
rlm@77 943 (if @move-up?
rlm@77 944 (.applyForce control-a
rlm@77 945 (Vector3f. force 0 0)
rlm@77 946 (Vector3f. 0 0 0)))
rlm@77 947 (if @move-down?
rlm@77 948 (.applyForce control-a
rlm@77 949 (Vector3f. (- force) 0 0)
rlm@77 950 (Vector3f. 0 0 0)))
rlm@77 951 (if @move-left?
rlm@77 952 (.applyForce control-a
rlm@77 953 (Vector3f. 0 force 0)
rlm@77 954 (Vector3f. 0 0 0)))
rlm@77 955 (if @move-right?
rlm@77 956 (.applyForce control-a
rlm@77 957 (Vector3f. 0 (- force) 0)
rlm@77 958 (Vector3f. 0 0 0)))
rlm@77 959
rlm@77 960 (if @roll-left?
rlm@77 961 (.applyForce control-a
rlm@77 962 (Vector3f. 0 0 force)
rlm@77 963 (Vector3f. 0 0 0)))
rlm@77 964 (if @roll-right?
rlm@77 965 (.applyForce control-a
rlm@77 966 (Vector3f. 0 0 (- force))
rlm@77 967 (Vector3f. 0 0 0)))
rlm@77 968
rlm@77 969 (if (zero? (rem (swap! timer inc) 100))
rlm@77 970 (.attachChild
rlm@77 971 (.getRootNode world)
rlm@77 972 (sphere 0.05 :color ColorRGBA/Yellow
rlm@77 973 :physical? false :position
rlm@77 974 (.getWorldTranslation obj-a)))))
rlm@77 975 )
rlm@77 976 ))
rlm@77 977
rlm@106 978 (defn test-joint [joint]
rlm@106 979 (let [[origin top bottom floor] (world-setup joint)
rlm@106 980 control (.getControl top RigidBodyControl)
rlm@106 981 move-up? (atom false)
rlm@106 982 move-down? (atom false)
rlm@106 983 move-left? (atom false)
rlm@106 984 move-right? (atom false)
rlm@106 985 roll-left? (atom false)
rlm@106 986 roll-right? (atom false)
rlm@106 987 timer (atom 0)]
rlm@106 988
rlm@106 989 (world
rlm@106 990 (nodify [top bottom floor origin])
rlm@106 991 (merge standard-debug-controls
rlm@106 992 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
rlm@106 993 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
rlm@106 994 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
rlm@106 995 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
rlm@106 996 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
rlm@106 997 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
rlm@106 998
rlm@106 999 (fn [world]
rlm@106 1000 (light-up-everything world)
rlm@106 1001 (enable-debug world)
rlm@106 1002 (set-gravity world (Vector3f. 0 0 0))
rlm@106 1003 )
rlm@106 1004
rlm@106 1005 (fn [world _]
rlm@106 1006 (if (zero? (rem (swap! timer inc) 100))
rlm@106 1007 (do
rlm@106 1008 ;; (println-repl @timer)
rlm@106 1009 (.attachChild (.getRootNode world)
rlm@106 1010 (sphere 0.05 :color ColorRGBA/Yellow
rlm@106 1011 :position (.getWorldTranslation top)
rlm@106 1012 :physical? false))
rlm@106 1013 (.attachChild (.getRootNode world)
rlm@106 1014 (sphere 0.05 :color ColorRGBA/LightGray
rlm@106 1015 :position (.getWorldTranslation bottom)
rlm@106 1016 :physical? false))))
rlm@106 1017
rlm@106 1018 (if @move-up?
rlm@106 1019 (.applyTorque control
rlm@106 1020 (.mult (.getPhysicsRotation control)
rlm@106 1021 (Vector3f. 0 0 10))))
rlm@106 1022 (if @move-down?
rlm@106 1023 (.applyTorque control
rlm@106 1024 (.mult (.getPhysicsRotation control)
rlm@106 1025 (Vector3f. 0 0 -10))))
rlm@106 1026 (if @move-left?
rlm@106 1027 (.applyTorque control
rlm@106 1028 (.mult (.getPhysicsRotation control)
rlm@106 1029 (Vector3f. 0 10 0))))
rlm@106 1030 (if @move-right?
rlm@106 1031 (.applyTorque control
rlm@106 1032 (.mult (.getPhysicsRotation control)
rlm@106 1033 (Vector3f. 0 -10 0))))
rlm@106 1034 (if @roll-left?
rlm@106 1035 (.applyTorque control
rlm@106 1036 (.mult (.getPhysicsRotation control)
rlm@106 1037 (Vector3f. -1 0 0))))
rlm@106 1038 (if @roll-right?
rlm@106 1039 (.applyTorque control
rlm@106 1040 (.mult (.getPhysicsRotation control)
rlm@106 1041 (Vector3f. 1 0 0))))))))
rlm@99 1042 #+end_src
rlm@99 1043
rlm@99 1044
rlm@99 1045 * COMMENT generate source
rlm@99 1046 #+begin_src clojure :tangle ../src/cortex/silly.clj
rlm@99 1047 <<body-1>>
rlm@99 1048 #+end_src
rlm@99 1049
rlm@99 1050
rlm@94 1051
rlm@94 1052