feat(anim): add frame-based animations
This commit is contained in:
94
scenes/demo-2.lisp
Normal file
94
scenes/demo-2.lisp
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
(set 'red
|
||||||
|
(material
|
||||||
|
(color 1 0 0)
|
||||||
|
(color 1 0 0)
|
||||||
|
(color 0.5 0 0)
|
||||||
|
50 0.25))
|
||||||
|
(set 'blue
|
||||||
|
(material
|
||||||
|
(color 0 0 1)
|
||||||
|
(color 0 0 1)
|
||||||
|
(color 0 0 0.6)
|
||||||
|
50 0.25))
|
||||||
|
(set 'green
|
||||||
|
(material
|
||||||
|
(color 0 1 0)
|
||||||
|
(color 0 1 0)
|
||||||
|
(color 0 0.6 0)
|
||||||
|
50 0.25))
|
||||||
|
(set 'white
|
||||||
|
(material
|
||||||
|
(color 1 1 1)
|
||||||
|
(color 1 1 1)
|
||||||
|
(color 0.6 0.6 0.6)
|
||||||
|
100 0.5))
|
||||||
|
(set 'black
|
||||||
|
(material
|
||||||
|
(color 0 0 0)
|
||||||
|
(color 0 0 0)
|
||||||
|
(color 0.6 0.6 0.6)
|
||||||
|
100 0.5))
|
||||||
|
|
||||||
|
(set 's1
|
||||||
|
(sphere
|
||||||
|
(point 0 1 0) 1 blue))
|
||||||
|
(set 's2
|
||||||
|
(sphere
|
||||||
|
(point 2 0.5 2) 0.5 green))
|
||||||
|
|
||||||
|
(defun spiral-sphere (i n)
|
||||||
|
(sphere
|
||||||
|
(progn
|
||||||
|
(print "Spiral Sphere at: ")
|
||||||
|
(println (point
|
||||||
|
(* 2 (cos (/ (* i 6.2) n)))
|
||||||
|
0.5
|
||||||
|
(* 2 (sin (/ (* i 6.2) n)))))
|
||||||
|
)
|
||||||
|
0.5 red))
|
||||||
|
|
||||||
|
(defun spiral (scn i n)
|
||||||
|
(if (< i n)
|
||||||
|
(scene-add
|
||||||
|
(spiral scn (+ i 1) n)
|
||||||
|
(spiral-sphere i n))
|
||||||
|
scn))
|
||||||
|
|
||||||
|
(set 'p1
|
||||||
|
(checkerboard
|
||||||
|
(point 0 0 0)
|
||||||
|
(vector 0 1 0)
|
||||||
|
black white 0.5
|
||||||
|
(vector 0.5 0 1)))
|
||||||
|
|
||||||
|
(set 'l1 (light (point 3 10 5) (color 1 1 1)))
|
||||||
|
(set 'l2 (light (point 2 10 5) (color 1 1 1)))
|
||||||
|
|
||||||
|
|
||||||
|
(set 'scn-base (scene
|
||||||
|
(color 0.1 0.1 0.1)
|
||||||
|
'(s1 s2 p1)
|
||||||
|
'(l1 l2)))
|
||||||
|
|
||||||
|
(set 'scn (spiral scn-base 0 10))
|
||||||
|
|
||||||
|
(set 'cam (camera (point 0 3 6) (point 0 0 0) (vector 0 1 0) 40 1920 1080))
|
||||||
|
|
||||||
|
(defun scene-fn (t)
|
||||||
|
scn)
|
||||||
|
|
||||||
|
(defun cam-fn (t c)
|
||||||
|
(let '((pos . (point 0 4 8))
|
||||||
|
(cnt . (point 0 0 0))
|
||||||
|
(to . (point 1 1 1))
|
||||||
|
(up . (vector 0 1 0))
|
||||||
|
(fovy . 40)
|
||||||
|
(pct . (/ t 300.0)))
|
||||||
|
(let '((tpos . (vadd pos (vmul (vsub to pos) pct)))
|
||||||
|
(tfovy . (+ fovy (* 10 pct)))
|
||||||
|
)
|
||||||
|
(camera-reposition c tpos cnt up fovy)
|
||||||
|
)
|
||||||
|
))
|
||||||
|
|
||||||
|
(render-animation cam scene-fn cam-fn 300 1 4 2)
|
||||||
@@ -108,6 +108,38 @@ impl Camera {
|
|||||||
});
|
});
|
||||||
img
|
img
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn reposition(
|
||||||
|
&self,
|
||||||
|
position: Point3,
|
||||||
|
center: Point3,
|
||||||
|
up: Vector3,
|
||||||
|
fovy: Scalar,
|
||||||
|
) -> Camera {
|
||||||
|
Camera::new(position, center, up, fovy, self.width, self.height)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render_animation<SFn: Fn(u32) -> Scene, CFn: Fn(u32, &Camera) -> Camera>(
|
||||||
|
&self,
|
||||||
|
scene_fn: SFn,
|
||||||
|
update_cam: CFn,
|
||||||
|
frames: u32,
|
||||||
|
fps: u32,
|
||||||
|
depth: u32,
|
||||||
|
subp: u32,
|
||||||
|
) {
|
||||||
|
let mut cam = self.to_owned();
|
||||||
|
for t in 0..frames {
|
||||||
|
println!("Rendering frame {}/{}", t + 1, frames);
|
||||||
|
cam = update_cam(t, &cam);
|
||||||
|
let img = cam.render(&scene_fn(t), depth, subp);
|
||||||
|
|
||||||
|
match img.save(format!("frame_{:04}.png", t)) {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(e) => print!("Could not render frame: {}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Camera {
|
impl Display for Camera {
|
||||||
|
|||||||
@@ -148,6 +148,19 @@ pub fn camera(
|
|||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[native_lisp_function(eval)]
|
||||||
|
pub fn camera_reposition(
|
||||||
|
cam: ForeignDataWrapper<Camera>,
|
||||||
|
pos: ForeignDataWrapper<Point3>,
|
||||||
|
cnt: ForeignDataWrapper<Point3>,
|
||||||
|
up: ForeignDataWrapper<Vector3>,
|
||||||
|
fovy: f64,
|
||||||
|
) -> Result<ForeignDataWrapper<Camera>, EvalError> {
|
||||||
|
Ok(ForeignDataWrapper::new(
|
||||||
|
cam.to_owned().reposition(*pos, *cnt, *up, fovy),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
#[native_lisp_function(eval)]
|
#[native_lisp_function(eval)]
|
||||||
pub fn render(
|
pub fn render(
|
||||||
cam: ForeignDataWrapper<Camera>,
|
cam: ForeignDataWrapper<Camera>,
|
||||||
@@ -165,6 +178,41 @@ pub fn render(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn render_animation(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
|
||||||
|
let [cam, scene_fn, update_cam, frames, fps, depth, subp]: [Expression; 7] = expr.try_into()?;
|
||||||
|
|
||||||
|
let cam: ForeignDataWrapper<Camera> = eval(env, cam)?.try_into()?;
|
||||||
|
let frames: i64 = eval(env, frames)?.try_into()?;
|
||||||
|
let fps: i64 = eval(env, fps)?.try_into()?;
|
||||||
|
let depth: i64 = eval(env, depth)?.try_into()?;
|
||||||
|
let subp: i64 = eval(env, subp)?.try_into()?;
|
||||||
|
|
||||||
|
let sfn = |t: u32| -> Scene {
|
||||||
|
let scene_fn_call: Expression = [scene_fn.clone(), (t as i64).into()].into();
|
||||||
|
let scn: ForeignDataWrapper<Scene> = eval(env, scene_fn_call).unwrap().try_into().unwrap();
|
||||||
|
scn.to_owned()
|
||||||
|
};
|
||||||
|
|
||||||
|
let ucm = |t: u32, c: &Camera| -> Camera {
|
||||||
|
let c = ForeignDataWrapper::new(c.to_owned());
|
||||||
|
let update_cam_call: Expression = [update_cam.clone(), (t as i64).into(), c.into()].into();
|
||||||
|
let new_c: ForeignDataWrapper<Camera> =
|
||||||
|
eval(env, update_cam_call).unwrap().try_into().unwrap();
|
||||||
|
new_c.to_owned()
|
||||||
|
};
|
||||||
|
|
||||||
|
cam.render_animation(
|
||||||
|
sfn,
|
||||||
|
ucm,
|
||||||
|
frames as u32,
|
||||||
|
fps as u32,
|
||||||
|
depth as u32,
|
||||||
|
subp as u32,
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(Expression::Nil)
|
||||||
|
}
|
||||||
|
|
||||||
#[native_lisp_function(eval)]
|
#[native_lisp_function(eval)]
|
||||||
pub fn sin(x: f64) -> Result<f64, EvalError> {
|
pub fn sin(x: f64) -> Result<f64, EvalError> {
|
||||||
Ok(x.sin())
|
Ok(x.sin())
|
||||||
@@ -231,12 +279,21 @@ pub fn vsub_pv(
|
|||||||
Ok(ForeignDataWrapper::new(*a - *b))
|
Ok(ForeignDataWrapper::new(*a - *b))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[native_lisp_function]
|
||||||
|
pub fn vsub_pp(
|
||||||
|
a: ForeignDataWrapper<Point3>,
|
||||||
|
b: ForeignDataWrapper<Point3>,
|
||||||
|
) -> Result<ForeignDataWrapper<Vector3>, EvalError> {
|
||||||
|
Ok(ForeignDataWrapper::new(*a - *b))
|
||||||
|
}
|
||||||
|
|
||||||
native_lisp_function_proxy!(
|
native_lisp_function_proxy!(
|
||||||
fname = vsub,
|
fname = vsub,
|
||||||
eval,
|
eval,
|
||||||
dispatch = vsub_vv,
|
dispatch = vsub_vv,
|
||||||
dispatch = vsub_vp,
|
dispatch = vsub_vp,
|
||||||
dispatch = vsub_pv
|
dispatch = vsub_pv,
|
||||||
|
dispatch = vsub_pp
|
||||||
);
|
);
|
||||||
|
|
||||||
#[native_lisp_function]
|
#[native_lisp_function]
|
||||||
@@ -255,7 +312,30 @@ pub fn vmul_sv(
|
|||||||
Ok(ForeignDataWrapper::new(*b * a))
|
Ok(ForeignDataWrapper::new(*b * a))
|
||||||
}
|
}
|
||||||
|
|
||||||
native_lisp_function_proxy!(fname = vmul, eval, dispatch = vmul_vs, dispatch = vmul_sv);
|
#[native_lisp_function]
|
||||||
|
pub fn vmul_ps(
|
||||||
|
a: ForeignDataWrapper<Point3>,
|
||||||
|
b: f64,
|
||||||
|
) -> Result<ForeignDataWrapper<Point3>, EvalError> {
|
||||||
|
Ok(ForeignDataWrapper::new(*a * b))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[native_lisp_function]
|
||||||
|
pub fn vmul_sp(
|
||||||
|
a: f64,
|
||||||
|
b: ForeignDataWrapper<Point3>,
|
||||||
|
) -> Result<ForeignDataWrapper<Point3>, EvalError> {
|
||||||
|
Ok(ForeignDataWrapper::new(*b * a))
|
||||||
|
}
|
||||||
|
|
||||||
|
native_lisp_function_proxy!(
|
||||||
|
fname = vmul,
|
||||||
|
eval,
|
||||||
|
dispatch = vmul_vs,
|
||||||
|
dispatch = vmul_sv,
|
||||||
|
dispatch = vmul_ps,
|
||||||
|
dispatch = vmul_sp
|
||||||
|
);
|
||||||
|
|
||||||
/// Adds the raytracing functions to the given environment layer.
|
/// Adds the raytracing functions to the given environment layer.
|
||||||
pub fn mk_raytrace(layer: &mut EnvironmentLayer) {
|
pub fn mk_raytrace(layer: &mut EnvironmentLayer) {
|
||||||
@@ -273,7 +353,15 @@ pub fn mk_raytrace(layer: &mut EnvironmentLayer) {
|
|||||||
layer.set("scene".to_string(), Expression::Function(scene));
|
layer.set("scene".to_string(), Expression::Function(scene));
|
||||||
layer.set("scene-add".to_string(), Expression::Function(scene_add));
|
layer.set("scene-add".to_string(), Expression::Function(scene_add));
|
||||||
layer.set("camera".to_string(), Expression::Function(camera));
|
layer.set("camera".to_string(), Expression::Function(camera));
|
||||||
|
layer.set(
|
||||||
|
"camera-reposition".to_string(),
|
||||||
|
Expression::Function(camera_reposition),
|
||||||
|
);
|
||||||
layer.set("render".to_string(), Expression::Function(render));
|
layer.set("render".to_string(), Expression::Function(render));
|
||||||
|
layer.set(
|
||||||
|
"render-animation".to_string(),
|
||||||
|
Expression::Function(render_animation),
|
||||||
|
);
|
||||||
layer.set("sin".to_string(), Expression::Function(sin));
|
layer.set("sin".to_string(), Expression::Function(sin));
|
||||||
layer.set("cos".to_string(), Expression::Function(cos));
|
layer.set("cos".to_string(), Expression::Function(cos));
|
||||||
layer.set("vadd".to_string(), Expression::Function(vadd));
|
layer.set("vadd".to_string(), Expression::Function(vadd));
|
||||||
|
|||||||
Reference in New Issue
Block a user