From f2a127ace7575ca9373f372c443a723b19d3c27e Mon Sep 17 00:00:00 2001 From: STP Date: Tue, 28 Nov 2023 13:22:41 -0500 Subject: [PATCH] Moved node & material to own files --- src/material.rs | 48 +++++++ src/node.rs | 97 ++++++++++++++ src/primitive.rs | 333 ++++++----------------------------------------- src/scene.rs | 92 +------------ 4 files changed, 191 insertions(+), 379 deletions(-) create mode 100644 src/material.rs create mode 100644 src/node.rs diff --git a/src/material.rs b/src/material.rs new file mode 100644 index 0000000..eb651c8 --- /dev/null +++ b/src/material.rs @@ -0,0 +1,48 @@ +#[allow(dead_code)] +use nalgebra::Vector3; +// MATERIAL ----------------------------------------------------------------- +#[derive(Clone)] +pub struct Material { + pub kd: Vector3, + pub ks: Vector3, + pub shininess: f32, +} + +impl Material { + pub fn new(kd: Vector3, ks: Vector3, shininess: f64) -> Material { + let kd = kd.cast(); + let ks = ks.cast(); + let shininess = shininess as f32; + Material { kd, ks, shininess } + } + pub fn magenta() -> Material { + let kd = Vector3::new(1.0, 0.0, 1.0); + let ks = Vector3::new(1.0, 0.0, 1.0); + let shininess = 0.5; + Material { kd, ks, shininess } + } + pub fn turquoise() -> Material { + let kd = Vector3::new(0.25, 0.3, 0.7); + let ks = Vector3::new(0.25, 0.3, 0.7); + let shininess = 0.5; + Material { kd, ks, shininess } + } + pub fn red() -> Material { + let kd = Vector3::new(0.8, 0.0, 0.3); + let ks = Vector3::new(0.8, 0.3, 0.0); + let shininess = 0.5; + Material { kd, ks, shininess } + } + pub fn blue() -> Material { + let kd = Vector3::new(0.0, 0.3, 0.6); + let ks = Vector3::new(0.3, 0.0, 0.6); + let shininess = 0.5; + Material { kd, ks, shininess } + } + pub fn green() -> Material { + let kd = Vector3::new(0.0, 1.0, 0.0); + let ks = Vector3::new(0.0, 1.0, 0.0); + let shininess = 0.5; + Material { kd, ks, shininess } + } +} diff --git a/src/node.rs b/src/node.rs new file mode 100644 index 0000000..a8cc085 --- /dev/null +++ b/src/node.rs @@ -0,0 +1,97 @@ +use crate::{material::Material, primitive::*}; +use nalgebra::{Matrix4, Vector3}; +use std::rc::Rc; + +#[derive(Clone)] +pub struct Node { + //Primitive + pub primitive: Rc, + pub material: Material, + //Transformations + pub rotation: [f64; 3], + pub scale: [f64; 3], + pub translation: [f64; 3], + //Model matricies + pub model: Matrix4, + pub inv_model: Matrix4, + + pub active: bool, +} + +impl Node { + //New node with no transformations + pub fn new(primitive: Rc, material: Material) -> Node { + Node { + primitive, + material, + rotation: [0.0, 0.0, 0.0], + scale: [1.0, 1.0, 1.0], + translation: [0.0, 0.0, 0.0], + model: Matrix4::identity(), + inv_model: Matrix4::identity(), + + active: true, + } + } + //New node with parent transformations + pub fn child(self, primitive: Rc) -> Node { + let mut child = self.clone(); + child.primitive = primitive; + child + } + //Toggle is a mesh is visible or not + pub fn set_active(&mut self, active: bool) { + self.active = active; + } + + //Rotate a mesh by adding to its rotation + pub fn rotate(&mut self, roll: f64, pitch: f64, yaw: f64) { + //Convert to radians + let roll = roll.to_radians(); + // Convert pitch and yaw to radians + let pitch = pitch.to_radians(); + let yaw = yaw.to_radians(); + + // Add the roll, pitch, and yaw to the current rotation + self.rotation[0] += roll; + self.rotation[1] += pitch; + self.rotation[2] += yaw; + + // Recompute the model and inverse model matrices + self.compute(); + } + // Translate a mesh by adding to its current position + pub fn translate(&mut self, x: f64, y: f64, z: f64) { + self.translation[0] += x; + self.translation[1] += y; + self.translation[2] += z; + + // Recompute the model and inverse model matrices + self.compute(); + } + // Scale a mesh by adding to its current scale + pub fn scale(&mut self, x: f64, y: f64, z: f64) { + self.scale[0] += x; + self.scale[1] += y; + self.scale[2] += z; + + // Recompute the model and inverse model matrices + self.compute(); + } + // This function computes the model and inverse model matrices + pub fn compute(&mut self) { + //Translation matrix + let translation = Vector3::from_row_slice(&self.translation); + let translation_matrix = Matrix4::new_translation(&translation); + // Scale matrix + let scale = &Vector3::from_row_slice(&self.scale); + let scale_matrix = Matrix4::new_nonuniform_scaling(&scale); + // Rotation matrix + let (roll, pitch, yaw) = (self.rotation[0], self.rotation[1], self.rotation[2]); + let rotation_matrix = Matrix4::from_euler_angles(roll, pitch, yaw); + // Compute the model matrix by combining the translation, rotation, and scale matrices + self.model = (translation_matrix * rotation_matrix * scale_matrix).cast(); + // Compute the inverse model matrix by inverting the model matrix + self.inv_model = self.model.try_inverse().unwrap(); + } +} diff --git a/src/primitive.rs b/src/primitive.rs index 9bbb0f0..9da5435 100644 --- a/src/primitive.rs +++ b/src/primitive.rs @@ -1,127 +1,19 @@ +use crate::{ + bvh::BoundingBox, + ray::{Intersection, Ray}, + {EPSILON, INFINITY}, +}; + #[allow(dead_code)] -use crate::ray::Ray; -use crate::{EPSILON, INFINITY}; -use nalgebra::{distance, Matrix4, Point3, Vector3}; +use nalgebra::{distance, Point3, Vector3}; use roots::{find_roots_quadratic, find_roots_quartic, Roots}; use std::fs::File; use std::io::{BufRead, BufReader}; use std::rc::Rc; -// MATERIAL ----------------------------------------------------------------- -#[derive(Clone)] -pub struct Material { - pub kd: Vector3, - pub ks: Vector3, - pub shininess: f32, -} - -impl Material { - pub fn new(kd: Vector3, ks: Vector3, shininess: f64) -> Rc { - let kd = kd.cast(); - let ks = ks.cast(); - let shininess = shininess as f32; - Rc::new(Material { kd, ks, shininess }) - } - pub fn magenta() -> Rc { - let kd = Vector3::new(1.0, 0.0, 1.0); - let ks = Vector3::new(1.0, 0.0, 1.0); - let shininess = 0.5; - Rc::new(Material { kd, ks, shininess }) - } - pub fn turquoise() -> Rc { - let kd = Vector3::new(0.25, 0.3, 0.7); - let ks = Vector3::new(0.25, 0.3, 0.7); - let shininess = 0.5; - Rc::new(Material { kd, ks, shininess }) - } - pub fn red() -> Rc { - let kd = Vector3::new(0.8, 0.0, 0.3); - let ks = Vector3::new(0.8, 0.3, 0.0); - let shininess = 0.5; - Rc::new(Material { kd, ks, shininess }) - } - pub fn blue() -> Rc { - let kd = Vector3::new(0.0, 0.3, 0.6); - let ks = Vector3::new(0.3, 0.0, 0.6); - let shininess = 0.5; - Rc::new(Material { kd, ks, shininess }) - } - pub fn green() -> Rc { - let kd = Vector3::new(0.0, 1.0, 0.0); - let ks = Vector3::new(0.0, 1.0, 0.0); - let shininess = 0.5; - Rc::new(Material { kd, ks, shininess }) - } -} - -// INTERSECTION ----------------------------------------------------------------- -pub struct Intersection { - // Information about an intersection - pub point: Point3, - pub normal: Vector3, - pub incidence: Vector3, - pub material: Rc, - pub distance: f64, -} -impl Intersection { - pub fn transform(&self, trans: &Matrix4, inv_trans: &Matrix4) -> Intersection { - Intersection { - point: trans.transform_point(&self.point), - normal: inv_trans.transpose().transform_vector(&self.normal), - incidence: trans.transform_vector(&self.incidence), - material: self.material.clone(), - distance: self.distance, - } - } -} - -// BOUNDING BOX ----------------------------------------------------------------- -#[derive(Clone)] -struct BoundingBox { - bln: Point3, - trf: Point3, -} - -impl BoundingBox { - fn new(bln: Point3, trf: Point3) -> Self { - let bln = bln + Vector3::new(EPSILON, EPSILON, EPSILON); - let trf = trf - Vector3::new(EPSILON, EPSILON, EPSILON); - BoundingBox { bln, trf } - } - fn intersect_bounding_box(&self, ray: &Ray) -> bool { - let bln = &self.bln; - let trf = &self.trf; - let t1 = (bln - ray.a).component_div(&ray.b); - let t2 = (trf - ray.a).component_div(&ray.b); - - let tmin = t1.inf(&t2).min(); - let tmax = t1.sup(&t2).max(); - - if tmax >= tmin { - let intersect = ray.at_t(tmin); - - // Check if the intersection is inside the box - if intersect.x > bln.x - EPSILON - || intersect.x < trf.x + EPSILON - || intersect.y > bln.y - EPSILON - || intersect.y < trf.y + EPSILON - || intersect.z > bln.z - EPSILON - || intersect.z < trf.z + EPSILON - { - return true; // Intersection is outside the box - } - } - false - } - #[allow(dead_code)] - fn get_centroid(&self) -> Point3 { - self.bln + (self.trf - self.bln) / 2.0 - } -} // PRIMITIVE TRAIT ----------------------------------------------------------------- pub trait Primitive { fn intersect_ray(&self, ray: &Ray) -> Option; fn intersect_bounding_box(&self, ray: &Ray) -> bool; - fn get_material(&self) -> Rc; } // SPHERE ----------------------------------------------------------------- @@ -130,11 +22,10 @@ pub struct Sphere { position: Point3, radius: f64, bounding_box: BoundingBox, - material: Rc, } impl Sphere { - pub fn new(position: Point3, radius: f64, material: Rc) -> Rc { + pub fn new(position: Point3, radius: f64) -> Rc { let radius_vec = Vector3::new(radius, radius, radius); let bln = position - radius_vec; let trf = position + radius_vec; @@ -143,12 +34,11 @@ impl Sphere { position, radius, bounding_box, - material, }) } - pub fn unit(material: Rc) -> Rc { - Sphere::new(Point3::new(0.0, 0.0, 0.0), 1.0, material) + pub fn unit() -> Rc { + Sphere::new(Point3::new(0.0, 0.0, 0.0), 1.0) } } @@ -184,16 +74,10 @@ impl Primitive for Sphere { Some(Intersection { point: intersect, normal, - incidence: ray.b, - material: Rc::clone(&self.material), distance: t, }) } - fn get_material(&self) -> Rc { - Rc::clone(&self.material) - } - fn intersect_bounding_box(&self, ray: &Ray) -> bool { return self.bounding_box.intersect_bounding_box(ray); } @@ -205,17 +89,11 @@ pub struct Circle { position: Point3, radius: f64, normal: Vector3, - material: Rc, bounding_box: BoundingBox, } impl Circle { - pub fn new( - position: Point3, - radius: f64, - normal: Vector3, - material: Rc, - ) -> Rc { + pub fn new(position: Point3, radius: f64, normal: Vector3) -> Rc { let radius_vec = Vector3::new(radius, radius, radius); let bln = position - radius_vec; let trf = position + radius_vec; @@ -224,16 +102,14 @@ impl Circle { position, radius, normal: normal.normalize(), - material, bounding_box, }) } - pub fn unit(material: Rc) -> Rc { + pub fn unit() -> Rc { let position = Point3::new(0.0, 0.0, 0.0); let normal = Vector3::new(0.0, 1.0, 0.0); let radius = 1.0; - let material = material; let bln = Point3::new(-radius, 0.0, -EPSILON); let trf = Point3::new(radius, 0.0, EPSILON); @@ -243,7 +119,6 @@ impl Circle { position, normal, radius, - material, bounding_box, }) } @@ -265,18 +140,12 @@ impl Primitive for Circle { return Some(Intersection { point: intersect, normal: self.normal.normalize(), - incidence: ray.b, - material: Rc::clone(&self.material), distance: t, }) } } } - fn get_material(&self) -> Rc { - Rc::clone(&self.material) - } - fn intersect_bounding_box(&self, ray: &Ray) -> bool { self.bounding_box.intersect_bounding_box(ray) } @@ -289,23 +158,20 @@ pub struct Cylinder { height: f64, base_circle: Rc, top_circle: Rc, - material: Rc, bounding_box: BoundingBox, } impl Cylinder { - pub fn new(radius: f64, height: f64, material: Rc) -> Rc { + pub fn new(radius: f64, height: f64) -> Rc { let base_circle = Circle::new( Point3::new(0.0, 0.0, 0.0), radius, Vector3::new(0.0, -1.0, 0.0), - Rc::clone(&material), ); let top_circle = Circle::new( Point3::new(0.0, height, 0.0), radius, Vector3::new(0.0, 1.0, 0.0), - Rc::clone(&material), ); let bln = Point3::new(-radius, 0.0, -radius); let trf = Point3::new(radius, height, radius); @@ -314,7 +180,6 @@ impl Cylinder { height, base_circle, top_circle, - material, bounding_box: BoundingBox { bln, trf }, }) } @@ -356,8 +221,6 @@ impl Primitive for Cylinder { Some(Intersection { point: intersect, normal: normal, - incidence: ray.b, - material: Rc::clone(&self.material), distance: t, }) } else { @@ -400,10 +263,6 @@ impl Primitive for Cylinder { } } - fn get_material(&self) -> Rc { - Rc::clone(&self.material) - } - fn intersect_bounding_box(&self, ray: &Ray) -> bool { self.bounding_box.intersect_bounding_box(ray) } @@ -416,17 +275,15 @@ pub struct Cone { base: f64, apex: f64, circle: Rc, - material: Rc, bounding_box: BoundingBox, } impl Cone { - pub fn new(radius: f64, apex: f64, base: f64, material: Rc) -> Rc { + pub fn new(radius: f64, apex: f64, base: f64) -> Rc { let circle = Circle::new( Point3::new(0.0, base, 0.0), radius, Vector3::new(0.0, 1.0, 0.0), - Rc::clone(&material), ); let bln = Point3::new(-radius, base, -radius); let trf = Point3::new(radius, base + apex, radius); @@ -435,12 +292,11 @@ impl Cone { base, apex, circle, - material, bounding_box: BoundingBox { bln, trf }, }) } - pub fn unit(material: Rc) -> Rc { - Cone::new(1.0, 2.0, -1.0, material) + pub fn unit() -> Rc { + Cone::new(1.0, 2.0, -1.0) } pub fn get_normal(&self, intersect: Point3) -> Vector3 { @@ -489,8 +345,6 @@ impl Primitive for Cone { true => Some(Intersection { point: intersect, normal: self.get_normal(intersect), - incidence: ray.b, - material: Rc::clone(&self.material), distance: t, }), false => None, @@ -515,10 +369,6 @@ impl Primitive for Cone { } } - fn get_material(&self) -> Rc { - Rc::clone(&self.material) - } - fn intersect_bounding_box(&self, ray: &Ray) -> bool { self.bounding_box.intersect_bounding_box(ray) } @@ -530,7 +380,6 @@ pub struct Rectangle { position: Point3, normal: Vector3, width_direction: Vector3, - material: Rc, width: f64, height: f64, bounding_box: BoundingBox, @@ -543,7 +392,6 @@ impl Rectangle { width_direction: Vector3, width: f64, height: f64, - material: Rc, ) -> Rc { let normal = normal.normalize(); let width_direction = width_direction.normalize(); @@ -556,18 +404,16 @@ impl Rectangle { width_direction: width_direction.normalize(), width, height, - material, bounding_box: BoundingBox { bln, trf }, }) } - pub fn unit(material: Rc) -> Rc { + pub fn unit() -> Rc { Rectangle::new( Point3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 1.0, 0.0), Vector3::new(1.0, 0.0, 0.0), 2.0, 2.0, - material, ) } } @@ -595,18 +441,12 @@ impl Primitive for Rectangle { return Some(Intersection { point: intersect, normal: self.normal, - incidence: ray.b, - material: Rc::clone(&self.material), distance: t, }); } None } - fn get_material(&self) -> Rc { - Rc::clone(&self.material) - } - fn intersect_bounding_box(&self, ray: &Ray) -> bool { self.bounding_box.intersect_bounding_box(ray) } @@ -617,24 +457,22 @@ impl Primitive for Rectangle { pub struct Cube { bln: Point3, trf: Point3, - material: Rc, bounding_box: BoundingBox, } impl Cube { - pub fn new(bln: Point3, trf: Point3, material: Rc) -> Rc { + pub fn new(bln: Point3, trf: Point3) -> Rc { Rc::new(Cube { bln, trf, - material, bounding_box: BoundingBox { bln, trf }, }) } - pub fn unit(material: Rc) -> Rc { + pub fn unit() -> Rc { let bln = Point3::new(-1.0, -1.0, -1.0); let trf = Point3::new(1.0, 1.0, 1.0); - Cube::new(bln, trf, material) + Cube::new(bln, trf) } } @@ -651,17 +489,17 @@ impl Primitive for Cube { let tmax = t1.sup(&t2).min(); // Check if there's an intersection between tmin and tmax - if tmax >= tmin { + if tmax >= tmin && tmin > EPSILON { // The ray intersects the box, and tmin is the entry point, tmax is the exit point let intersect = ray.at_t(tmin); // Check if the intersection is outside the box - if intersect.x < bln.x - EPSILON - || intersect.x > trf.x + EPSILON - || intersect.y < bln.y - EPSILON - || intersect.y > trf.y + EPSILON - || intersect.z < bln.z - EPSILON - || intersect.z > trf.z + EPSILON + if intersect.x < bln.x + || intersect.x > trf.x + || intersect.y < bln.y + || intersect.y > trf.y + || intersect.z < bln.z + || intersect.z > trf.z { return None; // Intersection is outside the box } @@ -684,8 +522,6 @@ impl Primitive for Cube { Some(Intersection { point: intersect, normal: normal, - incidence: ray.b, - material: Rc::clone(&self.material), distance: tmin, }) } else { @@ -696,10 +532,6 @@ impl Primitive for Cube { fn intersect_bounding_box(&self, ray: &Ray) -> bool { self.bounding_box.intersect_bounding_box(ray) } - - fn get_material(&self) -> Rc { - Rc::clone(&self.material) - } } // TRIANGLE ----------------------------------------------------------------- @@ -710,17 +542,11 @@ pub struct Triangle { v: Point3, w: Point3, normal: Vector3, - material: Rc, bounding_box: BoundingBox, } impl Triangle { - pub fn new( - u: Point3, - v: Point3, - w: Point3, - material: Rc, - ) -> Rc { + pub fn new(u: Point3, v: Point3, w: Point3) -> Rc { let uv = v - u; let uw = w - u; let normal = uv.cross(&uw).normalize(); @@ -732,17 +558,15 @@ impl Triangle { v, w, normal, - material, bounding_box, }) } #[allow(dead_code)] - pub fn unit(material: Rc) -> Rc { - let u = Point3::new(-1.0, 0.0, -1.0); - let v = Point3::new(0.0, 0.0, 1.0); - let w = Point3::new(1.0, 0.0, -1.0); - let material = material; - Triangle::new(u, v, w, material) + pub fn unit() -> Rc { + let u = Point3::new(-1.0, -1.0, 0.0); + let v = Point3::new(0.0, 1.0, 0.0); + let w = Point3::new(1.0, -1.0, 0.0); + Triangle::new(u, v, w) } } @@ -777,8 +601,6 @@ impl Primitive for Triangle { Some(Intersection { point: intersect, normal: normal, - incidence: ray.b, - material: Rc::clone(&self.material), distance: t, }) } else { @@ -786,10 +608,6 @@ impl Primitive for Triangle { } } - fn get_material(&self) -> Rc { - Rc::clone(&self.material) - } - fn intersect_bounding_box(&self, ray: &Ray) -> bool { self.bounding_box.intersect_bounding_box(ray) } @@ -799,17 +617,15 @@ impl Primitive for Triangle { #[derive(Clone)] pub struct Mesh { triangles: Vec, - material: Rc, bounding_box: BoundingBox, } impl Mesh { - pub fn new(triangles: Vec, material: Rc) -> Rc { + pub fn new(triangles: Vec) -> Rc { // Calculate the bounding box for the entire mesh based on the bounding boxes of individual triangles let bounding_box = Mesh::compute_bounding_box(&triangles); Rc::new(Mesh { triangles, - material, bounding_box, }) } @@ -828,7 +644,7 @@ impl Mesh { BoundingBox { bln, trf } } - pub fn from_file(filename: &str, material: Rc) -> Rc { + pub fn from_file(filename: &str) -> Rc { let mut triangles: Vec = Vec::new(); let mut vertices: Vec> = Vec::new(); @@ -872,13 +688,11 @@ impl Mesh { let bln = u.inf(&v).inf(&w); let trf = u.sup(&v).sup(&w); let bounding_box = BoundingBox { bln, trf }; - let material = material.clone(); triangles.push(Triangle { u, v, w, normal, - material, bounding_box, }); } @@ -888,7 +702,7 @@ impl Mesh { } } } - Mesh::new(triangles, material) + Mesh::new(triangles) } } @@ -913,10 +727,6 @@ impl Primitive for Mesh { closest_intersect } - fn get_material(&self) -> Rc { - Rc::clone(&self.material) - } - fn intersect_bounding_box(&self, ray: &Ray) -> bool { self.bounding_box.intersect_bounding_box(ray) } @@ -927,19 +737,17 @@ impl Primitive for Mesh { pub struct Torus { inner_rad: f64, outer_rad: f64, - material: Rc, bounding_box: BoundingBox, } impl Torus { - pub fn new(inner_rad: f64, outer_rad: f64, material: Rc) -> Rc { + pub fn new(inner_rad: f64, outer_rad: f64) -> Rc { // I need to find the bounding box for this shape let trf = Point3::new(1.0, 1.0, 1.0); let bln = Point3::new(-1.0, -1.0, -1.0); Rc::new(Torus { inner_rad, outer_rad, - material, bounding_box: BoundingBox { bln, trf }, }) } @@ -1042,8 +850,6 @@ impl Primitive for Torus { Some(Intersection { point, normal, - incidence: ray.b, - material: Rc::clone(&self.material), distance: t, }) } @@ -1051,10 +857,6 @@ impl Primitive for Torus { fn intersect_bounding_box(&self, ray: &Ray) -> bool { self.bounding_box.intersect_bounding_box(ray) } - - fn get_material(&self) -> Rc { - Rc::clone(&self.material) - } } // GNOMON ----------------------------------------------------------------- @@ -1063,28 +865,24 @@ pub struct Gnonom { x_cube: Rc, y_cube: Rc, z_cube: Rc, - material: Rc, bounding_box: BoundingBox, } impl Gnonom { const GNONOM_WIDTH: f64 = 0.1; const GNONOM_LENGTH: f64 = 2.0; - pub fn new(material: Rc) -> Rc { + pub fn new() -> Rc { let x_cube = Cube::new( Point3::new(0.0, -Self::GNONOM_WIDTH, -Self::GNONOM_WIDTH), Point3::new(Self::GNONOM_LENGTH, Self::GNONOM_WIDTH, Self::GNONOM_WIDTH), - material.clone(), ); let y_cube = Cube::new( Point3::new(-Self::GNONOM_WIDTH, 0.0, -Self::GNONOM_WIDTH), Point3::new(Self::GNONOM_WIDTH, Self::GNONOM_LENGTH, Self::GNONOM_WIDTH), - material.clone(), ); let z_cube = Cube::new( Point3::new(-Self::GNONOM_WIDTH, -Self::GNONOM_WIDTH, 0.0), Point3::new(Self::GNONOM_WIDTH, Self::GNONOM_WIDTH, Self::GNONOM_LENGTH), - material.clone(), ); let bounding_box = BoundingBox { bln: Point3::new( @@ -1102,7 +900,6 @@ impl Gnonom { x_cube, y_cube, z_cube, - material, bounding_box, }) } @@ -1128,26 +925,20 @@ impl Primitive for Gnonom { fn intersect_bounding_box(&self, ray: &Ray) -> bool { self.bounding_box.intersect_bounding_box(ray) } - - fn get_material(&self) -> Rc { - self.material.clone() - } } // CROSS CAP --------- #[derive(Clone)] pub struct CrossCap { - material: Rc, bounding_box: BoundingBox, } impl CrossCap { - pub fn new(material: Rc) -> Rc { + pub fn new() -> Rc { // I need to find the bounding box for this shape let trf = Point3::new(1.0, 1.0, 1.0); let bln = Point3::new(-1.0, -1.0, -1.0); Rc::new(CrossCap { - material, bounding_box: BoundingBox { bln, trf }, }) } @@ -1219,8 +1010,6 @@ impl Primitive for CrossCap { Some(Intersection { point, normal, - incidence: ray.b, - material: Rc::clone(&self.material), distance: t, }) } @@ -1228,10 +1017,6 @@ impl Primitive for CrossCap { fn intersect_bounding_box(&self, ray: &Ray) -> bool { self.bounding_box.intersect_bounding_box(ray) } - - fn get_material(&self) -> Rc { - Rc::clone(&self.material) - } } // CROSS CAP 2 --------- @@ -1239,19 +1024,17 @@ impl Primitive for CrossCap { pub struct CrossCap2 { p: f64, q: f64, - material: Rc, bounding_box: BoundingBox, } impl CrossCap2 { - pub fn new(p: f64, q: f64, material: Rc) -> Rc { + pub fn new(p: f64, q: f64) -> Rc { // I need to find the bounding box for this shape let trf = Point3::new(1.0, 1.0, 1.0); let bln = Point3::new(-1.0, -1.0, -1.0); Rc::new(CrossCap2 { p, q, - material, bounding_box: BoundingBox { bln, trf }, }) } @@ -1348,8 +1131,6 @@ impl Primitive for CrossCap2 { Some(Intersection { point, normal, - incidence: ray.b, - material: Rc::clone(&self.material), distance: t, }) } @@ -1357,26 +1138,20 @@ impl Primitive for CrossCap2 { fn intersect_bounding_box(&self, ray: &Ray) -> bool { self.bounding_box.intersect_bounding_box(ray) } - - fn get_material(&self) -> Rc { - Rc::clone(&self.material) - } } // Steiner --------- #[derive(Clone)] pub struct Steiner { - material: Rc, bounding_box: BoundingBox, } impl Steiner { - pub fn new(material: Rc) -> Rc { + pub fn new() -> Rc { // I need to find the bounding box for this shape let trf = Point3::new(1.0, 1.0, 1.0); let bln = Point3::new(-1.0, -1.0, -1.0); Rc::new(Steiner { - material, bounding_box: BoundingBox { bln, trf }, }) } @@ -1437,8 +1212,6 @@ impl Primitive for Steiner { Some(Intersection { point, normal, - incidence: ray.b, - material: Rc::clone(&self.material), distance: t, }) } @@ -1446,26 +1219,20 @@ impl Primitive for Steiner { fn intersect_bounding_box(&self, ray: &Ray) -> bool { self.bounding_box.intersect_bounding_box(ray) } - - fn get_material(&self) -> Rc { - Rc::clone(&self.material) - } } // Steiner 2 --------- #[derive(Clone)] pub struct Steiner2 { - material: Rc, bounding_box: BoundingBox, } impl Steiner2 { - pub fn new(material: Rc) -> Rc { + pub fn new() -> Rc { // I need to find the bounding box for this shape let trf = Point3::new(1.0, 1.0, 1.0); let bln = Point3::new(-1.0, -1.0, -1.0); Rc::new(Steiner2 { - material, bounding_box: BoundingBox { bln, trf }, }) } @@ -1537,8 +1304,6 @@ impl Primitive for Steiner2 { Some(Intersection { point, normal, - incidence: ray.b, - material: Rc::clone(&self.material), distance: t, }) } @@ -1546,28 +1311,22 @@ impl Primitive for Steiner2 { fn intersect_bounding_box(&self, ray: &Ray) -> bool { self.bounding_box.intersect_bounding_box(ray) } - - fn get_material(&self) -> Rc { - Rc::clone(&self.material) - } } // Roman --------- #[derive(Clone)] pub struct Roman { k: f64, - material: Rc, bounding_box: BoundingBox, } impl Roman { - pub fn new(k: f64, material: Rc) -> Rc { + pub fn new(k: f64) -> Rc { // I need to find the bounding box for this shape let trf = Point3::new(1.0, 1.0, 1.0); let bln = Point3::new(-1.0, -1.0, -1.0); Rc::new(Roman { k, - material, bounding_box: BoundingBox { bln, trf }, }) } @@ -1656,8 +1415,6 @@ impl Primitive for Roman { Some(Intersection { point, normal, - incidence: ray.b, - material: Rc::clone(&self.material), distance: t, }) } @@ -1665,10 +1422,6 @@ impl Primitive for Roman { fn intersect_bounding_box(&self, ray: &Ray) -> bool { self.bounding_box.intersect_bounding_box(ray) } - - fn get_material(&self) -> Rc { - Rc::clone(&self.material) - } } fn smallest_non_zero(arr: &[f64]) -> Option { diff --git a/src/scene.rs b/src/scene.rs index aea3f36..fadff89 100644 --- a/src/scene.rs +++ b/src/scene.rs @@ -1,96 +1,10 @@ -use crate::camera::Camera; -use crate::light::Light; -use crate::primitive::*; -use nalgebra::{Matrix4, Vector3}; +use crate::{camera::Camera, light::Light, material::*, node::*}; use std::collections::HashMap; -use std::rc::Rc; -#[derive(Clone)] -pub struct Node { - //Primitive - pub primitive: Rc, - //Transformations - pub rotation: [f64; 3], - pub scale: [f64; 3], - pub translation: [f64; 3], - //Model matricies - pub model: Matrix4, - pub inv_model: Matrix4, -} - -impl Node { - //New node with no transformations - pub fn new(primitive: Rc) -> Node { - Node { - primitive, - rotation: [0.0, 0.0, 0.0], - scale: [1.0, 1.0, 1.0], - translation: [0.0, 0.0, 0.0], - model: Matrix4::identity(), - inv_model: Matrix4::identity(), - } - } - //New node with parent transformations - pub fn child(self, primitive: Rc) -> Node { - let mut child = self.clone(); - child.primitive = primitive; - child - } - //Rotate a mesh by adding to its rotation - pub fn rotate(&mut self, roll: f64, pitch: f64, yaw: f64) { - //Convert to radians - let roll = roll.to_radians(); - // Convert pitch and yaw to radians - let pitch = pitch.to_radians(); - let yaw = yaw.to_radians(); - - // Add the roll, pitch, and yaw to the current rotation - self.rotation[0] += roll; - self.rotation[1] += pitch; - self.rotation[2] += yaw; - - // Recompute the model and inverse model matrices - self.compute(); - } - // Translate a mesh by adding to its current position - pub fn translate(&mut self, x: f64, y: f64, z: f64) { - self.translation[0] += x; - self.translation[1] += y; - self.translation[2] += z; - - // Recompute the model and inverse model matrices - self.compute(); - } - // Scale a mesh by adding to its current scale - pub fn scale(&mut self, x: f64, y: f64, z: f64) { - self.scale[0] += x; - self.scale[1] += y; - self.scale[2] += z; - - // Recompute the model and inverse model matrices - self.compute(); - } - // This function computes the model and inverse model matrices - pub fn compute(&mut self) { - //Translation matrix - let translation = Vector3::from_row_slice(&self.translation); - let translation_matrix = Matrix4::new_translation(&translation); - // Scale matrix - let scale = &Vector3::from_row_slice(&self.scale); - let scale_matrix = Matrix4::new_nonuniform_scaling(&scale); - // Rotation matrix - let (roll, pitch, yaw) = (self.rotation[0], self.rotation[1], self.rotation[2]); - let rotation_matrix = Matrix4::from_euler_angles(roll, pitch, yaw); - // Compute the model matrix by combining the translation, rotation, and scale matrices - self.model = (translation_matrix * rotation_matrix * scale_matrix).cast(); - // Compute the inverse model matrix by inverting the model matrix - self.inv_model = self.model.try_inverse().unwrap(); - } -} #[derive(Clone)] pub struct Scene { pub nodes: HashMap, - pub materials: HashMap>, + pub materials: HashMap, pub lights: HashMap, pub cameras: HashMap, } @@ -110,7 +24,7 @@ impl Scene { self.nodes.insert(label, node); } // Adds a material to the scene - pub fn add_material(&mut self, label: String, material: Rc) { + pub fn add_material(&mut self, label: String, material: Material) { self.materials.insert(label, material); } // Adds a light to the scene