#!/usr/bin/env lua -- -- CS5600 University of Utah -- Charles McGarvey -- mcgarvey@eng.utah.edu -- -- This program that draws a scene multiple times from different camera angles -- and positions. The rasters are saved in the `frames' directory, and if -- ffmpeg is installed, they will also be combined into a video file. The -- camera will make a full rotation along the X and Z axes, around a specified -- point (center), all the while looking at some other point (look). -- This must be called from the same directory where the rasterize program is. local size = {w = 640, h = 480} -- width and height of the viewport local frames = 512 -- number of animation frames local look = {x = 2, y = 1, z = 2} -- the point to look at local center = {x = 0, y = 1, z = 0} -- center of rotation local distance = 4 -- the distance from the center local start = math.pi -- where is the first frame local jobs = 6 -- number of concurrent renderings -- the actual objects of the scene that will be drawn: 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 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 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 c 0 1 0 0 1 0 0 1 0 t 0 -1 0 s 0.6 0.6 0.6 ]] function vec_add(a, b) return {x = a.x + b.x, y = a.y + b.y, z = a.z + b.z} end function vec_scale(v, s) return {x = v.x * s, y = v.y * s, z = v.z * s} end local fmt = string.format local write = function(...) io.write(fmt(...)) end function render(i, v) while i and v do local filename = fmt("frames/anim%04d.bmp", i) local command = fmt("./rasterize -o %s >/dev/null", filename) local out = io.popen(command, "w") write("\27[80D\27[2Kframe\t %4d / %d", i + 1, frames) out:write(fmt([[ U3 %d %d %f %f %f %f %f %f 0 1 0 1.57 %f 0.1 1000 %s X ]], size.w, size.h, v.x, v.y, v.z, look.x, look.y, look.z, size.w/size.h, scene)) i, v = coroutine.yield() out:close() end end print("Animating scene...") local threads = {} for i = 1,jobs do table.insert(threads, coroutine.wrap(render)) end os.execute("rm -rf frames && mkdir frames >/dev/null 2>&1") for i = 0,(frames-1) do local t = start + 2 * math.pi * i / frames local v = { x = math.cos(t), y = 0, z = math.sin(t), } v = vec_add(vec_scale(v, distance), center) threads[1 + (i % jobs)](i, v) 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 print("Animation written to scene.avi.") end