use illuminator::prelude::*;
use num_traits::Zero;
use rayon::prelude::*;
pub fn bvh_example(save_path: Option<&str>) {
println!("Running BVH example...");
let n = 1024;
let node_limit = 65;
let mut bvh = BVH::new(n);
for i in (0..n).step_by(150).skip(1).take(6) {
let cnt = Vec3f::vec([i as f32 + 0.5; 3]);
bvh.push(Sphere::new(cnt, 100.));
}
bvh.build(node_limit, true);
let (w, h) = (512, 512);
let mut img: Image<Rgb<u8>> = Image::new(w, h);
img.data_mut()
.par_iter_mut()
.enumerate()
.for_each(|(i, pix)| {
let (iw, ih) = (i % w, i / w);
let (x, y) = (
iw as f32 * n as f32 / (w - 1) as f32,
(h - ih) as f32 * n as f32 / (h - 1) as f32,
);
let org = Vec3f::vec([x - 0.5, y - 0.5, 1025.]);
let dir = Vec3f::vec([0., 0., -1.]);
let ray = Ray::new(org, dir);
if let Some(hit) = bvh.raycast(&ray) {
let t = (hit.t * 255. / 1024.) as u8;
*pix = Rgb([t; 3]);
}
});
let save_path = &path_or_default(save_path, "bvh_example.png");
let rgbimg = RgbImage::from(img);
rgbimg
.save(save_path)
.expect("Failed to save BVH example image");
println!("BVH example completed! Output saved to {save_path}");
}
pub fn gaussian_splatting_example(ply_path: Option<&str>, (w, h): (usize, usize)) {
use illuminator::{prelude::*, splat::render::SplatsRenderer};
use image::RgbImage;
use std::path::Path;
use std::time::Instant;
println!("Running Gaussian Splatting tracing example...");
let read_path = &path_or_default(ply_path, "point_cloud.ply");
let rdr = SplatsRenderer::from_ply(read_path);
if rdr.is_err() {
println!("Read file at {read_path} Error.");
return;
}
let rdr = rdr.unwrap();
let high_res = w * h > 256 * 256;
if high_res {
print!("Resolution is larger than 256x256. This may take a while. Continue? (y/n): ");
std::io::Write::flush(&mut std::io::stdout()).unwrap();
let mut input = String::new();
std::io::stdin().read_line(&mut input).unwrap();
if !input.trim().to_lowercase().starts_with('y') {
println!("Gaussian splatting example cancelled.");
return;
}
}
println!("Trace resolution: {w}x{h}");
let cam_pos = Vec3f::vec([-3., 0., 0.]);
let forward = Vec3f::zero() - cam_pos;
let cam = Camera::new(cam_pos, forward, 60., 0.25, 4.);
let start = Instant::now();
let img = rdr.render(&cam, (w, h));
println!("Rendering used {:.2}s", start.elapsed().as_secs_f32());
let fname = Path::new(read_path)
.with_extension("png")
.to_string_lossy()
.into_owned();
let rgbimg = RgbImage::from(img);
rgbimg
.save(fname)
.expect("Failed to save Gaussian Splatting example image");
}
fn path_or_default(path: Option<&str>, default: &str) -> String {
let default_path = if std::path::Path::new("Cargo.toml").exists() {
format!("./target/{default}")
} else {
format!("./{default}")
};
path.unwrap_or(&default_path).to_string()
}