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]
extern crate anyhow;
@ -12,5 +12,6 @@ pub mod ray;
pub mod scene;
pub mod utils;
pub type Point2 = Vector2<f64>;
pub type Point = Vector3<f64>;
pub type Vector = Vector3<f64>;

View file

@ -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),
}
}
}

View file

@ -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<usize>,
texture_idx: Option<usize>,
}
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::<usize>()? - 1;
let texture_idx =
match parts.get(1).and_then(|s| s.is_empty().then(|| *s)) {
Some(s) => Some(s.parse::<usize>()? - 1),
None => None,
};
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 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<Light>,
pub objects: Vec<Object>,
/// List of textures
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 smooth_triangles: Vec<((usize, usize), (usize, usize), (usize, usize))>,
}

View file

@ -10,19 +10,21 @@ use super::illumination::IntersectionContext;
use super::Scene;
#[derive(Debug)]
pub struct FlatTriangle {
pub struct Triangle {
pub vertices: Vector3<usize>,
pub normals: Option<Vector3<usize>>,
pub textures: Option<Vector3<usize>>,
}
impl FlatTriangle {
impl Triangle {
pub fn intersects_ray_at(
&self,
scene: &Scene,
ray: &Ray,
) -> Result<Option<IntersectionContext>> {
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:
//