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]
|
#[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>;
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))>,
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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:
|
||||||
//
|
//
|
||||||
|
|
Loading…
Reference in a new issue