Mercurial > cortex
comparison org/sense.org @ 200:7eb966144dad
finished video for sense.org, now with subtitles!
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Mon, 06 Feb 2012 08:26:20 -0700 |
parents | 305439cec54d |
children | 1c915cc1118b |
comparison
equal
deleted
inserted
replaced
199:305439cec54d | 200:7eb966144dad |
---|---|
217 relocated))) | 217 relocated))) |
218 #+end_src | 218 #+end_src |
219 * Viewing Sense Data | 219 * Viewing Sense Data |
220 | 220 |
221 It's vital to /see/ the sense data to make sure that everything is | 221 It's vital to /see/ the sense data to make sure that everything is |
222 behaving as it should. =(view-sense)= is here so that each sense can | 222 behaving as it should. =(view-sense)= and its helper, =(view-image)= |
223 define its own way of turning sense-data into pictures, while the | 223 are here so that each sense can define its own way of turning |
224 actual rendering of said pictures stays in one central place. | 224 sense-data into pictures, while the actual rendering of said pictures |
225 =(points->image)= helps senses generate a base image onto which they | 225 stays in one central place. =(points->image)= helps senses generate a |
226 can overlay actual sense data. | 226 base image onto which they can overlay actual sense data. |
227 | 227 |
228 #+name: view-senses | 228 #+name: view-senses |
229 #+begin_src clojure | 229 #+begin_src clojure |
230 (in-ns 'cortex.sense) | 230 (in-ns 'cortex.sense) |
231 | |
232 (defn points->image | |
233 "Take a collection of points and visuliaze it as a BufferedImage." | |
234 [points] | |
235 (if (empty? points) | |
236 (BufferedImage. 1 1 BufferedImage/TYPE_BYTE_BINARY) | |
237 (let [xs (vec (map first points)) | |
238 ys (vec (map second points)) | |
239 x0 (apply min xs) | |
240 y0 (apply min ys) | |
241 width (- (apply max xs) x0) | |
242 height (- (apply max ys) y0) | |
243 image (BufferedImage. (inc width) (inc height) | |
244 BufferedImage/TYPE_INT_RGB)] | |
245 (dorun | |
246 (for [x (range (.getWidth image)) | |
247 y (range (.getHeight image))] | |
248 (.setRGB image x y 0xFF0000))) | |
249 (dorun | |
250 (for [index (range (count points))] | |
251 (.setRGB image (- (xs index) x0) (- (ys index) y0) -1))) | |
252 image))) | |
253 | 231 |
254 (defn view-image | 232 (defn view-image |
255 "Initailizes a JPanel on which you may draw a BufferedImage. | 233 "Initailizes a JPanel on which you may draw a BufferedImage. |
256 Returns a function that accepts a BufferedImage and draws it to the | 234 Returns a function that accepts a BufferedImage and draws it to the |
257 JPanel. If given a directory it will save the images as png files | 235 JPanel. If given a directory it will save the images as png files |
301 (map | 279 (map |
302 (fn [display datum] | 280 (fn [display datum] |
303 (display (sense-display-kernel datum))) | 281 (display (sense-display-kernel datum))) |
304 @windows data))))) | 282 @windows data))))) |
305 | 283 |
284 (defn points->image | |
285 "Take a collection of points and visuliaze it as a BufferedImage." | |
286 [points] | |
287 (if (empty? points) | |
288 (BufferedImage. 1 1 BufferedImage/TYPE_BYTE_BINARY) | |
289 (let [xs (vec (map first points)) | |
290 ys (vec (map second points)) | |
291 x0 (apply min xs) | |
292 y0 (apply min ys) | |
293 width (- (apply max xs) x0) | |
294 height (- (apply max ys) y0) | |
295 image (BufferedImage. (inc width) (inc height) | |
296 BufferedImage/TYPE_INT_RGB)] | |
297 (dorun | |
298 (for [x (range (.getWidth image)) | |
299 y (range (.getHeight image))] | |
300 (.setRGB image x y 0xFF0000))) | |
301 (dorun | |
302 (for [index (range (count points))] | |
303 (.setRGB image (- (xs index) x0) (- (ys index) y0) -1))) | |
304 image))) | |
305 | |
306 (defn gray | 306 (defn gray |
307 "Create a gray RGB pixel with R, G, and B set to num. num must be | 307 "Create a gray RGB pixel with R, G, and B set to num. num must be |
308 between 0 and 255." | 308 between 0 and 255." |
309 [num] | 309 [num] |
310 (+ num | 310 (+ num |
375 (defn local-to-world | 375 (defn local-to-world |
376 "Convert the local coordinates into world relative coordinates" | 376 "Convert the local coordinates into world relative coordinates" |
377 [#^Spatial object local-coordinate] | 377 [#^Spatial object local-coordinate] |
378 (.localToWorld object local-coordinate nil)) | 378 (.localToWorld object local-coordinate nil)) |
379 #+end_src | 379 #+end_src |
380 | |
381 ** Sense Binding | |
380 | 382 |
381 =(bind-sense)= binds either a Camera or a Listener object to any | 383 =(bind-sense)= binds either a Camera or a Listener object to any |
382 object so that they will follow that object no matter how it | 384 object so that they will follow that object no matter how it |
383 moves. It is used to create both eyes and ears. | 385 moves. It is used to create both eyes and ears. |
384 | 386 |
408 sense | 410 sense |
409 (.mult total-rotation initial-sense-rotation)))) | 411 (.mult total-rotation initial-sense-rotation)))) |
410 (controlRender [_ _]))))) | 412 (controlRender [_ _]))))) |
411 #+end_src | 413 #+end_src |
412 | 414 |
413 Here is some example code which shows a camera bound to a blue | 415 Here is some example code which shows how a camera bound to a blue box |
414 box as it is buffeted by white cannonballs. | 416 with =(bind-sense)= moves as the box is buffeted by white cannonballs. |
415 | 417 |
416 #+name: test | 418 #+name: test |
417 #+begin_src clojure | 419 #+begin_src clojure |
418 (ns cortex.test.sense | 420 (ns cortex.test.sense |
419 (:use (cortex world util sense vision)) | 421 (:use (cortex world util sense vision)) |
452 BufferedImage!)) | 454 BufferedImage!)) |
453 (add-camera! world (.getCamera world) no-op))) | 455 (add-camera! world (.getCamera world) no-op))) |
454 no-op))) | 456 no-op))) |
455 #+end_src | 457 #+end_src |
456 | 458 |
457 ** Demo Video | |
458 | |
459 #+begin_html | 459 #+begin_html |
460 <video controls="controls" width="755"> | 460 <video controls="controls" width="755"> |
461 <source src="../video/bind-sense.ogg" type="video/ogg" | 461 <source src="../video/bind-sense.ogg" type="video/ogg" |
462 preload="none" poster="../images/aurellem-1280x480.png" /> | 462 preload="none" poster="../images/aurellem-1280x480.png" /> |
463 </video> | 463 </video> |
464 | 464 |
465 #+end_html | 465 #+end_html |
466 | 466 |
467 note to self: the video was created with the following commands: | 467 With this, eyes are easy --- you just bind the camera closer to the |
468 | 468 desired object, and set it to look outward instead of inward as it |
469 | 469 does in the video. |
470 | |
471 (nb : the video was created with the following commands) | |
472 | |
473 *** Combine Frames with ImageMagick | |
470 #+begin_src clojure :results silent | 474 #+begin_src clojure :results silent |
471 (in-ns 'user) | 475 (in-ns 'user) |
472 (import java.io.File) | 476 (import java.io.File) |
473 (use 'clojure.contrib.shell-out) | 477 (use 'clojure.contrib.shell-out) |
474 | |
475 (let | 478 (let |
476 [idx (atom -1) | 479 [idx (atom -1) |
477 left (rest | 480 left (rest |
478 (sort | 481 (sort |
479 (file-seq (File. "/home/r/proj/cortex/render/bind-sense0/")))) | 482 (file-seq (File. "/home/r/proj/cortex/render/bind-sense0/")))) |
480 right (rest | 483 right (rest |
481 (sort | 484 (sort |
482 (file-seq (File. "/home/r/proj/cortex/render/bind-sense1/"))))] | 485 (file-seq |
486 (File. "/home/r/proj/cortex/render/bind-sense1/")))) | |
487 sub (rest | |
488 (sort | |
489 (file-seq | |
490 (File. "/home/r/proj/cortex/render/bind-senseB/")))) | |
491 sub* (concat sub (repeat 1000 (last sub)))] | |
483 (dorun | 492 (dorun |
484 (map | 493 (map |
485 (fn [im-1 im-2] | 494 (fn [im-1 im-2 sub] |
486 (println idx) | |
487 (sh "convert" (.getCanonicalPath im-1) | 495 (sh "convert" (.getCanonicalPath im-1) |
488 (.getCanonicalPath im-2) "+append" | 496 (.getCanonicalPath im-2) "+append" |
497 (.getCanonicalPath sub) "-append" | |
489 (.getCanonicalPath | 498 (.getCanonicalPath |
490 (File. "/home/r/proj/cortex/render/bind-sense/" | 499 (File. "/home/r/proj/cortex/render/bind-sense/" |
491 (format "%07d.png" (swap! idx inc)))))) | 500 (format "%07d.png" (swap! idx inc)))))) |
492 left right))) | 501 left right sub*))) |
493 #+end_src | 502 #+end_src |
503 | |
504 *** Encode Frames with ffmpeg | |
494 | 505 |
495 #+begin_src sh :results silent | 506 #+begin_src sh :results silent |
496 cd /home/r/proj/cortex/render/ | 507 cd /home/r/proj/cortex/render/ |
497 cp ../images/aurellem-1280x480.png bind-sense/0000000.png | |
498 ffmpeg -r 60 -b 9000k -i bind-sense/%07d.png bind-sense.ogg | 508 ffmpeg -r 60 -b 9000k -i bind-sense/%07d.png bind-sense.ogg |
499 #+end_src | 509 #+end_src |
500 | |
501 | |
502 | 510 |
503 * Bookkeeping | 511 * Bookkeeping |
504 Here is the header for this namespace, included for completness. | 512 Here is the header for this namespace, included for completness. |
505 #+name: header | 513 #+name: header |
506 #+begin_src clojure | 514 #+begin_src clojure |
518 (:import com.jme3.scene.control.AbstractControl) | 526 (:import com.jme3.scene.control.AbstractControl) |
519 (:import (com.jme3.math Quaternion Vector3f)) | 527 (:import (com.jme3.math Quaternion Vector3f)) |
520 (:import javax.imageio.ImageIO) | 528 (:import javax.imageio.ImageIO) |
521 (:import java.io.File) | 529 (:import java.io.File) |
522 (:import (javax.swing JPanel JFrame SwingUtilities))) | 530 (:import (javax.swing JPanel JFrame SwingUtilities))) |
523 | |
524 #+end_src | 531 #+end_src |
525 | 532 |
526 * Source Listing | 533 * Source Listing |
527 Full source: [[../src/cortex/sense.clj][sense.clj]] | 534 Full source: [[../src/cortex/sense.clj][sense.clj]] |
528 | 535 |