Slight refactor

This commit is contained in:
Michael Zhang 2023-02-24 04:34:01 -06:00
parent a725cc2e39
commit 021ba892f8
5 changed files with 76 additions and 45 deletions

View file

@ -1,4 +1,4 @@
use nalgebra::Vector3; use nalgebra::{Vector2, Vector3};
#[macro_use] #[macro_use]
extern crate anyhow; extern crate anyhow;
@ -12,5 +12,6 @@ pub mod ray;
pub mod scene; pub mod scene;
pub mod utils; pub mod utils;
pub type Point2 = Vector2<f64>;
pub type Point = Vector3<f64>; pub type Point = Vector3<f64>;
pub type Vector = Vector3<f64>; pub type Vector = Vector3<f64>;

View file

@ -10,14 +10,14 @@ use crate::Point;
use super::cylinder::Cylinder; use super::cylinder::Cylinder;
use super::illumination::IntersectionContext; use super::illumination::IntersectionContext;
use super::sphere::Sphere; use super::sphere::Sphere;
use super::triangle::FlatTriangle; use super::triangle::Triangle;
use super::Scene; use super::Scene;
#[derive(Debug)] #[derive(Debug)]
pub enum ObjectKind { pub enum ObjectKind {
Sphere(Sphere), Sphere(Sphere),
Cylinder(Cylinder), Cylinder(Cylinder),
FlatTriangle(FlatTriangle), Triangle(Triangle),
} }
impl ObjectKind { impl ObjectKind {
@ -34,9 +34,7 @@ impl ObjectKind {
match self { match self {
ObjectKind::Sphere(sphere) => sphere.intersects_ray_at(scene, ray), ObjectKind::Sphere(sphere) => sphere.intersects_ray_at(scene, ray),
ObjectKind::Cylinder(cylinder) => cylinder.intersects_ray_at(scene, ray), ObjectKind::Cylinder(cylinder) => cylinder.intersects_ray_at(scene, ray),
ObjectKind::FlatTriangle(triangle) => { ObjectKind::Triangle(triangle) => triangle.intersects_ray_at(scene, ray),
triangle.intersects_ray_at(scene, ray)
}
} }
} }
} }

View file

