From c33adf9ebaa0cf9bd8c9b3e8ec98a0d3726263ff Mon Sep 17 00:00:00 2001 From: fremag Date: Mon, 19 Feb 2024 22:17:33 +0100 Subject: [PATCH] Chap 15: triangles (smooth triangles) --- img/teapot_smooth.png | Bin 0 -> 45248 bytes ray-tracer-cli/src/main.rs | 4 +- ray-tracer-cli/src/scenes/mod.rs | 1 + .../src/scenes/smooth_teapot_scene.rs | 43 +++++++++++++ ray-tracer-lib/src/obj_reader.rs | 60 ++++++++++++++---- ray-tracer-lib/src/shapes/smooth_triangle.rs | 4 -- ray-tracer-lib/src/tests/obj_reader_tests.rs | 47 +++++++++++++- 7 files changed, 142 insertions(+), 17 deletions(-) create mode 100644 img/teapot_smooth.png create mode 100644 ray-tracer-cli/src/scenes/smooth_teapot_scene.rs diff --git a/img/teapot_smooth.png b/img/teapot_smooth.png new file mode 100644 index 0000000000000000000000000000000000000000..3ddd9d38884860330c8f9d6d0d036131666b90a0 GIT binary patch literal 45248 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

!P9YNJWxi3P%fG!vn`h+pfMdK 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 World { + println!("{}", env::current_dir().unwrap().display()); + let file_path = r"./obj/teapot.obj"; + let file = File::open(file_path).unwrap(); + + let mut obj_reader = ObjReader::new(file); + obj_reader.read(); + + let teapot = obj_reader.smooth_models; + let teapot_model= teapot.get("Teapot001").unwrap(); + let mut obj_teapot = Object::new_smooth_triangle(teapot_model.clone()); + obj_teapot.set_transformation(&rotation_y(-PI/4.0) * &(&rotation_x(-PI/2.0)*&rotation_z(PI/2.0))); + let mut world = World::new(); + world.objects.push(obj_teapot); + let lights = vec!(PointLight::new(point(-100.0, 100.0, -100.0), Color::new(1.0, 1.0, 1.0))); + world.set_lights(lights); + world + } + + fn get_camera(&self, h_size: usize, v_size: usize) -> Camera { + let mut camera = Camera::new(h_size, v_size, PI / 3.0); + camera.set_transform(view_transform(point(-15.0, 15.0, -30.0), + point(0.0, 1.0, 0.0), + vector(0.0, 1.0, 0.0))); + camera + } +} \ No newline at end of file diff --git a/ray-tracer-lib/src/obj_reader.rs b/ray-tracer-lib/src/obj_reader.rs index f82ca90..ff4923e 100644 --- a/ray-tracer-lib/src/obj_reader.rs +++ b/ray-tracer-lib/src/obj_reader.rs @@ -1,19 +1,28 @@ use std::collections::HashMap; use std::io::{BufRead, BufReader}; use crate::core::math::Float; -use crate::core::tuple::{point, Tuple}; +use crate::core::tuple::{point, Tuple, vector}; +use crate::shapes::smooth_triangle::SmoothTriangle; +use crate::shapes::smooth_triangle_model::SmoothTriangleModel; use crate::shapes::triangle::Triangle; use crate::shapes::triangle_model::TriangleModel; pub struct ObjReader { pub source : T, pub vertices : Vec, + pub normals : Vec, pub triangles : Vec, + pub smooth_triangles : Vec, pub models: HashMap, + pub smooth_models: HashMap, } impl ObjReader where T: std::io::Read { - pub fn new(source : T) -> Self { Self{source, vertices: vec![], triangles: vec![], models: HashMap::new() } } + pub fn new(source : T) -> Self { + Self{source, vertices: vec![], normals: vec![], + triangles: vec![], smooth_triangles: vec![], + models: HashMap::new(), smooth_models: HashMap::new(), + } } pub fn read(&mut self) { let reader = BufReader::new(&mut self.source); @@ -30,6 +39,13 @@ impl ObjReader where T: std::io::Read { let z = items[3].parse::().unwrap(); self.vertices.push(point(x, y, z)); } + if line.starts_with("vn ") { + let items : Vec<&str> = line.split(' ').collect(); + let x = items[1].parse::().unwrap(); + let y = items[2].parse::().unwrap(); + let z = items[3].parse::().unwrap(); + self.normals.push(vector(x, y, z)); + } if line.starts_with("f ") { let items: Vec<&str> = line.split(' ').filter(|item| ! item.is_empty()).collect(); for i in 1..items.len()-2 { @@ -42,24 +58,46 @@ impl ObjReader where T: std::io::Read { let v1 = &self.vertices[i1]; let v2 = &self.vertices[i2]; let v3 = &self.vertices[i3]; - let triangle = Triangle::new(*v1, *v2, *v3); - self.triangles.push(triangle); + if s1.len() == 3 { + let i_n1 = s1[2].parse::().unwrap() - 1; + let i_n2 = s2[2].parse::().unwrap() - 1; + let i_n3 = s3[2].parse::().unwrap() - 1; + let n1 = self.normals[i_n1]; + let n2 = self.normals[i_n2]; + let n3 = self.normals[i_n3]; + let smooth_triangle = SmoothTriangle::new(*v1, *v2, *v3, n1, n2, n3); + self.smooth_triangles.push(smooth_triangle); + } else { + let triangle = Triangle::new(*v1, *v2, *v3); + self.triangles.push(triangle); + } } } if line.starts_with("g ") { let items: Vec<&str> = line.split(' ').collect(); let name = String::from(items[1]); - let triangle_model = TriangleModel::new(self.triangles.clone()); - self.models.insert(current_name.to_string(), triangle_model); - + if self.triangles.len() > 0 { + let triangle_model = TriangleModel::new(self.triangles.clone()); + self.models.insert(current_name.to_string(), triangle_model); + self.triangles = vec![]; + } else { + let smooth_triangle_model = SmoothTriangleModel::new(self.smooth_triangles.clone()); + self.smooth_models.insert(current_name.to_string(), smooth_triangle_model); + self.smooth_triangles = vec![]; + } current_name = name; - self.triangles = vec![]; } } } } - let triangle_model = TriangleModel::new(self.triangles.clone()); - self.models.insert(current_name.to_string(), triangle_model); - self.triangles = vec![]; + if self.triangles.len() > 0 { + let triangle_model = TriangleModel::new(self.triangles.clone()); + self.models.insert(current_name.to_string(), triangle_model); + self.triangles = vec![]; + } else { + let smooth_triangle_model = SmoothTriangleModel::new(self.smooth_triangles.clone()); + self.smooth_models.insert(current_name.to_string(), smooth_triangle_model); + self.smooth_triangles = vec![]; + } } } \ No newline at end of file diff --git a/ray-tracer-lib/src/shapes/smooth_triangle.rs b/ray-tracer-lib/src/shapes/smooth_triangle.rs index 6359a1f..7bf04ff 100644 --- a/ray-tracer-lib/src/shapes/smooth_triangle.rs +++ b/ray-tracer-lib/src/shapes/smooth_triangle.rs @@ -23,10 +23,6 @@ impl SmoothTriangle { let b= self.n3 * intersection.v; let c = self.n1 * (1.0 - intersection.u - intersection.v); let n = a+b+c; - print!("{} {} {}", a.x, a.y, a.z); - print!("{} {} {}", b.x, b.y, b.z); - print!("{} {} {}", c.x, c.y, c.z); - print!("{} {} {}", n.x, n.y, n.z); n.normalize() } diff --git a/ray-tracer-lib/src/tests/obj_reader_tests.rs b/ray-tracer-lib/src/tests/obj_reader_tests.rs index c404a97..668b067 100644 --- a/ray-tracer-lib/src/tests/obj_reader_tests.rs +++ b/ray-tracer-lib/src/tests/obj_reader_tests.rs @@ -1,6 +1,6 @@ #[cfg(test)] mod tests { - use crate::core::tuple::point; + use crate::core::tuple::{point, vector}; use crate::obj_reader::ObjReader; #[test] @@ -113,4 +113,49 @@ f 1 3 4 assert_eq!(t2.p2, obj_reader.vertices[2]); assert_eq!(t2.p3, obj_reader.vertices[3]); } + + #[test] + fn vertex_normal_records_test() { + let str = " +vn 0 0 1 +vn 0.707 0 -0.707 +vn 1 2 3 +"; + let mut obj_reader = ObjReader::new(str.as_bytes()); + obj_reader.read(); + assert_eq!(obj_reader.normals[0], vector(0.0, 0.0, 1.0)); + assert_eq!(obj_reader.normals[1], vector(0.707, 0.0, -0.707)); + assert_eq!(obj_reader.normals[2], vector(1.0, 2.0, 3.0)); + } + + #[test] + fn faces_with_normals_test() { + let str = " +v 0 1 0 +v -1 0 0 +v 1 0 0 +vn -1 0 0 +vn 1 0 0 +vn 0 1 0 +f 1//3 2//1 3//2 +f 1/0/3 2/102/1 3/14/2 +"; + + let mut obj_reader = ObjReader::new(str.as_bytes()); + obj_reader.read(); + let t1 = &obj_reader.smooth_triangles[0]; + assert_eq!(t1.triangle.p1, point(0.0, 1.0, 0.0)); + assert_eq!(t1.triangle.p2, point(-1.0, 0.0, 0.0)); + assert_eq!(t1.triangle.p3, point(1.0, 0.0, 0.0)); + assert_eq!(t1.n1, vector(0.0, 1.0, 0.0)); + assert_eq!(t1.n2, vector(-1.0, 0.0, 0.0)); + assert_eq!(t1.n3, vector(1.0, 0.0, 0.0)); + let t2 = &obj_reader.smooth_triangles[1]; + assert_eq!(t2.triangle.p1, point(0.0, 1.0, 0.0)); + assert_eq!(t2.triangle.p2, point(-1.0, 0.0, 0.0)); + assert_eq!(t2.triangle.p3, point(1.0, 0.0, 0.0)); + assert_eq!(t2.n1, vector(0.0, 1.0, 0.0)); + assert_eq!(t2.n2, vector(-1.0, 0.0, 0.0)); + assert_eq!(t2.n3, vector(1.0, 0.0, 0.0)); + } } \ No newline at end of file