From 021ba892f809ed4cf8bc6a304501f9b894710c89 Mon Sep 17 00:00:00 2001 From: Michael Zhang Date: Fri, 24 Feb 2023 04:34:01 -0600 Subject: [PATCH] Slight refactor --- assignment-1c/src/lib.rs | 3 +- assignment-1c/src/scene/data.rs | 8 +-- assignment-1c/src/scene/input_file.rs | 83 +++++++++++++++++---------- assignment-1c/src/scene/mod.rs | 15 +++-- assignment-1c/src/scene/triangle.rs | 12 ++-- 5 files changed, 76 insertions(+), 45 deletions(-) diff --git a/assignment-1c/src/lib.rs b/assignment-1c/src/lib.rs index e2b448e..2960125 100644 --- a/assignment-1c/src/lib.rs +++ b/assignment-1c/src/lib.rs @@ -1,4 +1,4 @@ -use nalgebra::Vector3; +use nalgebra::{Vector2, Vector3}; #[macro_use] extern crate anyhow; @@ -12,5 +12,6 @@ pub mod ray; pub mod scene; pub mod utils; +pub type Point2 = Vector2; pub type Point = Vector3; pub type Vector = Vector3; diff --git a/assignment-1c/src/scene/data.rs b/assignment-1c/src/scene/data.rs index c1cf907..6729870 100644 --- a/assignment-1c/src/scene/data.rs +++ b/assignment-1c/src/scene/data.rs @@ -10,14 +10,14 @@ use crate::Point; use super::cylinder::Cylinder; use super::illumination::IntersectionContext; use super::sphere::Sphere; -use super::triangle::FlatTriangle; +use super::triangle::Triangle; use super::Scene; #[derive(Debug)] pub enum ObjectKind { Sphere(Sphere), Cylinder(Cylinder), - FlatTriangle(FlatTriangle), + Triangle(Triangle), } impl ObjectKind { @@ -34,9 +34,7 @@ impl ObjectKind { match self { ObjectKind::Sphere(sphere) => sphere.intersects_ray_at(scene, ray), ObjectKind::Cylinder(cylinder) => cylinder.intersects_ray_at(scene, ray), - ObjectKind::FlatTriangle(triangle) => { - triangle.intersects_ray_at(scene, ray) - } + ObjectKind::Triangle(triangle) => triangle.intersects_ray_at(scene, ray), } } } diff --git a/assignment-1c/src/scene/input_file.rs b/assignment-1c/src/scene/input_file.rs index a75bca7..29b78b8 100644 --- a/assignment-1c/src/scene/input_file.rs +++ b/assignment-1c/src/scene/input_file.rs @@ -10,7 +10,7 @@ use crate::{ cylinder::Cylinder, data::{Attenuation, Light, LightKind, Material, Object}, sphere::Sphere, - triangle::FlatTriangle, + triangle::Triangle, Scene, }, Point, Vector, @@ -196,7 +196,7 @@ impl Scene { // Assignment 1C: Triangles and textures // v x y z - "v" => scene.vertices.push(r!(Vector)), + "v" => scene.triangle_vertices.push(r!(Vector)), // vn nx ny nz "vn" => scene.normals.push(r!(Vector)), @@ -204,29 +204,42 @@ impl Scene { // f v1 v2 v3 // f v1//n1 v2//n2 v3//n3 "f" => { - use TriangleVertex::*; - let v1 = r!(TriangleVertex); let v2 = r!(TriangleVertex); let v3 = r!(TriangleVertex); + let vs = Vector3::new(v1, v2, v3); - match (v1, v2, v3) { - (Flat(v1), Flat(v2), Flat(v3)) => { - let vertices = Vector3::new(v1, v2, v3); - scene.objects.push(Object { - kind: ObjectKind::FlatTriangle(FlatTriangle { vertices }), - material: mat!(), - }); - } - (Smooth(v1, n1), Smooth(v2, n2), Smooth(v3, n3)) => { - scene.smooth_triangles.push(((v1, n1), (v2, n2), (v3, n3))) - } - _ => bail!("Must all be either v_idx or v_idx//n_idx"), - } + let vertices = vs.map(|v| v.vertex_idx); - enum TriangleVertex { - Flat(usize), - Smooth(usize, usize), + let normals = vs.map(|v| v.normal_idx); + let normals = match normals.iter().filter(|o| o.is_some()).count() { + 0 => None, + n if n == vs.len() => Some(normals.map(|o| o.unwrap())), + _ => bail!("Cannot mix and match having a normal index"), + }; + + let textures = vs.map(|v| v.texture_idx); + let textures = match textures.iter().filter(|o| o.is_some()).count() { + 0 => None, + n if n == vs.len() => Some(textures.map(|o| o.unwrap())), + _ => bail!("Cannot mix and match having a normal index"), + }; + + let triangle = Triangle { + vertices, + normals, + textures, + }; + scene.objects.push(Object { + kind: ObjectKind::Triangle(triangle), + material: mat!(), + }); + + #[derive(Debug, Copy, Clone, PartialEq)] + struct TriangleVertex { + vertex_idx: usize, + normal_idx: Option, + texture_idx: Option, } impl Construct for TriangleVertex { @@ -243,16 +256,26 @@ impl Scene { // Note: indexed by 1 not 0, so we will just do the subtraction // here to avoid having to deal with it later - let parts = s.split("//").collect_vec(); - ensure!(parts.len() >= 1 && parts.len() <= 2); - let v_idx: usize = parts[0].parse()?; - Ok(match parts.len() { - 1 => TriangleVertex::Flat(v_idx - 1), - 2 => { - let n_idx: usize = parts[1].parse()?; - TriangleVertex::Smooth(v_idx - 1, n_idx - 1) - } - _ => bail!("Invalid"), + let parts = s.split("/").collect_vec(); + ensure!(parts.len() >= 1 && parts.len() <= 3); + let vertex_idx: usize = parts[0].parse::()? - 1; + + let texture_idx = + match parts.get(1).and_then(|s| s.is_empty().then(|| *s)) { + Some(s) => Some(s.parse::()? - 1), + None => None, + }; + + let normal_idx = + match parts.get(2).and_then(|s| s.is_empty().then(|| *s)) { + Some(s) => Some(s.parse::()? - 1), + None => None, + }; + + Ok(TriangleVertex { + vertex_idx, + texture_idx, + normal_idx, }) } } diff --git a/assignment-1c/src/scene/mod.rs b/assignment-1c/src/scene/mod.rs index 4746889..86153cc 100644 --- a/assignment-1c/src/scene/mod.rs +++ b/assignment-1c/src/scene/mod.rs @@ -5,8 +5,10 @@ pub mod input_file; pub mod sphere; pub mod triangle; +use nalgebra::Vector2; + use crate::image::{Color, Image}; -use crate::{Point, Vector}; +use crate::{Point, Point2, Vector}; use self::data::{Attenuation, DepthCueing, Light, Material, Object}; @@ -32,10 +34,15 @@ pub struct Scene { pub lights: Vec, pub objects: Vec, + /// List of textures pub textures: Vec, - pub vertices: Vec, - pub flat_triangles: Vec<(usize, usize, usize)>, + /// Coordinates into a texture image + pub texture_vertices: Vec, + + /// Triangle vertices + pub triangle_vertices: Vec, + + /// Normal vectors pub normals: Vec, - pub smooth_triangles: Vec<((usize, usize), (usize, usize), (usize, usize))>, } diff --git a/assignment-1c/src/scene/triangle.rs b/assignment-1c/src/scene/triangle.rs index 27e64ce..34b0048 100644 --- a/assignment-1c/src/scene/triangle.rs +++ b/assignment-1c/src/scene/triangle.rs @@ -10,19 +10,21 @@ use super::illumination::IntersectionContext; use super::Scene; #[derive(Debug)] -pub struct FlatTriangle { +pub struct Triangle { pub vertices: Vector3, + pub normals: Option>, + pub textures: Option>, } -impl FlatTriangle { +impl Triangle { pub fn intersects_ray_at( &self, scene: &Scene, ray: &Ray, ) -> Result> { - let p0 = scene.vertices[self.vertices.x]; - let p1 = scene.vertices[self.vertices.y]; - let p2 = scene.vertices[self.vertices.z]; + let p0 = scene.triangle_vertices[self.vertices.x]; + let p1 = scene.triangle_vertices[self.vertices.y]; + let p2 = scene.triangle_vertices[self.vertices.z]; // Solve for the plane equation coefficients A, B, C, D such that: //