X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Frasterize;a=blobdiff_plain;f=animate.lua;h=616c717f4eb51ff396a343b5a2759ef90faf35d8;hp=fb4ca825ee0b764fb0c02ef699e7167a8166631c;hb=07083c8dfbbd4fe48e84d86ce8d7e44e0719b84a;hpb=143da66e7f625b7f195a115b9740a748ee003534 diff --git a/animate.lua b/animate.lua index fb4ca82..616c717 100755 --- a/animate.lua +++ b/animate.lua @@ -10,9 +10,7 @@ -- The rasters are saved in the `frames' directory, and if ffmpeg is -- installed, the frames will also be combined into a video file. This script -- must be called from the same directory where the rasterize program is. - --- Set the width and height of the viewport. -local size = {w = 640, h = 480} +-- The CACHE_GEOMETRY option is also recommended to improve performance. -- Set the number of frames to be rendered for the animation. local frames = 360 @@ -20,8 +18,8 @@ local frames = 360 -- Define the code to calculate where the camera is, in world coordinates. local eye = function(frame) -- just rotate around the center of the scene on the XZ plane - local center = vec_new(0, 1, 0) - local distance = 4 + local center = vec_new(0, 0.4, 0) + local distance = 0.7 local start = math.pi local t = start + 2 * math.pi * frame / frames local v = vec_new(math.cos(t), 0, math.sin(t)) @@ -30,50 +28,44 @@ end -- Define the code to calculate where the focal point of the scene is. local look = function(frame) - -- keep the camera focused on the buddha - return vec_new(2, 1, 2) + -- keep the camera focused at the center + return vec_new(0, 0, 0) end -- Define the actual objects of the scene that will be rendered, in the -- extended u3d format. local scene = [[ -L 0 1000000 0 1 1 1 1 1 1 -L 0 0 1000000 1 1 1 1 1 1 -g triangle.raw -c 0.9 0.8 0.7 0.6 0.5 0.4 0.3 0.2 0.1 -t 2 0 -2 -s 1 1 1 -g dragon.raw -M 0.3 0.3 0.3 5 -c 0.7 0.3 0.2 0.8 0.2 0.1 0.9 0.2 0.2 -t -2 -1 -2 -s 2 2 2 -g budda.raw -c 0.1 0.2 0.7 0.1 0.3 0.9 0.2 0.1 0.8 -t 2 -1.5 2 -s 10 10 10 -g bunny.raw -M 0.2 0.2 0.2 1 -c 0.9 0.8 0.9 0.8 0.7 0.9 0.9 0.8 0.7 -t -2 -1 2 -s 10 10 10 -g teapot2.raw -M 1 1 1 128 -c 0 1 0 0 1 0 0 1 0 -t 0 -1 0 -s 0.6 0.6 0.6 +l -14687.0 7986.0 8976.0 1.0 1.0 1.0 +g checker.obj +c 1.0 0.6 0.6 0.6 +m checker.ppm +r -1.57 1.0 0.0 0.0 +p 1.0 1.0 1.0 100.0 +g teapot.raw +c 0.9 0.7 0.1 0.2 +p 1.0 1.0 1.0 60.0 +t 0.0 0.1 0.0 +s 0.004 0.004 0.004 ]] +-- Set the number of samples for supersampling. If this is set to a value +-- of two or greater, each frame will be rendered larger by the factor +-- specified. ImageMagick is used to scale the frames back down to size; +-- if ImageMagick is not installed, this script will exit with error 1. +local supersample = 2 + +-- Set the width and height of the viewport. +local size = {w = 640, h = 480} + -- Set the number of concurrent renderings (for multi-core machines). local jobs = 6 +-- Set the options to be passed directly to ffmpeg. +local ffmpeg_opts = "-b 1024k" -- end of configuration --------------------------------------------------------------------------- -local fmt = string.format -local write = function(...) io.write(fmt(...)) end - function vec_new(x, y, z) return {x = x, y = y, z = z} end @@ -86,44 +78,72 @@ function vec_scale(v, s) return vec_new(v.x * s, v.y * s, v.z * s) end +local fmt = string.format +local write = function(...) io.write(fmt(...)) io.flush() end +local run = function(...) return os.execute(fmt(...)) end + function render(i) while i do + local w, h = size.w, size.h + if 1 < supersample then + w = w * supersample + h = h * supersample + end local filename = fmt("frames/anim%04d.bmp", i) local command = fmt("./rasterize -o %s >/dev/null", filename) local out = io.popen(command, "w") local e = eye(i) local l = look(i) - write("\27[80D\27[2Kframe\t %4d / %d", i + 1, frames) + write("\27[80D\27[2Kframe\t %4d / %d", i, frames) out:write(fmt([[ -U3 +U4 %d %d %f %f %f %f %f %f 0 1 0 1.57 %f 0.1 1000 +1.0 1.0 1.0 %s X -]], size.w, size.h, e.x, e.y, e.z, l.x, l.y, l.z, size.w/size.h, scene)) +]], w, h, e.x, e.y, e.z, l.x, l.y, l.z, size.w/size.h, scene)) i = coroutine.yield() out:close() + if 1 < supersample and + run("convert %s -scale %dx%d %s", filename, size.w, size.h, filename) ~= 0 then + print() + os.exit(1) + end + end +end + +function renderings() + local t = {} + for i = 1,jobs do + table.insert(t, coroutine.wrap(render)) + end + local iterations = frames + jobs + local frame = 0 + return function() + frame = frame + 1 + if frame <= iterations then + local i = frame + if frames < i then i = null end + return t[1 + frame % jobs], i + end end end print("Animating scene...") -local threads = {} -for i = 1,jobs do - table.insert(threads, coroutine.wrap(render)) -end +run("rm -rf frames && mkdir frames >/dev/null 2>&1") +for render,frame in renderings() do render(frame) end -os.execute("rm -rf frames && mkdir frames >/dev/null 2>&1") -for i = 0,(frames-1) do - threads[1 + (i % jobs)](i) -end -for _,thread in ipairs(threads) do thread(null) end print() -if os.execute("ffmpeg -i frames/anim%04d.bmp -b 1024k -y -an scene.avi") == 0 then +if run("ffmpeg -i frames/anim%%04d.bmp %s -y -an scene.avi", ffmpeg_opts) == 0 then print("Animation written to scene.avi.") +else + print("The animation could not be created. Is ffmpeg installed?") + os.exit(2) end