comparison org/test-creature.org @ 108:92b857b6145d

slow implementation of UV-mapped touch is complete
author Robert McIntyre <rlm@mit.edu>
date Sun, 15 Jan 2012 04:08:31 -0700
parents 53fb379ac678
children c05d8d222166
comparison
equal deleted inserted replaced
107:53fb379ac678 108:92b857b6145d
63 (import java.awt.Dimension) 63 (import java.awt.Dimension)
64 (import javax.swing.JFrame) 64 (import javax.swing.JFrame)
65 (import java.awt.Dimension) 65 (import java.awt.Dimension)
66 (import com.aurellem.capture.RatchetTimer) 66 (import com.aurellem.capture.RatchetTimer)
67 (declare joint-create) 67 (declare joint-create)
68 (use 'clojure.contrib.def)
68 69
69 (defn view-image 70 (defn view-image
70 "Initailizes a JPanel on which you may draw a BufferedImage. 71 "Initailizes a JPanel on which you may draw a BufferedImage.
71 Returns a function that accepts a BufferedImage and draws it to the 72 Returns a function that accepts a BufferedImage and draws it to the
72 JPanel." 73 JPanel."
140 141
141 (defn collapse 142 (defn collapse
142 "Take a set of pairs of integers and collapse them into a 143 "Take a set of pairs of integers and collapse them into a
143 contigous bitmap." 144 contigous bitmap."
144 [points] 145 [points]
145 (let 146 (if (empty? points) []
146 [num-points (count points) 147 (let
147 center (vector 148 [num-points (count points)
148 (int (average (map first points))) 149 center (vector
149 (int (average (map first points)))) 150 (int (average (map first points)))
150 flattened 151 (int (average (map first points))))
151 (reduce 152 flattened
152 concat 153 (reduce
153 (map 154 concat
154 (fn [column] 155 (map
155 (map vector 156 (fn [column]
156 (map first column) 157 (map vector
157 (collapse-1d (second center) 158 (map first column)
158 (map second column)))) 159 (collapse-1d (second center)
159 (partition-by first (sort-by first points)))) 160 (map second column))))
160 squeezed 161 (partition-by first (sort-by first points))))
161 (reduce 162 squeezed
162 concat 163 (reduce
163 (map 164 concat
164 (fn [row] 165 (map
165 (map vector 166 (fn [row]
166 (collapse-1d (first center) 167 (map vector
167 (map first row)) 168 (collapse-1d (first center)
168 (map second row))) 169 (map first row))
169 (partition-by second (sort-by second flattened)))) 170 (map second row)))
170 relocate 171 (partition-by second (sort-by second flattened))))
171 (let [min-x (apply min (map first squeezed)) 172 relocate
172 min-y (apply min (map second squeezed))] 173 (let [min-x (apply min (map first squeezed))
173 (map (fn [[x y]] 174 min-y (apply min (map second squeezed))]
174 [(- x min-x) 175 (map (fn [[x y]]
175 (- y min-y)]) 176 [(- x min-x)
176 squeezed))] 177 (- y min-y)])
177 relocate 178 squeezed))]
178 )) 179 relocate
180 )))
179 181
180 (defn load-bullet [] 182 (defn load-bullet []
181 (let [sim (world (Node.) {} no-op no-op)] 183 (let [sim (world (Node.) {} no-op no-op)]
182 (doto sim 184 (doto sim
183 (.enqueue 185 (.enqueue
415 417
416 (import jme3tools.converters.ImageToAwt) 418 (import jme3tools.converters.ImageToAwt)
417 419
418 (import ij.ImagePlus) 420 (import ij.ImagePlus)
419 421
420 (defn triangle-indices 422 ;; Every Mesh has many triangles, each with its own index.
421 "Get the triangle vertex indices of a given triangle from a given 423 ;; Every vertex has its own index as well.
422 mesh." 424
423 [#^Mesh mesh triangle-index] 425 (defn tactile-sensor-image
424 (let [indices (int-array 3)]
425 (.getTriangle mesh triangle-index indices)
426 (vec indices)))
427
428 (defn uv-coord
429 "Get the uv-coordinates of the vertex named by vertex-index"
430 [#^Mesh mesh vertex-index]
431 (let [UV-buffer
432 (.getData
433 (.getBuffer
434 mesh
435 VertexBuffer$Type/TexCoord))]
436 (Vector2f.
437 (.get UV-buffer (* vertex-index 2))
438 (.get UV-buffer (+ 1 (* vertex-index 2))))))
439
440 (defn tri-uv-coord
441 "Get the uv-cooridnates of the triangle's verticies."
442 [#^Mesh mesh #^Triangle triangle]
443 (map (partial uv-coord mesh)
444 (triangle-indices mesh (.getIndex triangle))))
445
446 (defn touch-receptor-image
447 "Return the touch-sensor distribution image in ImagePlus format, or 426 "Return the touch-sensor distribution image in ImagePlus format, or
448 nil if it does not exist." 427 nil if it does not exist."
449 [#^Geometry obj] 428 [#^Geometry obj]
450 (let [mat (.getMaterial obj)] 429 (let [mat (.getMaterial obj)]
451 (if-let [texture-param 430 (if-let [texture-param
454 MaterialHelper/TEXTURE_TYPE_DIFFUSE)] 433 MaterialHelper/TEXTURE_TYPE_DIFFUSE)]
455 (let 434 (let
456 [texture 435 [texture
457 (.getTextureValue texture-param) 436 (.getTextureValue texture-param)
458 im (.getImage texture)] 437 im (.getImage texture)]
459 (ImagePlus. 438 (ImageToAwt/convert im false false 0)))))
460 "UV-map"
461 (ImageToAwt/convert im false false 0))))))
462 439
463 (import ij.process.ImageProcessor) 440 (import ij.process.ImageProcessor)
464 (import java.awt.image.BufferedImage) 441 (import java.awt.image.BufferedImage)
465 442
466 (def white -1) 443 (def white -1)
467 444
468 (defn filter-pixels 445 (defn filter-pixels
469 "List the coordinates of all pixels matching pred." 446 "List the coordinates of all pixels matching pred, within the bounds
447 provided. Bounds -> [x0 y0 width height]"
470 {:author "Dylan Holmes"} 448 {:author "Dylan Holmes"}
471 [pred #^ImageProcessor ip] 449 ([pred #^BufferedImage image]
472 (let 450 (filter-pixels pred image [0 0 (.getWidth image) (.getHeight image)]))
473 [width (.getWidth ip) 451 ([pred #^BufferedImage image [x0 y0 width height]]
474 height (.getHeight ip)] 452 ((fn accumulate [x y matches]
475 ((fn accumulate [x y matches] 453 (cond
476 (cond 454 (>= y (+ height y0)) matches
477 (>= y height) matches 455 (>= x (+ width x0)) (recur 0 (inc y) matches)
478 (>= x width) (recur 0 (inc y) matches) 456 (pred (.getRGB image x y))
479 (pred (.getPixel ip x y)) 457 (recur (inc x) y (conj matches [x y]))
480 (recur (inc x) y (conj matches (Vector2f. x y))) 458 :else (recur (inc x) y matches)))
481 :else (recur (inc x) y matches))) 459 x0 y0 [])))
482 0 0 [])))
483 460
484 (defn white-coordinates 461 (defn white-coordinates
485 "List the coordinates of all the white pixels in an image." 462 "Coordinates of all the white pixels in a subset of the image."
486 [#^ImageProcessor ip] 463 [#^BufferedImage image bounds]
487 (filter-pixels #(= % white) ip)) 464 (filter-pixels #(= % white) image bounds))
465
466 (defn triangle
467 "Get the triangle specified by triangle-index from the mesh"
468 [#^Mesh mesh triangle-index]
469 (let [scratch (Triangle.)]
470 (.getTriangle mesh triangle-index scratch)
471 scratch))
472
473 (defn triangle-vertex-indices
474 "Get the triangle vertex indices of a given triangle from a given
475 mesh."
476 [#^Mesh mesh triangle-index]
477 (let [indices (int-array 3)]
478 (.getTriangle mesh triangle-index indices)
479 (vec indices)))
480
481 (defn vertex-UV-coord
482 "Get the uv-coordinates of the vertex named by vertex-index"
483 [#^Mesh mesh vertex-index]
484 (let [UV-buffer
485 (.getData
486 (.getBuffer
487 mesh
488 VertexBuffer$Type/TexCoord))]
489 [(.get UV-buffer (* vertex-index 2))
490 (.get UV-buffer (+ 1 (* vertex-index 2)))]))
491
492 (defn triangle-UV-coord
493 "Get the uv-cooridnates of the triangle's verticies."
494 [#^Mesh mesh width height triangle-index]
495 (map (fn [[u v]] (vector (* width u) (* height v)))
496 (map (partial vertex-UV-coord mesh)
497 (triangle-vertex-indices mesh triangle-index))))
488 498
489 (defn same-side? 499 (defn same-side?
490 "Given the points p1 and p2 and the reference point ref, is point p 500 "Given the points p1 and p2 and the reference point ref, is point p
491 on the same side of the line that goes through p1 and p2 as ref is?" 501 on the same side of the line that goes through p1 and p2 as ref is?"
492 [p1 p2 ref p] 502 [p1 p2 ref p]
494 0 504 0
495 (.dot 505 (.dot
496 (.cross (.subtract p2 p1) (.subtract p p1)) 506 (.cross (.subtract p2 p1) (.subtract p p1))
497 (.cross (.subtract p2 p1) (.subtract ref p1))))) 507 (.cross (.subtract p2 p1) (.subtract ref p1)))))
498 508
509 (defn triangle-seq [#^Triangle tri]
510 [(.get1 tri) (.get2 tri) (.get3 tri)])
511
512 (defn vector3f-seq [#^Vector3f v]
513 [(.getX v) (.getY v) (.getZ v)])
514
515 (defn inside-triangle?
516 "Is the point inside the triangle?"
517 {:author "Dylan Holmes"}
518 [#^Triangle tri #^Vector3f p]
519 (let [[vert-1 vert-2 vert-3] (triangle-seq tri)]
520 (and
521 (same-side? vert-1 vert-2 vert-3 p)
522 (same-side? vert-2 vert-3 vert-1 p)
523 (same-side? vert-3 vert-1 vert-2 p))))
524
499 (defn triangle->matrix4f 525 (defn triangle->matrix4f
500 "Converts the triangle into a 4x4 matrix of vertices: The first 526 "Converts the triangle into a 4x4 matrix: The first three columns
501 three columns contain the vertices of the triangle; the last 527 contain the vertices of the triangle; the last contains the unit
502 contains the unit normal of the triangle. The bottom row is filled 528 normal of the triangle. The bottom row is filled with 1s."
503 with 1s."
504 [#^Triangle t] 529 [#^Triangle t]
505 (let [mat (Matrix4f.) 530 (let [mat (Matrix4f.)
506 [vert-1 vert-2 vert-3] 531 [vert-1 vert-2 vert-3]
507 ((comp vec map) #(.get t %) (range 3)) 532 ((comp vec map) #(.get t %) (range 3))
508 unit-normal (do (.calculateNormal t)(.getNormal t)) 533 unit-normal (do (.calculateNormal t)(.getNormal t))
521 [#^Triangle tri-1 #^Triangle tri-2] 546 [#^Triangle tri-1 #^Triangle tri-2]
522 (.mult 547 (.mult
523 (triangle->matrix4f tri-2) 548 (triangle->matrix4f tri-2)
524 (.invert (triangle->matrix4f tri-1)))) 549 (.invert (triangle->matrix4f tri-1))))
525 550
526 (def death (Triangle. 551 (defn point->vector2f [[u v]]
527 (Vector3f. 1 1 1) 552 (Vector2f. u v))
528 (Vector3f. 1 2 3)
529 (Vector3f. 5 6 7)))
530
531 (def death-2 (Triangle.
532 (Vector3f. 2 2 2)
533 (Vector3f. 1 1 1)
534 (Vector3f. 0 1 0)))
535 553
536 (defn vector2f->vector3f [v] 554 (defn vector2f->vector3f [v]
537 (Vector3f. (.getX v) (.getY v) 0)) 555 (Vector3f. (.getX v) (.getY v) 0))
538
539 (extend-type Triangle
540 Textual
541 (text [t]
542 (println "Triangle: " \newline (.get1 t) \newline
543 (.get2 t) \newline (.get3 t))))
544 556
545 (defn map-triangle [f #^Triangle tri] 557 (defn map-triangle [f #^Triangle tri]
546 (Triangle. 558 (Triangle.
547 (f 0 (.get1 tri)) 559 (f 0 (.get1 tri))
548 (f 1 (.get2 tri)) 560 (f 1 (.get2 tri))
549 (f 2 (.get3 tri)))) 561 (f 2 (.get3 tri))))
550 562
551 (defn triangle-seq [#^Triangle tri] 563 (defn points->triangle
552 [(.get1 tri) (.get2 tri) (.get3 tri)]) 564 "Convert a list of points into a triangle."
553 565 [points]
554 (defn vector3f-seq [#^Vector3f v]
555 [(.getX v) (.getY v) (.getZ v)])
556
557 (defn inside-triangle?
558 "Is the point inside the triangle? Now what do we do?
559 You might want to hold on there"
560 {:author "Dylan Holmes"}
561 [tri p]
562 (let [[vert-1 vert-2 vert-3] (triangle-seq tri)]
563 (and
564 (same-side? vert-1 vert-2 vert-3 p)
565 (same-side? vert-2 vert-3 vert-1 p)
566 (same-side? vert-3 vert-1 vert-2 p))))
567
568 (defn uv-triangle
569 "Convert the mesh triangle into the cooresponding triangle in
570 UV-space. Z-component of these triangles is always zero."
571 [#^Mesh mesh #^Triangle tri]
572 (apply #(Triangle. %1 %2 %3) 566 (apply #(Triangle. %1 %2 %3)
573 (map vector2f->vector3f 567 (map (fn [point]
574 (tri-uv-coord mesh tri)))) 568 (let [point (vec point)]
575 569 (Vector3f. (get point 0 0)
576 (defn pixel-triangle 570 (get point 1 0)
577 "Convert the mesh triangle into the corresponding triangle in 571 (get point 2 0))))
578 UV-pixel-space. Z compenent will be zero." 572 (take 3 points))))
579 [#^Mesh mesh #^Triangle tri width height] 573
580 (map-triangle (fn [_ v] 574 (defn convex-bounds
581 (Vector3f. (* width (.getX v)) 575 "Dimensions of the smallest integer bounding square of the list of
582 (* height (.getY v)) 576 2D verticies in the form: [x y width height]."
583 0)) 577 [uv-verts]
584 (uv-triangle mesh tri))) 578 (let [xs (map first uv-verts)
585 579 ys (map second uv-verts)
586 (def rasterize pixel-triangle) 580 x0 (Math/floor (apply min xs))
587 581 y0 (Math/floor (apply min ys))
588 582 x1 (Math/ceil (apply max xs))
589 (defn triangle-bounds 583 y1 (Math/ceil (apply max ys))]
590 "Dimensions of the bounding square of the triangle in the form 584 [x0 y0 (- x1 x0) (- y1 y0)]))
591 [x y width height].
592 Assumes that the triangle lies in the XY plane."
593 [#^Triangle tri]
594 (let [verts (map vector3f-seq (triangle-seq tri))
595 x (apply min (map first verts))
596 y (apply min (map second verts))]
597 [x y
598 (- (apply max (map first verts)) x)
599 (- (apply max (map second verts)) y)
600 ]))
601
602 585
603 (defn sensors-in-triangle 586 (defn sensors-in-triangle
604 "Find the locations of the touch sensors within a triangle in both 587 "Find the locations of the touch sensors within a triangle in both
605 UV and gemoetry relative coordinates." 588 UV and gemoetry relative coordinates."
606 [image mesh tri-index] 589 [image mesh tri-index]
607 (let [width (.getWidth image) 590 (let [width (.getWidth image)
608 height (.getHeight image)] 591 height (.getHeight image)
609 592 UV-vertex-coords (triangle-UV-coord mesh width height tri-index)
610 593 bounds (convex-bounds UV-vertex-coords)
611 594
612 595 cutout-triangle (points->triangle UV-vertex-coords)
613 ) 596 UV-sensor-coords
614 597 (filter (comp (partial inside-triangle? cutout-triangle)
615 598 (fn [[u v]] (Vector3f. u v 0)))
616 (defn locate-feelers 599 (white-coordinates image bounds))
600 UV->geometry (triangle-transformation
601 cutout-triangle
602 (triangle mesh tri-index))
603 geometry-sensor-coords
604 (map (fn [[u v]] (.mult UV->geometry (Vector3f. u v 0)))
605 UV-sensor-coords)]
606 {:UV UV-sensor-coords :geometry geometry-sensor-coords}))
607
608 (defn-memo locate-feelers
617 "Search the geometry's tactile UV image for touch sensors, returning 609 "Search the geometry's tactile UV image for touch sensors, returning
618 their positions in geometry-relative coordinates." 610 their positions in geometry-relative coordinates."
619 [#^Geometry geo] 611 [#^Geometry geo]
620 (if-let [image (touch-receptor-image geo)] 612 (let [mesh (.getMesh geo)
621 (let [mesh (.getMesh geo) 613 num-triangles (.getTriangleCount mesh)]
622 tris (triangles geo) 614 (if-let [image (tactile-sensor-image geo)]
623 615 (map
624 width (.getWidth image) 616 (partial sensors-in-triangle image mesh)
625 height (.getHeight image) 617 (range num-triangles))
626 618 (repeat (.getTriangleCount mesh) {:UV nil :geometry nil}))))
627 ;; for each triangle
628 sensor-coords
629 (fn [tri]
630 ;; translate triangle to uv-pixel-space
631 (let [uv-tri
632 (pixel-triangle mesh tri width height)
633 bounds (vec (triangle-bounds uv-tri))]
634
635 ;; get that part of the picture
636
637 (apply #(.setRoi image %1 %2 %3 %4) bounds)
638 (let [cutout (.crop (.getProcessor image))
639 ;; extract white pixels inside triangle
640 cutout-tri
641 (map-triangle
642 (fn [_ v]
643 (.subtract
644 v
645 (Vector3f. (bounds 0) (bounds 1) (float 0))))
646 uv-tri)
647 whites (filter (partial inside-triangle? cutout-tri)
648 (map vector2f->vector3f
649 (white-coordinates cutout)))
650 ;; translate pixel coordinates to world-space
651 transform (triangle-transformation cutout-tri tri)]
652 (map #(.mult transform %) whites))))]
653 (vec (map sensor-coords tris)))
654 (repeat (count (triangles geo)) [])))
655 619
656 (use 'clojure.contrib.def) 620 (use 'clojure.contrib.def)
657 621
658 (defn-memo touch-topology [#^Gemoetry geo] 622 (defn-memo touch-topology [#^Gemoetry geo]
659 (if-let [image (touch-receptor-image geo)] 623 (vec (collapse (reduce concat (map :UV (locate-feelers geo))))))
660 (let [feeler-coords 624
661 (map 625 (defn-memo feeler-coordinates [#^Geometry geo]
662 #(vector (int (.getX %)) (int (.getY %))) 626 (vec (map :geometry (locate-feelers geo))))
663 (white-coordinates
664 (.getProcessor image)))]
665 (vec (collapse feeler-coords)))
666 []))
667 627
668 (defn enable-touch [#^Geometry geo] 628 (defn enable-touch [#^Geometry geo]
669 (let [feeler-coords (locate-feelers geo) 629 (let [feeler-coords (feeler-coordinates geo)
670 tris (triangles geo) 630 tris (triangles geo)
671 limit 0.1] 631 limit 0.1]
672 (fn [node] 632 (fn [node]
673 (let [sensor-origins 633 (let [sensor-origins
674 (map 634 (map
742 (light-up-everything world) 702 (light-up-everything world)
743 (enable-debug world) 703 (enable-debug world)
744 ;;(com.aurellem.capture.Capture/captureVideo 704 ;;(com.aurellem.capture.Capture/captureVideo
745 ;; world (file-str "/home/r/proj/ai-videos/hand")) 705 ;; world (file-str "/home/r/proj/ai-videos/hand"))
746 (.setTimer world (RatchetTimer. 60)) 706 (.setTimer world (RatchetTimer. 60))
707 ;;(speed-up world)
747 ;;(set-gravity world (Vector3f. 0 0 0)) 708 ;;(set-gravity world (Vector3f. 0 0 0))
748 ) 709 )
749 (fn [world tpf] 710 (fn [world tpf]
750 (dorun 711 (dorun
751 (map #(%1 (%2 (.getRootNode world))) touch-debug-windows touch-nerves)) 712 (map #(%1 (%2 (.getRootNode world))) touch-debug-windows touch-nerves))