rlm@306: #+title: Integration rlm@73: #+author: Robert McIntyre rlm@73: #+email: rlm@mit.edu rlm@73: #+description: rlm@73: #+keywords: simulation, jMonkeyEngine3, clojure rlm@73: #+SETUPFILE: ../../aurellem/org/setup.org rlm@73: #+INCLUDE: ../../aurellem/org/level-0.org rlm@73: rlm@302: * Integration rlm@129: rlm@281: This is the ultimate test which features all of the senses that I've rlm@281: made so far. The blender file for the creature serves as an example of rlm@281: a fully equipped creature in terms of senses. You can find it [[../assets/Models/test-creature/hand.blend][here]]. rlm@73: rlm@300: rlm@300: #+begin_html rlm@300:
rlm@300: rlm@300:

Simulated Senses in a Virtual Environment

rlm@300:
rlm@300: #+end_html rlm@300: rlm@302: * Generating the Video rlm@300: rlm@192: #+name: integration rlm@73: #+begin_src clojure rlm@300: (ns cortex.test.integration rlm@73: "let's play!" rlm@192: {:author "Robert McIntyre"} rlm@281: (:use (cortex world util body sense rlm@281: hearing touch vision proprioception movement)) rlm@192: (:import (com.jme3.math ColorRGBA Vector3f)) rlm@281: (:import java.io.File) rlm@192: (:import com.jme3.audio.AudioNode) rlm@192: (:import com.aurellem.capture.RatchetTimer)) rlm@73: rlm@281: (dorun (cortex.import/mega-import-jme3)) rlm@281: (rlm.rlm-commands/help) rlm@74: rlm@281: (def hand "Models/test-creature/hand.blend") rlm@78: rlm@281: (def output-base (File. "/home/r/proj/cortex/render/hand")) rlm@300: #+end_src rlm@189: rlm@300: For this demonstration I have to manually drive the muscles of the rlm@300: hand. I do this by creating a little mini-language to describe rlm@300: simulated muscle contraction. rlm@297: rlm@300: #+name: integration-2 rlm@300: #+begin_src clojure rlm@296: (defn motor-control-program rlm@296: "Create a function which will execute the motor script" rlm@296: [muscle-positions rlm@296: script] rlm@296: (let [current-frame (atom -1) rlm@296: keyed-script (group-by first script) rlm@296: current-forces (atom {}) ] rlm@296: (fn [effectors] rlm@296: (let [indexed-effectors (vec effectors)] rlm@296: (dorun rlm@296: (for [[_ part force] (keyed-script (swap! current-frame inc))] rlm@296: (swap! current-forces (fn [m] (assoc m part force))))) rlm@296: (doall (map (fn [effector power] rlm@296: (effector (int power))) rlm@296: effectors rlm@296: (map #(@current-forces % 0) muscle-positions))))))) rlm@296: rlm@296: (def muscle-positions rlm@296: [:pointer-2-e rlm@296: :pointer-2-f rlm@296: :thumb-1 rlm@296: :thumb-1 rlm@296: :pointer-1-e rlm@296: :pointer-1-f rlm@296: :thumb-2-e rlm@296: :thumb-2-f rlm@296: :middle-1-e rlm@296: :middle-1-f rlm@296: :pointer-3-f rlm@296: :pointer-3-e rlm@296: :middle-2-e rlm@296: :middle-2-f rlm@296: :middle-3-f rlm@296: :middle-3-e rlm@296: :pinky-2-e rlm@296: :pinky-2-f rlm@296: :pinky-3-f rlm@296: :pinky-3-e rlm@296: :ring-3-e rlm@296: :ring-3-f rlm@296: :ring-2-f rlm@296: :ring-2-e rlm@296: :ring-1-e rlm@296: :ring-1-f rlm@296: :thumb-1-e rlm@296: :thumb-1-f rlm@296: :pinky-1-f rlm@296: :pinky-1-e]) rlm@296: rlm@296: (def full 9001) rlm@300: rlm@300: rlm@306: ;; Choreography: rlm@300: rlm@300: ;; Let the hand fall palm-up rlm@300: rlm@300: ;; it curls its phalanges, starting with the pinky. rlm@300: rlm@300: ;; it lets its phalanges fall back down. rlm@300: rlm@300: ;; block falls down onto the hand, accompanied by a sound. The block rlm@300: ;; can be seen by the hand's eye. rlm@300: rlm@300: ;; hand FORCEFULLY catapults the block so that it hits the camera. rlm@300: rlm@300: rlm@306: ;; the syntax here is [keyframe body-part force] rlm@300: (def move-fingers rlm@298: [[300 :pinky-3-f 50] rlm@298: [320 :pinky-2-f 80] rlm@298: [340 :pinky-1-f 100] rlm@297: rlm@298: [310 :ring-3-f 100] rlm@298: [330 :ring-2-f 120] rlm@298: [350 :ring-1-f 140] rlm@296: rlm@298: [330 :middle-3-f 120] rlm@298: [340 :middle-2-f 120] rlm@298: [360 :middle-1-f 30] rlm@296: rlm@298: [350 :pointer-3-f 120] rlm@298: [360 :pointer-2-f 120] rlm@298: [380 :pointer-1-f 30] rlm@296: rlm@298: [800 :pinky-3-f 0] rlm@298: [800 :pinky-2-f 0] rlm@298: [800 :pinky-1-f 0] rlm@296: rlm@298: [800 :ring-3-f 0] rlm@298: [800 :ring-2-f 0] rlm@298: [800 :ring-1-f 0] rlm@296: rlm@298: [800 :middle-3-f 0] rlm@298: [800 :middle-2-f 0] rlm@298: [800 :middle-1-f 0] rlm@296: rlm@298: [800 :pointer-3-f 0] rlm@298: [800 :pointer-2-f 0] rlm@298: [800 :pointer-1-f 0] rlm@297: rlm@297: rlm@298: [800 :pinky-3-e 50] rlm@298: [800 :pinky-2-e 80] rlm@298: [800 :pinky-1-e 100] rlm@297: rlm@298: [800 :ring-3-e 100] rlm@298: [800 :ring-2-e 120] rlm@298: [800 :ring-1-e 140] rlm@298: rlm@298: [800 :middle-3-e 120] rlm@298: [800 :middle-2-e 120] rlm@298: [800 :middle-1-e 30] rlm@298: rlm@298: [800 :pointer-3-e 120] rlm@298: [800 :pointer-2-e 120] rlm@298: [800 :pointer-1-e 30] rlm@298: rlm@298: [870 :pinky-3-e 0] rlm@298: [870 :pinky-2-e 0] rlm@298: [870 :pinky-1-e 0] rlm@298: rlm@298: [870 :ring-3-e 0] rlm@298: [870 :ring-2-e 0] rlm@298: [870 :ring-1-e 0] rlm@298: rlm@298: [870 :middle-3-e 0] rlm@298: [870 :middle-2-e 0] rlm@298: [870 :middle-1-e 0] rlm@298: rlm@298: [870 :pointer-3-e 0] rlm@298: [870 :pointer-2-e 0] rlm@298: [870 :pointer-1-e 0] rlm@298: rlm@298: [1500 :pointer-1-f full] rlm@298: [1500 :pointer-2-f full] rlm@298: [1500 :pointer-3-f full] rlm@298: rlm@298: [1500 :middle-1-f full] rlm@298: [1500 :middle-2-f full] rlm@298: [1500 :middle-3-f full] rlm@298: rlm@298: [1510 :pointer-1-f 0] rlm@298: [1510 :pointer-2-f 0] rlm@298: [1510 :pointer-3-f 0] rlm@298: rlm@298: [1510 :middle-1-f 0] rlm@298: [1510 :middle-2-f 0] rlm@298: [1510 :middle-3-f 0] rlm@297: ]) rlm@297: rlm@298: (defn gen-summon-ball [debug?] rlm@298: (let [wait (atom 1100)] rlm@297: (fn [world] rlm@297: (if (= 0 (swap! wait dec)) rlm@297: (let [brick rlm@297: (box 0.8 0.8 0.8 :mass 0.05 rlm@298: :position (Vector3f. -0.5 0 0.5) rlm@298: :color (ColorRGBA/Red)) rlm@298: bell (AudioNode. (asset-manager) rlm@298: "Sounds/pure.wav" false)] rlm@298: (.play bell) rlm@298: (if debug? rlm@298: (.addControl rlm@298: brick rlm@298: (proxy [AbstractControl] [] rlm@298: (controlUpdate [tpf] rlm@298: (println-repl (.getWorldTranslation brick))) rlm@298: (controlRender [_ _])))) rlm@297: (add-element world brick)))))) rlm@295: rlm@298: (import com.aurellem.capture.Capture) rlm@298: rlm@281: (defn test-everything! rlm@281: ([] (test-everything! false)) rlm@281: ([record?] rlm@281: (let [me (sphere 0.5 :color ColorRGBA/Blue :physical? false) rlm@281: rlm@298: base (File. "/home/r/proj/cortex/render/hand") rlm@298: rlm@298: rlm@281: creature (doto (load-blender-model hand) rlm@281: (body!)) rlm@297: rlm@298: summon-ball (gen-summon-ball false) rlm@192: ;;;;;;;;;;;; Sensors/Effectors ;;;;;;;;;;;;;;;;;;;;;;;;;;;; rlm@298: touch (touch! creature) rlm@298: touch-display (view-touch) rlm@189: rlm@298: vision (vision! creature) rlm@298: vision-display (view-vision) rlm@189: rlm@298: hearing (hearing! creature) rlm@298: hearing-display (view-hearing) rlm@189: rlm@173: prop (proprioception! creature) rlm@190: prop-display (view-proprioception) rlm@148: rlm@296: control-script (motor-control-program rlm@300: muscle-positions move-fingers) rlm@191: muscles (movement! creature) rlm@281: muscle-display (view-movement) rlm@281: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; rlm@189: rlm@281: fix-display (gen-fix-display)] rlm@285: (world rlm@285: (nodify [creature rlm@285: (box 10 2 10 :position (Vector3f. 0 -9 0) rlm@285: :color ColorRGBA/Gray :mass 0) rlm@285: me]) rlm@298: standard-debug-controls rlm@298: rlm@285: (fn [world] rlm@285: (.setTimer world (RatchetTimer. 60)) rlm@297: (position-camera rlm@298: world (Vector3f. -0.13217318, 5.816415, -5.3089414) rlm@298: (Quaternion. 0.55685693, 0.0042774677, -0.0028673497, 0.83059245)) rlm@298: rlm@285: (light-up-everything world) rlm@285: (enable-debug world) rlm@285: (add-camera! world rlm@285: (add-eye! creature rlm@285: (.getChild rlm@285: (.getChild creature "eyes") "eye")) rlm@285: (comp (view-image) BufferedImage!)) rlm@298: rlm@298: (if record? rlm@298: (Capture/captureVideo rlm@298: world (File. base "main"))) rlm@298: (if record? rlm@298: (Capture/captureAudio rlm@298: world (File. base "main.wav")))) rlm@285: (fn [world tpf] rlm@298: (prop-display rlm@298: (prop) rlm@298: (if record? (File. base "proprio"))) rlm@298: (touch-display rlm@298: (map #(% (.getRootNode world)) touch) rlm@298: (if record? (File. base "touch"))) rlm@298: (vision-display rlm@298: (map #(% world) vision) rlm@298: (if record? (File. base "vision"))) rlm@298: (hearing-display rlm@298: (map #(% world) hearing) rlm@298: (if record? (File. base "hearing"))) rlm@298: (muscle-display rlm@298: (control-script muscles) rlm@298: (if record? (File. base "muscle"))) rlm@298: rlm@297: (summon-ball world) rlm@298: rlm@285: (.setLocalTranslation me (.getLocation (.getCamera world))) rlm@285: (fix-display world)))))) rlm@300: #+end_src rlm@298: rlm@302: ** ImageMagick / ffmpeg rlm@300: rlm@300: Just a bunch of calls to imagemagick to arrange the data that rlm@300: =test-everything!= produces. rlm@300: rlm@300: #+name: magick-8 rlm@300: #+begin_src clojure rlm@300: (ns cortex.video.magick8 rlm@300: (:import java.io.File) rlm@300: (:use clojure.contrib.shell-out)) rlm@298: rlm@298: (comment rlm@298: ;; list of touch targets rlm@298: 0 middle-11 rlm@298: 1 middle-21 rlm@298: 2 middle-31 rlm@298: 3 pinky-11 rlm@298: 4 pinky-21 rlm@298: 5 pinky-31 rlm@298: 6 pointer-11 rlm@298: 7 pointer-21 rlm@298: 8 pointer-31 rlm@298: 9 ring-11 rlm@298: 10 ring-21 rlm@298: 11 ring-31 rlm@298: 12 thumb-11 rlm@298: 13 thumb-2.0011 rlm@298: rlm@298: rlm@298: ;; list of vision targets rlm@298: 0 :all rlm@298: 1 :green rlm@298: 2 :blue rlm@298: 3 :red rlm@298: rlm@298: ;; list of proprio targets rlm@298: 0 middle-11 -> middle-21 rlm@298: 1 middle-21 -> middle-31 rlm@298: 2 thumb-11 -> thumb-2.0011 rlm@298: 3 pointer-11 -> pointer-21 rlm@298: 4 pointer-21 -> pointer-31 rlm@298: 5 ring-21 -> ring-31 rlm@298: 6 ring-11 -> ring-21 rlm@298: 7 pinky-21 -> pinky-31 rlm@298: 8 pinky-11 -> pinky-21 rlm@298: 9 middle-11 -> palm1 rlm@298: 10 pinky-11 -> palm1 rlm@298: 11 palm1 -> pointer-11 rlm@298: 12 palm1 -> ring-11 rlm@298: 13 palm1 -> thumb-11 rlm@298: rlm@298: rlm@298: ;; list of muscle targets rlm@298: 0 :pointer-2-e rlm@298: 1 :pointer-2-f rlm@298: 2 :thumb-1 rlm@298: 3 :thumb-1 rlm@298: 4 :pointer-1-e rlm@298: 5 :pointer-1-f rlm@298: 6 :thumb-2-e rlm@298: 7 :thumb-2-f rlm@298: 8 :middle-1-e rlm@298: 9 :middle-1-f rlm@298: 10 :pointer-3-f rlm@298: 11 :pointer-3-e rlm@298: 12 :middle-2-e rlm@298: 13 :middle-2-f rlm@298: 14 :middle-3-f rlm@298: 15 :middle-3-e rlm@298: 16 :pinky-2-e rlm@298: 17 :pinky-2-f rlm@298: 18 :pinky-3-f rlm@298: 19 :pinky-3-e rlm@298: 20 :ring-3-e rlm@298: 21 :ring-3-f rlm@298: 22 :ring-2-f rlm@298: 23 :ring-2-e rlm@298: 24 :ring-1-e rlm@298: 25 :ring-1-f rlm@298: 26 :thumb-1-e rlm@298: 27 :thumb-1-f rlm@298: 28 :pinky-1-f rlm@298: 29 :pinky-1-e rlm@298: ) rlm@298: rlm@298: (def base (File. "/home/r/proj/cortex/render/hand")) rlm@298: rlm@298: (defn prepare-muscle [muscle] rlm@298: ["(" muscle "-rotate" "90" "-scale" "15x60!" ")"]) rlm@298: rlm@298: (defn prepare-touch [touch] rlm@298: ["(" touch "-rotate" "180" ")"]) rlm@298: rlm@298: (defn generate-top-finger [tip-flexor tip-extensor tip rlm@298: joint-2-3 rlm@298: mid-flexor mid-extensor mid rlm@298: joint-1-2] rlm@298: ["(" rlm@298: "-size" "113x357" "xc:transparent" rlm@298: (prepare-muscle tip-flexor) "-geometry" "+0+7" "-composite" rlm@298: (prepare-muscle tip-extensor) "-geometry" "+98+7" "-composite" rlm@298: (prepare-touch tip) "-geometry" "+18+0" "-composite" rlm@298: rlm@298: joint-2-3 "-geometry" "+32+79" "-composite" rlm@298: rlm@298: (prepare-muscle mid-flexor) "-geometry" "+19+131" "-composite" rlm@298: (prepare-muscle mid-extensor) "-geometry" "+80+131" "-composite" rlm@298: (prepare-touch mid) "-geometry" "+39+133" "-composite" rlm@298: rlm@298: joint-1-2 "-geometry" "+32+193" "-composite" rlm@298: ")"]) rlm@298: rlm@299: (defn file-names [#^File dir] rlm@299: (map #(.getCanonicalPath %) (next (sort (file-seq dir))))) rlm@299: rlm@299: (defn file-groups [& paths] rlm@299: (apply (partial map list ) rlm@299: (map (comp file-names #(File. base %)) rlm@299: paths))) rlm@299: rlm@299: (defn pinky [] rlm@299: (file-groups rlm@299: "muscle/18" rlm@299: "muscle/19" rlm@299: "touch/5" rlm@299: "proprio/7" rlm@299: rlm@299: "muscle/17" rlm@299: "muscle/16" rlm@299: "touch/4" rlm@299: "proprio/8" rlm@299: rlm@299: "muscle/28" rlm@299: "muscle/29" rlm@299: "touch/3" rlm@299: "proprio/10")) rlm@299: rlm@299: (defn ring [] rlm@299: (file-groups rlm@299: "muscle/21" rlm@299: "muscle/20" rlm@299: "touch/11" rlm@299: "proprio/5" rlm@299: rlm@299: "muscle/22" rlm@299: "muscle/23" rlm@299: "touch/10" rlm@299: "proprio/6" rlm@299: rlm@299: "muscle/25" rlm@299: "muscle/24" rlm@299: "touch/9" rlm@299: "proprio/12")) rlm@299: rlm@299: (defn middle [] rlm@299: (file-groups rlm@299: "muscle/14" rlm@299: "muscle/15" rlm@299: "touch/2" rlm@299: "proprio/1" rlm@299: rlm@300: "muscle/13" rlm@299: "muscle/12" rlm@299: "touch/1" rlm@299: "proprio/0" rlm@299: rlm@300: "muscle/9" rlm@299: "muscle/8" rlm@299: "touch/0" rlm@299: "proprio/9")) rlm@299: rlm@299: (defn pointer [] rlm@299: (file-groups rlm@299: "muscle/10" rlm@299: "muscle/11" rlm@299: "touch/8" rlm@299: "proprio/4" rlm@299: rlm@299: "muscle/1" rlm@299: "muscle/0" rlm@299: "touch/7" rlm@299: "proprio/3" rlm@299: rlm@299: "muscle/5" rlm@299: "muscle/4" rlm@299: "touch/6" rlm@299: "proprio/11")) rlm@299: rlm@299: (defn thumb [] rlm@299: (file-groups rlm@299: "muscle/7" rlm@299: "muscle/6" rlm@299: "touch/13" rlm@299: "proprio/2" rlm@299: rlm@299: "muscle/27" rlm@299: "muscle/26" rlm@299: "muscle/3" rlm@299: "muscle/2" rlm@299: "touch/12" rlm@299: "proprio/13")) rlm@299: rlm@298: (defn generate-finger rlm@298: [tip-flexor tip-extensor tip rlm@298: joint-2-3 rlm@298: mid-flexor mid-extensor mid rlm@298: joint-1-2 rlm@298: base-flexor base-extensor base rlm@298: joint-palm-1] rlm@298: ["(" rlm@298: "-size" "113x357" "xc:transparent" rlm@298: (generate-top-finger rlm@298: tip-flexor tip-extensor tip rlm@298: joint-2-3 rlm@298: mid-flexor mid-extensor mid rlm@298: joint-1-2) "-geometry" "+0+0" "-composite" rlm@298: (prepare-muscle base-flexor) "-geometry" "+19+245" "-composite" rlm@298: (prepare-muscle base-extensor) "-geometry" "+80+245" "-composite" rlm@298: (prepare-touch base) "-geometry" "+39+247" "-composite" rlm@298: joint-palm-1 "-geometry" "+32+307" "-composite" rlm@298: ")"]) rlm@298: rlm@298: (defn generate-thumb rlm@298: [tip-flexor tip-extensor tip rlm@298: joint-1-2 rlm@298: mid-flexor mid-extensor mid-flexor-2 mid-extensor-2 mid rlm@298: joint-palm-1] rlm@298: ["(" rlm@298: "-size" "113x357" "xc:transparent" rlm@298: (generate-top-finger rlm@298: tip-flexor tip-extensor tip rlm@298: joint-1-2 rlm@298: mid-flexor mid-extensor mid rlm@298: joint-palm-1) "-geometry" "+0+0" "-composite" rlm@298: (prepare-muscle mid-flexor-2) "-geometry" "+2+131" "-composite" rlm@298: (prepare-muscle mid-extensor-2) "-geometry" "+100+131" "-composite" rlm@298: ")"]) rlm@298: rlm@298: (defn generate-hand rlm@298: [pinky-pieces rlm@298: ring-pieces rlm@298: middle-pieces rlm@298: pointer-pieces rlm@298: thumb-pieces] rlm@298: ["(" rlm@298: "-size" "688x769" "xc:transparent" rlm@298: (apply generate-finger pinky-pieces) rlm@298: "-geometry" "+0+195" "-composite" rlm@298: (apply generate-finger ring-pieces) rlm@298: "-geometry" "+111+100" "-composite" rlm@298: (apply generate-finger middle-pieces) rlm@298: "-geometry" "+228+0" "-composite" rlm@298: "(" (apply generate-thumb thumb-pieces) "-background" "#00000000" rlm@298: "-rotate" "45" ")" rlm@298: "-geometry" "+300+420" "-composite" rlm@298: (apply generate-finger pointer-pieces) rlm@298: "-geometry" "+350+96" "-composite" rlm@298: ")"]) rlm@298: rlm@298: (defn generate-vision rlm@298: [all green blue red] rlm@298: ["(" rlm@298: "-size" "204x192" "xc:transparent" rlm@298: all "-geometry" "+0+0" "-composite" rlm@298: green "-geometry" "+113+0" "-composite" rlm@298: blue "-geometry" "+0+105" "-composite" rlm@298: red "-geometry" "+113+105" "-composite" rlm@298: ")"]) rlm@298: rlm@298: (def test-muscle (File. base "muscle/0/0000000.png")) rlm@298: (def test-proprio (File. base "proprio/0/0000000.png")) rlm@298: (def test-tip (File. base "touch/2/0000000.png")) rlm@298: (def test-mid (File. base "touch/0/0000000.png")) rlm@298: (def test-vision (File. base "vision/0/0000000.png")) rlm@298: (def test-hearing (File. base "hearing/0/0000000.png")) rlm@298: (def test-main (File. base "main/0000000.png")) rlm@298: rlm@298: (def test-target (File. base "output.png")) rlm@298: rlm@298: (def background (File. base "background.png")) rlm@298: rlm@298: (use 'clojure.contrib.shell-out) rlm@299: rlm@299: (defn vision [] rlm@299: (file-groups rlm@299: "vision/0" rlm@299: "vision/1" rlm@299: "vision/2" rlm@299: "vision/3")) rlm@299: rlm@299: (defn hearing [] rlm@299: (file-names (File. base "hearing/0"))) rlm@299: rlm@299: (defn main [] rlm@299: (file-names (File. base "main"))) rlm@299: rlm@300: (defn targets [dest max] rlm@299: (map rlm@299: (comp #(.getCanonicalPath %) rlm@300: #(File. (str base dest (format "%07d.png" %)))) rlm@300: (range max))) rlm@299: rlm@299: rlm@299: (defn final-image [main [all red green blue] hearing rlm@299: pinky ring middle pointer thumb target] rlm@299: (println target) rlm@299: (apply rlm@298: sh rlm@298: (flatten rlm@298: ["convert" rlm@298: (.getCanonicalPath background) rlm@299: rlm@299: (generate-hand pinky ring middle pointer thumb) rlm@298: "-geometry" "+809+22" "-composite" rlm@298: rlm@299: (generate-vision all red green blue) rlm@298: "-geometry" "+974+599" "-composite" rlm@298: rlm@298: hearing rlm@298: "-geometry" "+784+819" "-composite" rlm@298: rlm@298: main rlm@298: "-geometry" "+78+202" "-composite" rlm@298: rlm@299: target]))) rlm@298: rlm@300: (defn combine-files [] rlm@299: (dorun rlm@299: (pmap final-image rlm@299: (main) rlm@299: (vision) rlm@299: (hearing) rlm@299: (pinky) rlm@299: (ring) rlm@299: (middle) rlm@299: (pointer) rlm@299: (thumb) rlm@300: (targets "/out/" (count (main)))))) rlm@300: rlm@300: (defn subtitles [] rlm@300: (file-names (File. base "subs"))) rlm@300: rlm@300: (defn outs [] rlm@300: (file-names (File. base "out"))) rlm@300: rlm@300: rlm@300: (defn mix-subtitles [] rlm@300: (let [subs (subtitles) rlm@300: targets (targets "/out-subs/" (count subs)) rlm@300: overlay (.getCanonicalPath (File. base "output.png"))] rlm@300: (dorun rlm@300: (pmap rlm@300: (fn [sub target] rlm@300: (sh rlm@300: "convert" rlm@300: overlay rlm@300: sub "-geometry" "+0+0" "-composite" rlm@300: target)) rlm@300: subs targets)))) rlm@300: rlm@300: (defn out-subtitles [] rlm@300: (file-names (File. base "out-subs"))) rlm@300: rlm@300: rlm@300: (defn insert-subtitles [] rlm@300: (let [subtitles (out-subtitles) rlm@300: outs (outs) rlm@300: targets (targets rlm@300: "/final/" rlm@300: (+ (count outs) (count subtitles)))] rlm@300: (dorun rlm@300: (pmap rlm@300: #(sh "cp" %1 %2) rlm@300: (concat subtitles outs) targets)))) rlm@300: rlm@300: (defn generate-final [] rlm@300: (combine-files) rlm@300: (mix-subtitles) rlm@300: (insert-subtitles)) rlm@299: #+end_src rlm@298: rlm@300: #+begin_src sh :results silent rlm@299: cd /home/r/proj/cortex/render/hand rlm@298: rlm@300: sox --ignore-length main.wav main-delayed.wav delay 24 rlm@300: rlm@300: mogrify -resize 755x final/* rlm@300: rlm@300: ffmpeg -r 60 -i final/%07d.png -i main-delayed.wav -b:a 128k \ rlm@299: -b:v 9000k -c:a libvorbis -c:v libtheora hand.ogg rlm@87: #+end_src rlm@83: rlm@301: rlm@301: * Source Listing rlm@301: - [[../src/cortex/test/integration.clj][cortex.test.integration]] rlm@302: - [[../src/cortex/video/magick8.clj][cortex.video.magick8]] rlm@301: - [[../assets/Models/subtitles/hand.blend][subtitles/hand.blend]] rlm@301: #+html: rlm@301: - [[http://hg.bortreb.com ][source-repository]] rlm@301: rlm@301: rlm@78: * COMMENT purgatory rlm@78: #+begin_src clojure rlm@77: (defn bullet-trans* [] rlm@77: (let [obj-a (box 1.5 0.5 0.5 :color ColorRGBA/Red rlm@77: :position (Vector3f. 5 0 0) rlm@77: :mass 90) rlm@77: obj-b (sphere 0.5 :color ColorRGBA/Blue rlm@77: :position (Vector3f. -5 0 0) rlm@77: :mass 0) rlm@77: control-a (.getControl obj-a RigidBodyControl) rlm@77: control-b (.getControl obj-b RigidBodyControl) rlm@77: move-up? (atom nil) rlm@77: move-down? (atom nil) rlm@77: move-left? (atom nil) rlm@77: move-right? (atom nil) rlm@77: roll-left? (atom nil) rlm@77: roll-right? (atom nil) rlm@77: force 100 rlm@77: swivel rlm@77: (.toRotationMatrix rlm@77: (doto (Quaternion.) rlm@77: (.fromAngleAxis (/ Math/PI 2) rlm@77: Vector3f/UNIT_X))) rlm@77: x-move rlm@77: (doto (Matrix3f.) rlm@77: (.fromStartEndVectors Vector3f/UNIT_X rlm@77: (.normalize (Vector3f. 1 1 0)))) rlm@77: rlm@77: timer (atom 0)] rlm@77: (doto rlm@77: (ConeJoint. rlm@77: control-a control-b rlm@77: (Vector3f. -8 0 0) rlm@77: (Vector3f. 2 0 0) rlm@77: ;;swivel swivel rlm@77: ;;Matrix3f/IDENTITY Matrix3f/IDENTITY rlm@77: x-move Matrix3f/IDENTITY rlm@77: ) rlm@77: (.setCollisionBetweenLinkedBodys false) rlm@77: (.setLimit (* 1 (/ Math/PI 4)) ;; twist rlm@77: (* 1 (/ Math/PI 4)) ;; swing span in X-Y plane rlm@77: (* 0 (/ Math/PI 4)))) ;; swing span in Y-Z plane rlm@77: (world (nodify rlm@77: [obj-a obj-b]) rlm@77: (merge standard-debug-controls rlm@77: {"key-r" (fn [_ pressed?] (reset! move-up? pressed?)) rlm@77: "key-t" (fn [_ pressed?] (reset! move-down? pressed?)) rlm@77: "key-f" (fn [_ pressed?] (reset! move-left? pressed?)) rlm@77: "key-g" (fn [_ pressed?] (reset! move-right? pressed?)) rlm@77: "key-v" (fn [_ pressed?] (reset! roll-left? pressed?)) rlm@77: "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))}) rlm@77: rlm@77: (fn [world] rlm@77: (enable-debug world) rlm@77: (set-gravity world Vector3f/ZERO) rlm@77: ) rlm@77: rlm@77: (fn [world _] rlm@77: rlm@77: (if @move-up? rlm@77: (.applyForce control-a rlm@77: (Vector3f. force 0 0) rlm@77: (Vector3f. 0 0 0))) rlm@77: (if @move-down? rlm@77: (.applyForce control-a rlm@77: (Vector3f. (- force) 0 0) rlm@77: (Vector3f. 0 0 0))) rlm@77: (if @move-left? rlm@77: (.applyForce control-a rlm@77: (Vector3f. 0 force 0) rlm@77: (Vector3f. 0 0 0))) rlm@77: (if @move-right? rlm@77: (.applyForce control-a rlm@77: (Vector3f. 0 (- force) 0) rlm@77: (Vector3f. 0 0 0))) rlm@77: rlm@77: (if @roll-left? rlm@77: (.applyForce control-a rlm@77: (Vector3f. 0 0 force) rlm@77: (Vector3f. 0 0 0))) rlm@77: (if @roll-right? rlm@77: (.applyForce control-a rlm@77: (Vector3f. 0 0 (- force)) rlm@77: (Vector3f. 0 0 0))) rlm@77: rlm@77: (if (zero? (rem (swap! timer inc) 100)) rlm@77: (.attachChild rlm@77: (.getRootNode world) rlm@77: (sphere 0.05 :color ColorRGBA/Yellow rlm@77: :physical? false :position rlm@77: (.getWorldTranslation obj-a))))) rlm@77: ) rlm@77: )) rlm@77: rlm@106: (defn test-joint [joint] rlm@106: (let [[origin top bottom floor] (world-setup joint) rlm@106: control (.getControl top RigidBodyControl) rlm@106: move-up? (atom false) rlm@106: move-down? (atom false) rlm@106: move-left? (atom false) rlm@106: move-right? (atom false) rlm@106: roll-left? (atom false) rlm@106: roll-right? (atom false) rlm@106: timer (atom 0)] rlm@106: rlm@106: (world rlm@106: (nodify [top bottom floor origin]) rlm@106: (merge standard-debug-controls rlm@106: {"key-r" (fn [_ pressed?] (reset! move-up? pressed?)) rlm@106: "key-t" (fn [_ pressed?] (reset! move-down? pressed?)) rlm@106: "key-f" (fn [_ pressed?] (reset! move-left? pressed?)) rlm@106: "key-g" (fn [_ pressed?] (reset! move-right? pressed?)) rlm@106: "key-v" (fn [_ pressed?] (reset! roll-left? pressed?)) rlm@106: "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))}) rlm@106: rlm@106: (fn [world] rlm@106: (light-up-everything world) rlm@106: (enable-debug world) rlm@106: (set-gravity world (Vector3f. 0 0 0)) rlm@106: ) rlm@106: rlm@106: (fn [world _] rlm@106: (if (zero? (rem (swap! timer inc) 100)) rlm@106: (do rlm@106: ;; (println-repl @timer) rlm@106: (.attachChild (.getRootNode world) rlm@106: (sphere 0.05 :color ColorRGBA/Yellow rlm@106: :position (.getWorldTranslation top) rlm@106: :physical? false)) rlm@106: (.attachChild (.getRootNode world) rlm@106: (sphere 0.05 :color ColorRGBA/LightGray rlm@106: :position (.getWorldTranslation bottom) rlm@106: :physical? false)))) rlm@106: rlm@106: (if @move-up? rlm@106: (.applyTorque control rlm@106: (.mult (.getPhysicsRotation control) rlm@106: (Vector3f. 0 0 10)))) rlm@106: (if @move-down? rlm@106: (.applyTorque control rlm@106: (.mult (.getPhysicsRotation control) rlm@106: (Vector3f. 0 0 -10)))) rlm@106: (if @move-left? rlm@106: (.applyTorque control rlm@106: (.mult (.getPhysicsRotation control) rlm@106: (Vector3f. 0 10 0)))) rlm@106: (if @move-right? rlm@106: (.applyTorque control rlm@106: (.mult (.getPhysicsRotation control) rlm@106: (Vector3f. 0 -10 0)))) rlm@106: (if @roll-left? rlm@106: (.applyTorque control rlm@106: (.mult (.getPhysicsRotation control) rlm@106: (Vector3f. -1 0 0)))) rlm@106: (if @roll-right? rlm@106: (.applyTorque control rlm@106: (.mult (.getPhysicsRotation control) rlm@106: (Vector3f. 1 0 0)))))))) rlm@99: #+end_src rlm@192: rlm@99: rlm@306: rlm@99: * COMMENT generate source rlm@300: #+begin_src clojure :tangle ../src/cortex/test/integration.clj rlm@192: <> rlm@300: <> rlm@300: #+end_src rlm@300: rlm@300: #+begin_src clojure :tangle ../src/cortex/video/magick8.clj rlm@300: <> rlm@99: #+end_src