diff --git a/ray-tracing-scene/src/examples/mod.rs b/ray-tracing-scene/src/examples/mod.rs index f7b0dcd..de7b5ed 100644 --- a/ray-tracing-scene/src/examples/mod.rs +++ b/ray-tracing-scene/src/examples/mod.rs @@ -52,12 +52,18 @@ pub fn example_scenes() -> HashMap<&'static str, Box { + scene: OnceCell>, +} + +impl Presentation { + pub fn new() -> Self { + Self { + scene: OnceCell::new(), + } + } +} + +impl ExampleScene for Presentation { + fn get_scene(&self) -> Box + Sync> { + let s = self.scene.get_or_init(|| { + let obj = ObjData::new("ray-tracing-scene/obj/stanford_dragon.obj").unwrap(); + + let mut triangles = obj + .triangle_faces() + .map(|t| Triangle::new(t.v, 4)) + .collect::>(); + + let materials = vec![ + BVHMaterial::new_material(OrenNayar::new(0.5, Color::new(0.8, 0.8, 0.8))), + BVHMaterial::new_material(OrenNayar::new(0.5, Color::new(0.9, 0.2, 0.2))), + BVHMaterial::new_material(OrenNayar::new(0.5, Color::new(0.2, 0.9, 0.2))), + BVHMaterial::new_light(AreaLight::new(Color::white() * 30.0)), + BVHMaterial::new_material(Iridescent::new(250.0, 250.0, 1.0, 1.5, 20)), + BVHMaterial::new_material(Iridescent::new(0.9 * 988.0, 0.1 * 988.0, 1.0, 1.5, 20)), + BVHMaterial::new_material(Iridescent::new(0.1 * 500.0, 0.9 * 500.0, 1.0, 1.5, 20)), + ]; + + let dragon_vertices = obj.vertices.len(); + let dragon_triangles = triangles.len(); + + let mut vertices = obj.vertices; + for v in &mut vertices { + *v = Pos3::new(v.x() * 0.3, (v.z() + 60.0) * 0.3, -v.y() * 0.3); + } + + // second dragon + let offset = vertices.len() as u32; + for i in 0..dragon_vertices { + vertices.push(vertices[i] + Dir3::new(50.0, 0.0, 25.0)); + } + + for i in 0..dragon_triangles { + triangles.push(Triangle::new( + [ + triangles[i].vertices[0] + offset, + triangles[i].vertices[1] + offset, + triangles[i].vertices[2] + offset, + ], + 5, + )); + } + + // third dragon + let offset = vertices.len() as u32; + for i in 0..dragon_vertices { + vertices.push(vertices[i] + Dir3::new(-50.0, 0.0, -25.0)); + } + + for i in 0..dragon_triangles { + triangles.push(Triangle::new( + [ + triangles[i].vertices[0] + offset, + triangles[i].vertices[1] + offset, + triangles[i].vertices[2] + offset, + ], + 6, + )); + } + + // cornel box + let side_length = 400.0; + let light_size = 150.0; + let light_offset = 0.01; + let offset = vertices.len() as u32; + vertices.extend_from_slice(&[ + Pos3::new(side_length, 2.0 * side_length, side_length), + Pos3::new(side_length, 2.0 * side_length, -side_length), + Pos3::new(side_length, 0.0, side_length), + Pos3::new(side_length, 0.0, -side_length), + Pos3::new(-side_length, 2.0 * side_length, side_length), + Pos3::new(-side_length, 2.0 * side_length, -side_length), + Pos3::new(-side_length, 0.0, side_length), + Pos3::new(-side_length, 0.0, -side_length), + Pos3::new(light_size, 2.0 * side_length - light_offset, light_size), + Pos3::new(light_size, 2.0 * side_length - light_offset, -light_size), + Pos3::new(-light_size, 2.0 * side_length - light_offset, light_size), + Pos3::new(-light_size, 2.0 * side_length - light_offset, -light_size), + ]); + + triangles.extend_from_slice(&[ + Triangle::new([offset, 1 + offset, 2 + offset], 0), + Triangle::new([1 + offset, 3 + offset, 2 + offset], 0), + Triangle::new([offset, 4 + offset, 1 + offset], 0), + Triangle::new([1 + offset, 4 + offset, 5 + offset], 0), + Triangle::new([2 + offset, 3 + offset, 6 + offset], 0), + Triangle::new([3 + offset, 7 + offset, 6 + offset], 0), + Triangle::new([offset, 2 + offset, 4 + offset], 1), + Triangle::new([6 + offset, 4 + offset, 2 + offset], 1), + Triangle::new([1 + offset, 5 + offset, 3 + offset], 2), + Triangle::new([7 + offset, 3 + offset, 5 + offset], 2), + Triangle::new([8 + offset, 10 + offset, 9 + offset], 3), + Triangle::new([11 + offset, 9 + offset, 10 + offset], 3), + ]); + + TriangleBVH::new(vertices, triangles, materials) + }); + + Box::new(s.clone()) + } + + fn get_camera_pos(&self) -> Pos3 { + Pos3::new(-150.0, 160.0, 250.0) + } + + fn get_camera_look_at(&self) -> Pos3 { + Pos3::new(0.0, 15.0, 0.0) + } + + fn get_camera_up(&self) -> Dir3 { + Dir3::up() + } + + fn get_horizontal_fov(&self) -> Float { + Float::to_radians(90.0) + } +} diff --git a/ray-tracing-scene/src/triangle_bvh.rs b/ray-tracing-scene/src/triangle_bvh.rs index 0e6e922..3b61f30 100644 --- a/ray-tracing-scene/src/triangle_bvh.rs +++ b/ray-tracing-scene/src/triangle_bvh.rs @@ -84,8 +84,8 @@ enum Node { #[derive(Debug, Clone, Copy)] pub struct Triangle { - vertices: [Index; 3], - material: Index, + pub vertices: [Index; 3], + pub material: Index, } impl Triangle {