use std::{env, time::Duration};
use nalgebra::{Vector3, Rotation3, Matrix3};
use clay::{
prelude::*,
shape::*,
material::*,
object::*,
scene::{TargetListScene, GradientBackground as GradBg},
view::ProjectionView,
filter::*,
process::{create_renderer, create_postproc},
shape_select, material_select, material_combine,
};
use clay_viewer::{Window, Motion};
use clay_utils::{args, FrameCounter};
shape_select!(MyShape {
P(TP=Parallelepiped),
S(TS=Ellipsoid),
});
material_combine!(Glossy {
reflect: Reflective,
diffuse: Colored<Diffuse>,
});
material_combine!(Glowing {
reflect: Reflective,
diffuse: Colored<Luminous>,
});
material_select!(MyMaterial {
D(TD=Colored<Diffuse>),
G(TG=Glossy),
F(TF=Glowing),
L(TL=Colored<Luminous>),
});
type MyObject = Covered<MyShape, MyMaterial>;
type MyScene = TargetListScene<MyObject, Sphere, GradBg>;
type MyView = ProjectionView;
fn main() -> clay::Result<()> {
let context = args::parse(env::args())?;
let dims = (1280, 800);
let mut scene = TargetListScene::new(GradBg::new(
Vector3::new(0.1, 0.1, 0.3), Vector3::new(0.0, 0.0, 0.0),
Vector3::new(0.0, 0.0, 1.0),
));
scene.add(MyShape::from(Parallelepiped::new(
Matrix3::from_diagonal(&Vector3::new(1000.0, 1000.0, 0.5)),
Vector3::new(0.0, 0.0, -0.5),
)).cover(MyMaterial::from(Diffuse {}.color_with(Vector3::new(0.9, 0.9, 0.9)))));
let mut rocks = Vec::new();
rocks.push((30.0, (-60.0, 30.0), 3e3*Vector3::new(1.0, 0.4, 0.4)));
rocks.push((100.0, (-200.0,-0.0), 2e3*Vector3::new(0.4, 0.4, 1.0)));
rocks.push((15.0, (-30.0,-30.0), 3e3*Vector3::new(0.4, 1.0, 0.4)));
let rot = Rotation3::rotation_between(
&Vector3::new(1.0, 1.0, 1.0),
&Vector3::new(0.0, 0.0, 1.0),
).unwrap().matrix().clone();
for (size, pos, color) in rocks {
scene.add(MyShape::from(Parallelepiped::new(
size*3.0f64.sqrt()/2.0*rot.clone(),
Vector3::new(pos.0, pos.1, -0.5*size),
)).cover(MyMaterial::from(Diffuse {}.color_with(Vector3::new(0.9, 0.9, 0.9)))));
let tsize = 0.025*size;
scene.add_targeted(MyShape::from(Parallelepiped::new(
tsize*3.0f64.sqrt()/2.0*rot*Matrix3::from_diagonal(&Vector3::new(0.5, 0.5, 2.0)),
Vector3::new(pos.0, pos.1, 1.2*size + 2.0*tsize),
)).cover(MyMaterial::from(Luminous {}.color_with(color))));
}
scene.add(MyShape::from(Ellipsoid::new(
0.25*Matrix3::identity(),
Vector3::new(1.0, 0.0, 0.25),
)).cover(MyMaterial::from(Luminous {}.color_with(1e1*Vector3::new(0.2, 1.0, 0.2)))));
scene.add(MyShape::from(Ellipsoid::new(
0.4*Matrix3::identity(),
Vector3::new(0.0, 1.0, 0.4),
)).cover(MyMaterial::from(Glossy::new(
(0.2, Reflective {}),
(0.8, Diffuse {}.color_with(Vector3::new(0.9, 0.9, 0.9))),
))));
scene.add(MyShape::from(Parallelepiped::new(
0.5*Matrix3::identity(),
Vector3::new(-1.0, 0.0, 0.5),
)).cover(MyMaterial::from(Glossy::new(
(0.5, Reflective {}),
(0.5, Diffuse {}.color_with(Vector3::new(0.9, 0.9, 0.9))),
))));
let view = ProjectionView::new(
Vector3::new(2.0, 0.0, 1.0),
Rotation3::face_towards(&-Vector3::new(-1.0, 0.0, 0.0), &Vector3::z_axis()),
);
let mut renderer = create_renderer::<MyScene, MyView>().build(dims, scene, view)?;
let (mut worker, _) = renderer.create_worker(&context)?;
let (mut postproc, _) = create_postproc().collect()?
.build(&context, dims, LogFilter::new(-2.0, 1.0))?;
let mut window = Window::new(dims)?;
window.set_capture_mode(true);
let mut motion = Motion::new(renderer.view.pos, renderer.view.ori.clone());
let mut fcnt = FrameCounter::new_with_log(Duration::from_secs(2));
while !window.poll_with_handler(&mut motion)? {
let n = worker.run_for(Duration::from_millis(20))?;
postproc.process_one(&worker.data().buffer())?;
postproc.make_image()?;
window.draw(&postproc.image())?;
let dt = window.step_frame();
if motion.was_updated() {
worker.data_mut().buffer_mut().clear()?;
motion.step(dt);
renderer.view.update(motion.pos(), motion.ori());
renderer.view.fov = motion.fov;
renderer.update_data(&context, worker.data_mut())?;
}
fcnt.step_frame(dt, n);
}
Ok(())
}