diff 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
line wrap: on
line diff
     1.1 --- a/org/sense.org	Sun Feb 05 14:01:47 2012 -0700
     1.2 +++ b/org/sense.org	Mon Feb 06 01:40:22 2012 -0700
     1.3 @@ -225,24 +225,9 @@
     1.4  =(points->image)= helps senses generate a base image onto which they
     1.5  can overlay actual sense data.
     1.6  
     1.7 -#+name view-senses
     1.8 +#+name: view-senses
     1.9  #+begin_src clojure
    1.10 -(defn view-sense 
    1.11 -  "Take a kernel that produces a BufferedImage from some sense data
    1.12 -   and return a function which takes a list of sense data, uses the
    1.13 -   kernel to convert to images, and displays those images, each in
    1.14 -   its own JFrame."
    1.15 -  [sense-display-kernel]
    1.16 -  (let [windows (atom [])]
    1.17 -    (fn [data]
    1.18 -      (if (> (count data) (count @windows))
    1.19 -        (reset! 
    1.20 -         windows (map (fn [_] (view-image)) (range (count data)))))
    1.21 -      (dorun
    1.22 -       (map
    1.23 -        (fn [display datum]
    1.24 -          (display (sense-display-kernel datum)))
    1.25 -        @windows data)))))
    1.26 +(in-ns 'cortex.sense)
    1.27  
    1.28  (defn points->image
    1.29    "Take a collection of points and visuliaze it as a BufferedImage."
    1.30 @@ -266,6 +251,58 @@
    1.31           (.setRGB image (- (xs index) x0) (- (ys index) y0) -1)))
    1.32        image)))
    1.33  
    1.34 +(defn view-image
    1.35 +  "Initailizes a JPanel on which you may draw a BufferedImage.
    1.36 +   Returns a function that accepts a BufferedImage and draws it to the
    1.37 +   JPanel. If given a directory it will save the images as png files
    1.38 +   starting at 0000000.png and incrementing from there."
    1.39 +  ([#^File save]
    1.40 +     (let [idx (atom -1)
    1.41 +           image
    1.42 +           (atom
    1.43 +            (BufferedImage. 1 1 BufferedImage/TYPE_4BYTE_ABGR))
    1.44 +           panel 
    1.45 +           (proxy [JPanel] []
    1.46 +             (paint
    1.47 +               [graphics]
    1.48 +               (proxy-super paintComponent graphics)
    1.49 +               (.drawImage graphics @image 0 0 nil)))
    1.50 +           frame (JFrame. "Display Image")]
    1.51 +       (SwingUtilities/invokeLater
    1.52 +        (fn []
    1.53 +          (doto frame
    1.54 +            (-> (.getContentPane) (.add panel))
    1.55 +            (.pack)
    1.56 +            (.setLocationRelativeTo nil)
    1.57 +            (.setResizable true)
    1.58 +            (.setVisible true))))
    1.59 +       (fn [#^BufferedImage i]
    1.60 +         (reset! image i)
    1.61 +         (.setSize frame (+ 8 (.getWidth i)) (+ 28 (.getHeight i)))
    1.62 +         (.repaint panel 0 0 (.getWidth i) (.getHeight i))
    1.63 +         (if save
    1.64 +           (ImageIO/write
    1.65 +            i "png"
    1.66 +            (File. save (format "%07d.png" (swap! idx inc))))))))
    1.67 +  ([] (view-image nil)))
    1.68 +
    1.69 +(defn view-sense 
    1.70 +  "Take a kernel that produces a BufferedImage from some sense data
    1.71 +   and return a function which takes a list of sense data, uses the
    1.72 +   kernel to convert to images, and displays those images, each in
    1.73 +   its own JFrame."
    1.74 +  [sense-display-kernel]
    1.75 +  (let [windows (atom [])]
    1.76 +    (fn [data]
    1.77 +      (if (> (count data) (count @windows))
    1.78 +        (reset! 
    1.79 +         windows (map (fn [_] (view-image)) (range (count data)))))
    1.80 +      (dorun
    1.81 +       (map
    1.82 +        (fn [display datum]
    1.83 +          (display (sense-display-kernel datum)))
    1.84 +        @windows data)))))
    1.85 +
    1.86  (defn gray
    1.87    "Create a gray RGB pixel with R, G, and B set to num. num must be
    1.88     between 0 and 255."
    1.89 @@ -343,8 +380,7 @@
    1.90  
    1.91  =(bind-sense)= binds either a Camera or a Listener object to any
    1.92  object so that they will follow that object no matter how it
    1.93 -moves. Here is some example code which shows a camera bound to a blue
    1.94 -box as it is buffeted by white cannonballs.
    1.95 +moves. It is used to create both eyes and ears.
    1.96  
    1.97  #+name: node-2
    1.98  #+begin_src clojure
    1.99 @@ -374,11 +410,99 @@
   1.100         (controlRender [_ _])))))
   1.101  #+end_src
   1.102  
   1.103 +Here is some example code which shows a camera bound to a blue
   1.104 +box as it is buffeted by white cannonballs.
   1.105 +
   1.106 +#+name: test
   1.107 +#+begin_src clojure 
   1.108 +(ns cortex.test.sense
   1.109 +  (:use (cortex world util sense vision))
   1.110 +  (:import
   1.111 +   java.io.File
   1.112 +   (com.jme3.math Vector3f ColorRGBA)
   1.113 +   (com.aurellem.capture RatchetTimer Capture)))
   1.114 +
   1.115 +(defn test-bind-sense
   1.116 +  "Show a camera that stays in the same relative position to a blue cube."
   1.117 +  []
   1.118 +  (let [camera-pos (Vector3f. 0 30 0)
   1.119 +        rock (box 1 1 1 :color ColorRGBA/Blue
   1.120 +                  :position (Vector3f. 0 10 0)
   1.121 +                  :mass 30)
   1.122 +        rot (.getWorldRotation rock)
   1.123 +        table (box 3 1 10 :color ColorRGBA/Gray :mass 0
   1.124 +                   :position (Vector3f. 0 -3 0))]
   1.125 +    (world
   1.126 +     (nodify [rock table])
   1.127 +     standard-debug-controls
   1.128 +     (fn [world]
   1.129 +       (let 
   1.130 +           [cam (doto (.clone (.getCamera world))
   1.131 +                  (.setLocation camera-pos)
   1.132 +                  (.lookAt Vector3f/ZERO
   1.133 +                           Vector3f/UNIT_X))]
   1.134 +         (bind-sense rock cam)
   1.135 +         (.setTimer world (RatchetTimer. 60))
   1.136 +         (Capture/captureVideo
   1.137 +          world (File. "/home/r/proj/cortex/render/bind-sense0"))
   1.138 +         (add-camera!
   1.139 +          world cam
   1.140 +          (comp (view-image
   1.141 +                 (File. "/home/r/proj/cortex/render/bind-sense1"))
   1.142 +                BufferedImage!))
   1.143 +         (add-camera! world (.getCamera world) no-op)))
   1.144 +     no-op)))
   1.145 +#+end_src
   1.146 +
   1.147 +** Demo Video
   1.148 +
   1.149 +#+begin_html
   1.150 +<video controls="controls" width="755">
   1.151 +  <source src="../video/bind-sense.ogg" type="video/ogg"
   1.152 +	  preload="none" poster="../images/aurellem-1280x480.png" />
   1.153 +</video>
   1.154 +
   1.155 +#+end_html
   1.156 +
   1.157 +note to self: the video was created with the following commands:
   1.158 +
   1.159 +
   1.160 +#+begin_src clojure :results silent
   1.161 +(in-ns 'user)
   1.162 +(import java.io.File)
   1.163 +(use 'clojure.contrib.shell-out)
   1.164 +
   1.165 +(let
   1.166 +    [idx (atom -1)
   1.167 +     left (rest 
   1.168 +           (sort
   1.169 +           (file-seq (File. "/home/r/proj/cortex/render/bind-sense0/"))))
   1.170 +     right (rest
   1.171 +            (sort
   1.172 +             (file-seq (File. "/home/r/proj/cortex/render/bind-sense1/"))))]
   1.173 +  (dorun
   1.174 +   (map  
   1.175 +    (fn [im-1 im-2]
   1.176 +      (println idx)
   1.177 +      (sh "convert" (.getCanonicalPath im-1)
   1.178 +          (.getCanonicalPath im-2) "+append"
   1.179 +          (.getCanonicalPath
   1.180 +           (File. "/home/r/proj/cortex/render/bind-sense/"
   1.181 +                  (format "%07d.png" (swap! idx inc))))))
   1.182 +    left right)))
   1.183 +#+end_src
   1.184 +
   1.185 +#+begin_src sh :results silent
   1.186 +cd /home/r/proj/cortex/render/
   1.187 +cp ../images/aurellem-1280x480.png bind-sense/0000000.png             
   1.188 +ffmpeg -r 60 -b 9000k -i bind-sense/%07d.png bind-sense.ogg
   1.189 +#+end_src
   1.190 +
   1.191  
   1.192  
   1.193  * Bookkeeping
   1.194  Here is the header for this namespace, included for completness.
   1.195 -#+name header
   1.196 +#+name: header
   1.197  #+begin_src clojure
   1.198  (ns cortex.sense
   1.199    "Here are functions useful in the construction of two or more
   1.200 @@ -392,7 +516,11 @@
   1.201    (:import com.jme3.bounding.BoundingBox)
   1.202    (:import (com.jme3.scene Node Spatial))
   1.203    (:import com.jme3.scene.control.AbstractControl)
   1.204 -  (:import (com.jme3.math Quaternion Vector3f)))
   1.205 +  (:import (com.jme3.math Quaternion Vector3f))
   1.206 +  (:import javax.imageio.ImageIO)
   1.207 +  (:import java.io.File)
   1.208 +  (:import (javax.swing JPanel JFrame SwingUtilities)))
   1.209 +
   1.210  #+end_src
   1.211  
   1.212  * Source Listing
   1.213 @@ -410,3 +538,7 @@
   1.214  <<node-2>>
   1.215  <<view-senses>>
   1.216  #+end_src
   1.217 +
   1.218 +#+begin_src clojure :tangle ../src/cortex/test/sense.clj
   1.219 +<<test>>
   1.220 +#+end_src