use rand::Rng; use ray_tracing_core::{light::AreaLight, prelude::*, scene::Scene}; use ray_tracing_material::{ microfacet::{BeckmannDistribution, Microfacet}, oren_nayar::OrenNayar, }; use std::cell::OnceCell; use crate::{ acceleration_structure::{ triangle_bvh::{Triangle, TriangleBVH}, ASMaterial, AccelerationStructureScene, }, parse_obj::ObjData, }; use super::ExampleScene; pub struct StanfordDragon { scene: OnceCell, R>>, } impl StanfordDragon { pub fn new() -> Self { Self { scene: OnceCell::new(), } } } impl ExampleScene for StanfordDragon { 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, 0)) .collect::>(); let color = Color::new(0.2, 0.2, 0.9); let materials = vec![ ASMaterial::new_material(Microfacet::new(BeckmannDistribution::new(0.01), color)), ASMaterial::new_material(OrenNayar::new(0.5, Color::new(0.8, 0.8, 0.8))), ASMaterial::new_material(OrenNayar::new(0.5, Color::new(0.9, 0.0, 0.0))), ASMaterial::new_material(OrenNayar::new(0.5, Color::new(0.0, 0.9, 0.0))), ASMaterial::new_light(AreaLight::new(Color::white() * 30.0)), ]; let mut vertices = obj.vertices; for v in &mut vertices { *v = Pos3::new(v.x(), v.z() + 60.0, -v.y()); } 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], 1), Triangle::new([1 + offset, 3 + offset, 2 + offset], 1), Triangle::new([offset, 4 + offset, 1 + offset], 1), Triangle::new([1 + offset, 4 + offset, 5 + offset], 1), Triangle::new([2 + offset, 3 + offset, 6 + offset], 1), Triangle::new([3 + offset, 7 + offset, 6 + offset], 1), Triangle::new([offset, 2 + offset, 4 + offset], 2), Triangle::new([6 + offset, 4 + offset, 2 + offset], 2), Triangle::new([1 + offset, 5 + offset, 3 + offset], 3), Triangle::new([7 + offset, 3 + offset, 5 + offset], 3), Triangle::new([8 + offset, 10 + offset, 9 + offset], 4), Triangle::new([11 + offset, 9 + offset, 10 + offset], 4), ]); let lights: Vec<_> = triangles .iter() .filter(|f| materials[f.data as usize].light.is_some()) .map(|t| { ( t.data as usize, [ vertices[t.vertices[0] as usize], vertices[t.vertices[1] as usize], vertices[t.vertices[2] as usize], ], ) }) .collect(); let a = TriangleBVH::new(vertices, triangles); AccelerationStructureScene::new(a, materials.into(), lights) }); let n: AccelerationStructureScene<_, _> = s.clone(); Box::new(n) } 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, 60.0, 0.0) } fn get_camera_up(&self) -> Dir3 { Dir3::up() } fn get_horizontal_fov(&self) -> Float { Float::to_radians(90.0) } }