Mercurial > cortex
comparison org/test-creature.org @ 156:e8df6e76c3e5
refactored touch
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Fri, 03 Feb 2012 06:15:34 -0700 |
parents | 95bf55614211 |
children | 84c67be00abe |
comparison
equal
deleted
inserted
replaced
155:95bf55614211 | 156:e8df6e76c3e5 |
---|---|
75 [#^Vector3f in] | 75 [#^Vector3f in] |
76 (Vector3f. (.getX in) | 76 (Vector3f. (.getX in) |
77 (.getZ in) | 77 (.getZ in) |
78 (- (.getY in)))) | 78 (- (.getY in)))) |
79 | 79 |
80 (defn world-to-local | |
81 "Convert the world coordinates into coordinates relative to the | |
82 object (i.e. local coordinates), taking into account the rotation | |
83 of object." | |
84 [#^Spatial object world-coordinate] | |
85 (.worldToLocal object world-coordinate nil)) | |
86 | |
87 (defn local-to-world | |
88 "Convert the local coordinates into coordinates into world relative | |
89 coordinates" | |
90 [#^Spatial object local-coordinate] | |
91 (.localToWorld object local-coordinate nil)) | |
92 | 80 |
93 (defmulti joint-dispatch | 81 (defmulti joint-dispatch |
94 "Translate blender pseudo-joints into real JME joints." | 82 "Translate blender pseudo-joints into real JME joints." |
95 (fn [constraints & _] | 83 (fn [constraints & _] |
96 (:type constraints))) | 84 (:type constraints))) |
243 | 231 |
244 (def hand "Models/creature1/one.blend") | 232 (def hand "Models/creature1/one.blend") |
245 | 233 |
246 (def worm "Models/creature1/try-again.blend") | 234 (def worm "Models/creature1/try-again.blend") |
247 | 235 |
248 (def touch "Models/creature1/touch.blend") | |
249 | |
250 (defn worm-model [] (load-blender-model worm)) | 236 (defn worm-model [] (load-blender-model worm)) |
251 | 237 |
252 (defn x-ray [#^ColorRGBA color] | 238 (defn x-ray [#^ColorRGBA color] |
253 (doto (Material. (asset-manager) | 239 (doto (Material. (asset-manager) |
254 "Common/MatDefs/Misc/Unshaded.j3md") | 240 "Common/MatDefs/Misc/Unshaded.j3md") |
261 | 247 |
262 (import jme3tools.converters.ImageToAwt) | 248 (import jme3tools.converters.ImageToAwt) |
263 | 249 |
264 (import ij.ImagePlus) | 250 (import ij.ImagePlus) |
265 | 251 |
266 ;; Every Mesh has many triangles, each with its own index. | |
267 ;; Every vertex has its own index as well. | |
268 | |
269 (defn tactile-sensor-image | |
270 "Return the touch-sensor distribution image in BufferedImage format, | |
271 or nil if it does not exist." | |
272 [#^Geometry obj] | |
273 (if-let [image-path (meta-data obj "touch")] | |
274 (ImageToAwt/convert | |
275 (.getImage | |
276 (.loadTexture | |
277 (asset-manager) | |
278 image-path)) | |
279 false false 0))) | |
280 | |
281 | |
282 | |
283 (defn triangle | |
284 "Get the triangle specified by triangle-index from the mesh within | |
285 bounds." | |
286 [#^Mesh mesh triangle-index] | |
287 (let [scratch (Triangle.)] | |
288 (.getTriangle mesh triangle-index scratch) | |
289 scratch)) | |
290 | |
291 (defn triangle-vertex-indices | |
292 "Get the triangle vertex indices of a given triangle from a given | |
293 mesh." | |
294 [#^Mesh mesh triangle-index] | |
295 (let [indices (int-array 3)] | |
296 (.getTriangle mesh triangle-index indices) | |
297 (vec indices))) | |
298 | |
299 (defn vertex-UV-coord | |
300 "Get the uv-coordinates of the vertex named by vertex-index" | |
301 [#^Mesh mesh vertex-index] | |
302 (let [UV-buffer | |
303 (.getData | |
304 (.getBuffer | |
305 mesh | |
306 VertexBuffer$Type/TexCoord))] | |
307 [(.get UV-buffer (* vertex-index 2)) | |
308 (.get UV-buffer (+ 1 (* vertex-index 2)))])) | |
309 | |
310 (defn triangle-UV-coord | |
311 "Get the uv-cooridnates of the triangle's verticies." | |
312 [#^Mesh mesh width height triangle-index] | |
313 (map (fn [[u v]] (vector (* width u) (* height v))) | |
314 (map (partial vertex-UV-coord mesh) | |
315 (triangle-vertex-indices mesh triangle-index)))) | |
316 | |
317 (defn same-side? | |
318 "Given the points p1 and p2 and the reference point ref, is point p | |
319 on the same side of the line that goes through p1 and p2 as ref is?" | |
320 [p1 p2 ref p] | |
321 (<= | |
322 0 | |
323 (.dot | |
324 (.cross (.subtract p2 p1) (.subtract p p1)) | |
325 (.cross (.subtract p2 p1) (.subtract ref p1))))) | |
326 | |
327 (defn triangle-seq [#^Triangle tri] | |
328 [(.get1 tri) (.get2 tri) (.get3 tri)]) | |
329 | |
330 (defn vector3f-seq [#^Vector3f v] | |
331 [(.getX v) (.getY v) (.getZ v)]) | |
332 | |
333 (defn inside-triangle? | |
334 "Is the point inside the triangle?" | |
335 {:author "Dylan Holmes"} | |
336 [#^Triangle tri #^Vector3f p] | |
337 (let [[vert-1 vert-2 vert-3] (triangle-seq tri)] | |
338 (and | |
339 (same-side? vert-1 vert-2 vert-3 p) | |
340 (same-side? vert-2 vert-3 vert-1 p) | |
341 (same-side? vert-3 vert-1 vert-2 p)))) | |
342 | |
343 (defn triangle->matrix4f | |
344 "Converts the triangle into a 4x4 matrix: The first three columns | |
345 contain the vertices of the triangle; the last contains the unit | |
346 normal of the triangle. The bottom row is filled with 1s." | |
347 [#^Triangle t] | |
348 (let [mat (Matrix4f.) | |
349 [vert-1 vert-2 vert-3] | |
350 ((comp vec map) #(.get t %) (range 3)) | |
351 unit-normal (do (.calculateNormal t)(.getNormal t)) | |
352 vertices [vert-1 vert-2 vert-3 unit-normal]] | |
353 (dorun | |
354 (for [row (range 4) col (range 3)] | |
355 (do | |
356 (.set mat col row (.get (vertices row)col)) | |
357 (.set mat 3 row 1)))) | |
358 mat)) | |
359 | |
360 (defn triangle-transformation | |
361 "Returns the affine transformation that converts each vertex in the | |
362 first triangle into the corresponding vertex in the second | |
363 triangle." | |
364 [#^Triangle tri-1 #^Triangle tri-2] | |
365 (.mult | |
366 (triangle->matrix4f tri-2) | |
367 (.invert (triangle->matrix4f tri-1)))) | |
368 | |
369 (defn point->vector2f [[u v]] | |
370 (Vector2f. u v)) | |
371 | |
372 (defn vector2f->vector3f [v] | |
373 (Vector3f. (.getX v) (.getY v) 0)) | |
374 | |
375 (defn map-triangle [f #^Triangle tri] | |
376 (Triangle. | |
377 (f 0 (.get1 tri)) | |
378 (f 1 (.get2 tri)) | |
379 (f 2 (.get3 tri)))) | |
380 | |
381 (defn points->triangle | |
382 "Convert a list of points into a triangle." | |
383 [points] | |
384 (apply #(Triangle. %1 %2 %3) | |
385 (map (fn [point] | |
386 (let [point (vec point)] | |
387 (Vector3f. (get point 0 0) | |
388 (get point 1 0) | |
389 (get point 2 0)))) | |
390 (take 3 points)))) | |
391 | |
392 (defn convex-bounds | |
393 ;;dylan | |
394 "Returns the smallest square containing the given | |
395 vertices, as a vector of integers [left top width height]." | |
396 ;; "Dimensions of the smallest integer bounding square of the list of | |
397 ;; 2D verticies in the form: [x y width height]." | |
398 [uv-verts] | |
399 (let [xs (map first uv-verts) | |
400 ys (map second uv-verts) | |
401 x0 (Math/floor (apply min xs)) | |
402 y0 (Math/floor (apply min ys)) | |
403 x1 (Math/ceil (apply max xs)) | |
404 y1 (Math/ceil (apply max ys))] | |
405 [x0 y0 (- x1 x0) (- y1 y0)])) | |
406 | |
407 (defn sensors-in-triangle | |
408 ;;dylan | |
409 "Locate the touch sensors in the triangle, returning a map of their UV and geometry-relative coordinates." | |
410 ;;"Find the locations of the touch sensors within a triangle in both | |
411 ;; UV and gemoetry relative coordinates." | |
412 [image mesh tri-index] | |
413 (let [width (.getWidth image) | |
414 height (.getHeight image) | |
415 UV-vertex-coords (triangle-UV-coord mesh width height tri-index) | |
416 bounds (convex-bounds UV-vertex-coords) | |
417 | |
418 cutout-triangle (points->triangle UV-vertex-coords) | |
419 UV-sensor-coords | |
420 (filter (comp (partial inside-triangle? cutout-triangle) | |
421 (fn [[u v]] (Vector3f. u v 0))) | |
422 (white-coordinates image bounds)) | |
423 UV->geometry (triangle-transformation | |
424 cutout-triangle | |
425 (triangle mesh tri-index)) | |
426 geometry-sensor-coords | |
427 (map (fn [[u v]] (.mult UV->geometry (Vector3f. u v 0))) | |
428 UV-sensor-coords)] | |
429 {:UV UV-sensor-coords :geometry geometry-sensor-coords})) | |
430 | |
431 (defn-memo locate-feelers | |
432 "Search the geometry's tactile UV image for touch sensors, returning | |
433 their positions in geometry-relative coordinates." | |
434 [#^Geometry geo] | |
435 (let [mesh (.getMesh geo) | |
436 num-triangles (.getTriangleCount mesh)] | |
437 (if-let [image (tactile-sensor-image geo)] | |
438 (map | |
439 (partial sensors-in-triangle image mesh) | |
440 (range num-triangles)) | |
441 (repeat (.getTriangleCount mesh) {:UV nil :geometry nil})))) | |
442 | |
443 (use 'clojure.contrib.def) | |
444 | |
445 (defn-memo touch-topology [#^Gemoetry geo] | |
446 (vec (collapse (reduce concat (map :UV (locate-feelers geo)))))) | |
447 | |
448 (defn-memo feeler-coordinates [#^Geometry geo] | |
449 (vec (map :geometry (locate-feelers geo)))) | |
450 | |
451 (defn enable-touch [#^Geometry geo] | |
452 (let [feeler-coords (feeler-coordinates geo) | |
453 tris (triangles geo) | |
454 limit 0.1 | |
455 ;;results (CollisionResults.) | |
456 ] | |
457 (if (empty? (touch-topology geo)) | |
458 nil | |
459 (fn [node] | |
460 (let [sensor-origins | |
461 (map | |
462 #(map (partial local-to-world geo) %) | |
463 feeler-coords) | |
464 triangle-normals | |
465 (map (partial get-ray-direction geo) | |
466 tris) | |
467 rays | |
468 (flatten | |
469 (map (fn [origins norm] | |
470 (map #(doto (Ray. % norm) | |
471 (.setLimit limit)) origins)) | |
472 sensor-origins triangle-normals))] | |
473 (vector | |
474 (touch-topology geo) | |
475 (vec | |
476 (for [ray rays] | |
477 (do | |
478 (let [results (CollisionResults.)] | |
479 (.collideWith node ray results) | |
480 (let [touch-objects | |
481 (filter #(not (= geo (.getGeometry %))) | |
482 results)] | |
483 (- 255 | |
484 (if (empty? touch-objects) 255 | |
485 (rem | |
486 (int | |
487 (* 255 (/ (.getDistance | |
488 (first touch-objects)) limit))) | |
489 256)))))))))))))) | |
490 | |
491 | |
492 (defn touch [#^Node pieces] | |
493 (filter (comp not nil?) | |
494 (map enable-touch | |
495 (filter #(isa? (class %) Geometry) | |
496 (node-seq pieces))))) | |
497 | 252 |
498 | 253 |
499 (defn test-eye [] | 254 (defn test-eye [] |
500 (.getChild | 255 (.getChild |
501 (.getChild (worm-model) "eyes") | 256 (.getChild (worm-model) "eyes") |