Mercurial > cortex
comparison org/sense.org @ 199:305439cec54d
added video to sense.org
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Mon, 06 Feb 2012 01:40:22 -0700 |
parents | fc0bf33bded2 |
children | 7eb966144dad |
comparison
equal
deleted
inserted
replaced
198:fc0bf33bded2 | 199:305439cec54d |
---|---|
223 define its own way of turning sense-data into pictures, while the | 223 define its own way of turning sense-data into pictures, while the |
224 actual rendering of said pictures stays in one central place. | 224 actual rendering of said pictures stays in one central place. |
225 =(points->image)= helps senses generate a base image onto which they | 225 =(points->image)= helps senses generate a base image onto which they |
226 can overlay actual sense data. | 226 can overlay actual sense data. |
227 | 227 |
228 #+name view-senses | 228 #+name: view-senses |
229 #+begin_src clojure | 229 #+begin_src clojure |
230 (defn view-sense | 230 (in-ns 'cortex.sense) |
231 "Take a kernel that produces a BufferedImage from some sense data | |
232 and return a function which takes a list of sense data, uses the | |
233 kernel to convert to images, and displays those images, each in | |
234 its own JFrame." | |
235 [sense-display-kernel] | |
236 (let [windows (atom [])] | |
237 (fn [data] | |
238 (if (> (count data) (count @windows)) | |
239 (reset! | |
240 windows (map (fn [_] (view-image)) (range (count data))))) | |
241 (dorun | |
242 (map | |
243 (fn [display datum] | |
244 (display (sense-display-kernel datum))) | |
245 @windows data))))) | |
246 | 231 |
247 (defn points->image | 232 (defn points->image |
248 "Take a collection of points and visuliaze it as a BufferedImage." | 233 "Take a collection of points and visuliaze it as a BufferedImage." |
249 [points] | 234 [points] |
250 (if (empty? points) | 235 (if (empty? points) |
264 (dorun | 249 (dorun |
265 (for [index (range (count points))] | 250 (for [index (range (count points))] |
266 (.setRGB image (- (xs index) x0) (- (ys index) y0) -1))) | 251 (.setRGB image (- (xs index) x0) (- (ys index) y0) -1))) |
267 image))) | 252 image))) |
268 | 253 |
254 (defn view-image | |
255 "Initailizes a JPanel on which you may draw a BufferedImage. | |
256 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 | |
258 starting at 0000000.png and incrementing from there." | |
259 ([#^File save] | |
260 (let [idx (atom -1) | |
261 image | |
262 (atom | |
263 (BufferedImage. 1 1 BufferedImage/TYPE_4BYTE_ABGR)) | |
264 panel | |
265 (proxy [JPanel] [] | |
266 (paint | |
267 [graphics] | |
268 (proxy-super paintComponent graphics) | |
269 (.drawImage graphics @image 0 0 nil))) | |
270 frame (JFrame. "Display Image")] | |
271 (SwingUtilities/invokeLater | |
272 (fn [] | |
273 (doto frame | |
274 (-> (.getContentPane) (.add panel)) | |
275 (.pack) | |
276 (.setLocationRelativeTo nil) | |
277 (.setResizable true) | |
278 (.setVisible true)))) | |
279 (fn [#^BufferedImage i] | |
280 (reset! image i) | |
281 (.setSize frame (+ 8 (.getWidth i)) (+ 28 (.getHeight i))) | |
282 (.repaint panel 0 0 (.getWidth i) (.getHeight i)) | |
283 (if save | |
284 (ImageIO/write | |
285 i "png" | |
286 (File. save (format "%07d.png" (swap! idx inc)))))))) | |
287 ([] (view-image nil))) | |
288 | |
289 (defn view-sense | |
290 "Take a kernel that produces a BufferedImage from some sense data | |
291 and return a function which takes a list of sense data, uses the | |
292 kernel to convert to images, and displays those images, each in | |
293 its own JFrame." | |
294 [sense-display-kernel] | |
295 (let [windows (atom [])] | |
296 (fn [data] | |
297 (if (> (count data) (count @windows)) | |
298 (reset! | |
299 windows (map (fn [_] (view-image)) (range (count data))))) | |
300 (dorun | |
301 (map | |
302 (fn [display datum] | |
303 (display (sense-display-kernel datum))) | |
304 @windows data))))) | |
305 | |
269 (defn gray | 306 (defn gray |
270 "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 |
271 between 0 and 255." | 308 between 0 and 255." |
272 [num] | 309 [num] |
273 (+ num | 310 (+ num |
341 (.localToWorld object local-coordinate nil)) | 378 (.localToWorld object local-coordinate nil)) |
342 #+end_src | 379 #+end_src |
343 | 380 |
344 =(bind-sense)= binds either a Camera or a Listener object to any | 381 =(bind-sense)= binds either a Camera or a Listener object to any |
345 object so that they will follow that object no matter how it | 382 object so that they will follow that object no matter how it |
346 moves. Here is some example code which shows a camera bound to a blue | 383 moves. It is used to create both eyes and ears. |
347 box as it is buffeted by white cannonballs. | |
348 | 384 |
349 #+name: node-2 | 385 #+name: node-2 |
350 #+begin_src clojure | 386 #+begin_src clojure |
351 (defn bind-sense | 387 (defn bind-sense |
352 "Bind the sense to the Spatial such that it will maintain its | 388 "Bind the sense to the Spatial such that it will maintain its |
372 sense | 408 sense |
373 (.mult total-rotation initial-sense-rotation)))) | 409 (.mult total-rotation initial-sense-rotation)))) |
374 (controlRender [_ _]))))) | 410 (controlRender [_ _]))))) |
375 #+end_src | 411 #+end_src |
376 | 412 |
413 Here is some example code which shows a camera bound to a blue | |
414 box as it is buffeted by white cannonballs. | |
415 | |
416 #+name: test | |
417 #+begin_src clojure | |
418 (ns cortex.test.sense | |
419 (:use (cortex world util sense vision)) | |
420 (:import | |
421 java.io.File | |
422 (com.jme3.math Vector3f ColorRGBA) | |
423 (com.aurellem.capture RatchetTimer Capture))) | |
424 | |
425 (defn test-bind-sense | |
426 "Show a camera that stays in the same relative position to a blue cube." | |
427 [] | |
428 (let [camera-pos (Vector3f. 0 30 0) | |
429 rock (box 1 1 1 :color ColorRGBA/Blue | |
430 :position (Vector3f. 0 10 0) | |
431 :mass 30) | |
432 rot (.getWorldRotation rock) | |
433 table (box 3 1 10 :color ColorRGBA/Gray :mass 0 | |
434 :position (Vector3f. 0 -3 0))] | |
435 (world | |
436 (nodify [rock table]) | |
437 standard-debug-controls | |
438 (fn [world] | |
439 (let | |
440 [cam (doto (.clone (.getCamera world)) | |
441 (.setLocation camera-pos) | |
442 (.lookAt Vector3f/ZERO | |
443 Vector3f/UNIT_X))] | |
444 (bind-sense rock cam) | |
445 (.setTimer world (RatchetTimer. 60)) | |
446 (Capture/captureVideo | |
447 world (File. "/home/r/proj/cortex/render/bind-sense0")) | |
448 (add-camera! | |
449 world cam | |
450 (comp (view-image | |
451 (File. "/home/r/proj/cortex/render/bind-sense1")) | |
452 BufferedImage!)) | |
453 (add-camera! world (.getCamera world) no-op))) | |
454 no-op))) | |
455 #+end_src | |
456 | |
457 ** Demo Video | |
458 | |
459 #+begin_html | |
460 <video controls="controls" width="755"> | |
461 <source src="../video/bind-sense.ogg" type="video/ogg" | |
462 preload="none" poster="../images/aurellem-1280x480.png" /> | |
463 </video> | |
464 | |
465 #+end_html | |
466 | |
467 note to self: the video was created with the following commands: | |
468 | |
469 | |
470 #+begin_src clojure :results silent | |
471 (in-ns 'user) | |
472 (import java.io.File) | |
473 (use 'clojure.contrib.shell-out) | |
474 | |
475 (let | |
476 [idx (atom -1) | |
477 left (rest | |
478 (sort | |
479 (file-seq (File. "/home/r/proj/cortex/render/bind-sense0/")))) | |
480 right (rest | |
481 (sort | |
482 (file-seq (File. "/home/r/proj/cortex/render/bind-sense1/"))))] | |
483 (dorun | |
484 (map | |
485 (fn [im-1 im-2] | |
486 (println idx) | |
487 (sh "convert" (.getCanonicalPath im-1) | |
488 (.getCanonicalPath im-2) "+append" | |
489 (.getCanonicalPath | |
490 (File. "/home/r/proj/cortex/render/bind-sense/" | |
491 (format "%07d.png" (swap! idx inc)))))) | |
492 left right))) | |
493 #+end_src | |
494 | |
495 #+begin_src sh :results silent | |
496 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 | |
499 #+end_src | |
500 | |
377 | 501 |
378 | 502 |
379 * Bookkeeping | 503 * Bookkeeping |
380 Here is the header for this namespace, included for completness. | 504 Here is the header for this namespace, included for completness. |
381 #+name header | 505 #+name: header |
382 #+begin_src clojure | 506 #+begin_src clojure |
383 (ns cortex.sense | 507 (ns cortex.sense |
384 "Here are functions useful in the construction of two or more | 508 "Here are functions useful in the construction of two or more |
385 sensors/effectors." | 509 sensors/effectors." |
386 {:author "Robert McInytre"} | 510 {:author "Robert McInytre"} |
390 (:import java.awt.image.BufferedImage) | 514 (:import java.awt.image.BufferedImage) |
391 (:import com.jme3.collision.CollisionResults) | 515 (:import com.jme3.collision.CollisionResults) |
392 (:import com.jme3.bounding.BoundingBox) | 516 (:import com.jme3.bounding.BoundingBox) |
393 (:import (com.jme3.scene Node Spatial)) | 517 (:import (com.jme3.scene Node Spatial)) |
394 (:import com.jme3.scene.control.AbstractControl) | 518 (:import com.jme3.scene.control.AbstractControl) |
395 (:import (com.jme3.math Quaternion Vector3f))) | 519 (:import (com.jme3.math Quaternion Vector3f)) |
520 (:import javax.imageio.ImageIO) | |
521 (:import java.io.File) | |
522 (:import (javax.swing JPanel JFrame SwingUtilities))) | |
523 | |
396 #+end_src | 524 #+end_src |
397 | 525 |
398 * Source Listing | 526 * Source Listing |
399 Full source: [[../src/cortex/sense.clj][sense.clj]] | 527 Full source: [[../src/cortex/sense.clj][sense.clj]] |
400 | 528 |
408 <<topology-2>> | 536 <<topology-2>> |
409 <<node-1>> | 537 <<node-1>> |
410 <<node-2>> | 538 <<node-2>> |
411 <<view-senses>> | 539 <<view-senses>> |
412 #+end_src | 540 #+end_src |
541 | |
542 #+begin_src clojure :tangle ../src/cortex/test/sense.clj | |
543 <<test>> | |
544 #+end_src |