Slight refactor
This commit is contained in:
parent
a725cc2e39
commit
021ba892f8
5 changed files with 76 additions and 45 deletions
|
@ -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>;
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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))>,
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
//
|
||||
|
|
Loading…
Reference in a new issue