@ -10,7 +10,7 @@ use crate::{
cylinder::Cylinder, cylinder::Cylinder,
data::{Attenuation, Light, LightKind, Material, Object}, data::{Attenuation, Light, LightKind, Material, Object},
sphere::Sphere, sphere::Sphere,
triangle::FlatTriangle, triangle::Triangle,
Scene, Scene,
}, },
Point, Vector, Point, Vector,
@ -196,7 +196,7 @@ impl Scene {
// Assignment 1C: Triangles and textures // Assignment 1C: Triangles and textures
// v x y z // v x y z
"v" => scene.vertices.push(r!(Vector)), "v" => scene.triangle_vertices.push(r!(Vector)),
// vn nx ny nz // vn nx ny nz
"vn" => scene.normals.push(r!(Vector)), "vn" => scene.normals.push(r!(Vector)),
@ -204,29 +204,42 @@ impl Scene {
// f v1 v2 v3 // f v1 v2 v3
// f v1//n1 v2//n2 v3//n3 // f v1//n1 v2//n2 v3//n3
"f" => { "f" => {
use TriangleVertex::*;
let v1 = r!(TriangleVertex); let v1 = r!(TriangleVertex);
let v2 = r!(TriangleVertex); let v2 = r!(TriangleVertex);
let v3 = r!(TriangleVertex); let v3 = r!(TriangleVertex);
let vs = Vector3::new(v1, v2, v3);
match (v1, v2, v3) { let vertices = vs.map(|v| v.vertex_idx);
(Flat(v1), Flat(v2), Flat(v3)) => {
let vertices = Vector3::new(v1, v2, v3); 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 { scene.objects.push(Object {
kind: ObjectKind::FlatTriangle(FlatTriangle { vertices }), kind: ObjectKind::Triangle(triangle),
material: mat!(), 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"),
}
enum TriangleVertex { #[derive(Debug, Copy, Clone, PartialEq)]
Flat(usize), struct TriangleVertex {
Smooth(usize, usize), vertex_idx: usize,
normal_idx: Option<usize>,
texture_idx: Option<usize>,
} }
impl Construct for TriangleVertex { impl Construct for TriangleVertex {
@ -243,16 +256,26 @@ impl Scene {
// Note: indexed by 1 not 0, so we will just do the subtraction // Note: indexed by 1 not 0, so we will just do the subtraction
// here to avoid having to deal with it later // here to avoid having to deal with it later
let parts = s.split("//").collect_vec(); let parts = s.split("/").collect_vec();
ensure!(parts.len() >= 1 && parts.len() <= 2); ensure!(parts.len() >= 1 && parts.len() <= 3);
let v_idx: usize = parts[0].parse()?; let vertex_idx: usize = parts[0].parse::<usize>()? - 1;
Ok(match parts.len() {
1 => TriangleVertex::Flat(v_idx - 1), let texture_idx =
2 => { match parts.get(1).and_then(|s| s.is_empty().then(|| *s)) {
let n_idx: usize = parts[1].parse()?; Some(s) => Some(s.parse::<usize>()? - 1),
TriangleVertex::Smooth(v_idx - 1, n_idx - 1) None => None,
} };
_ => bail!("Invalid"),
let normal_idx =
match parts.get(2).and_then(|s| s.is_empty().then(|| *s)) {
Some(s) => Some(s.parse::<usize>()? - 1),
None => None,
};
Ok(TriangleVertex {
vertex_idx,
texture_idx,
normal_idx,
}) })
} }
} }

View file

@ -5,8 +5,10 @@ pub mod input_file;
pub mod sphere; pub mod sphere;
pub mod triangle; pub mod triangle;
use nalgebra::Vector2;
use crate::image::{Color, Image}; use crate::image::{Color, Image};
use crate::{Point, Vector}; use crate::{Point, Point2, Vector};
use self::data::{Attenuation, DepthCueing, Light, Material, Object}; use self::data::{Attenuation, DepthCueing, Light, Material, Object};
@ -32,10 +34,15 @@ pub struct Scene {
pub lights: Vec<Light>, pub lights: Vec<Light>,
pub objects: Vec<Object>, pub objects: Vec<Object>,
/// List of textures
pub textures: Vec<Image>, pub textures: Vec<Image>,
pub vertices: Vec<Point>,
pub flat_triangles: Vec<(usize, usize, usize)>,
/// Coordinates into a texture image
pub texture_vertices: Vec<Point2>,
/// Triangle vertices
pub triangle_vertices: Vec<Point>,
/// Normal vectors
pub normals: Vec<Vector>, pub normals: Vec<Vector>,
pub smooth_triangles: Vec<((usize, usize), (usize, usize), (usize, usize))>,
} }

View file

@ -10,19 +10,21 @@ use super::illumination::IntersectionContext;
use super::Scene; use super::Scene;
#[derive(Debug)] #[derive(Debug)]
pub struct FlatTriangle { pub struct Triangle {
pub vertices: Vector3<usize>, pub vertices: Vector3<usize>,
pub normals: Option<Vector3<usize>>,
pub textures: Option<Vector3<usize>>,
} }
impl FlatTriangle { impl Triangle {
pub fn intersects_ray_at( pub fn intersects_ray_at(
&self, &self,
scene: &Scene, scene: &Scene,
ray: &Ray, ray: &Ray,
) -> Result<Option<IntersectionContext>> { ) -> Result<Option<IntersectionContext>> {
let p0 = scene.vertices[self.vertices.x]; let p0 = scene.triangle_vertices[self.vertices.x];
let p1 = scene.vertices[self.vertices.y]; let p1 = scene.triangle_vertices[self.vertices.y];
let p2 = scene.vertices[self.vertices.z]; let p2 = scene.triangle_vertices[self.vertices.z];
// Solve for the plane equation coefficients A, B, C, D such that: // Solve for the plane equation coefficients A, B, C, D such that:
// //