Refactor Vector3<f64> -> Point
This commit is contained in:
parent
1774fbc0de
commit
800eb68134
17 changed files with 128 additions and 68 deletions
10
assignment-1b/examples/Hw1bSample2.txt
Executable file
10
assignment-1b/examples/Hw1bSample2.txt
Executable file
|
@ -0,0 +1,10 @@
|
|||
eye 0 0 0
|
||||
viewdir 0 -0.3 -1
|
||||
updir 0 1 0
|
||||
hfov 60
|
||||
imsize 256 512
|
||||
bkgcolor 0.1 0.1 0.1
|
||||
light 0 -1 0 0 1 1 1
|
||||
mtlcolor 1 1 0 1 1 1 0.2 0.6 0.2 20
|
||||
sphere 0 -2 -3 1
|
||||
sphere 0 0 -3 0.5
|
2
assignment-1c/Cargo.lock
generated
2
assignment-1c/Cargo.lock
generated
|
@ -18,7 +18,7 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "assignment-1b"
|
||||
name = "assignment-1c"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[package]
|
||||
name = "assignment-1b"
|
||||
name = "assignment-1c"
|
||||
authors = ["Michael Zhang <zhan4854@umn.edu>"]
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
@ -15,7 +15,7 @@ strip = true
|
|||
lto = true
|
||||
|
||||
[[bin]]
|
||||
name = "raytracer1b"
|
||||
name = "raytracer1c"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
|
|
|
@ -8,8 +8,8 @@ ZIP := zip
|
|||
PANDOC := pandoc
|
||||
CONVERT := convert
|
||||
|
||||
HANDIN := ./hw1b.michael.zhang.zip
|
||||
BINARY := ./raytracer1b
|
||||
HANDIN := ./hw1c.michael.zhang.zip
|
||||
BINARY := ./raytracer1c
|
||||
WRITEUP := ./writeup.pdf
|
||||
SHOWCASE := ./showcase.png
|
||||
SOURCES := Cargo.toml $(shell find -name "*.rs")
|
||||
|
@ -31,7 +31,7 @@ $(BINARY): $(SOURCES)
|
|||
-e CARGO_TARGET_DIR=/usr/src/myapp/target/docker \
|
||||
rust \
|
||||
cargo build --profile release-handin
|
||||
mv target/docker/release-handin/raytracer1b $@
|
||||
mv target/docker/release-handin/raytracer1c $@
|
||||
|
||||
$(HANDIN): $(BINARY) $(WRITEUP) Makefile Cargo.toml Cargo.lock README.md $(EXAMPLES_PNG) $(EXAMPLES_PPM) $(SHOWCASE)
|
||||
$(ZIP) -r $@ src examples $^
|
||||
|
|
17
assignment-1c/examples/Hw1cSample1.txt
Executable file
17
assignment-1c/examples/Hw1cSample1.txt
Executable file
|
@ -0,0 +1,17 @@
|
|||
eye 0 0 0
|
||||
viewdir 0 0 -1
|
||||
updir 0 1 0
|
||||
hfov 60
|
||||
imsize 512 256
|
||||
bkgcolor 0.1 0.1 0.1
|
||||
light -2 1 0 1 1 1 1
|
||||
mtlcolor 1 0 1 1 1 1 0.1 0.4 0.4 20
|
||||
|
||||
|
||||
v -2 1 -5
|
||||
v -1 -1 -4
|
||||
v 1 -1 -4
|
||||
v 2 1 -6
|
||||
|
||||
f 1 2 3
|
||||
f 1 3 4
|
21
assignment-1c/examples/Hw1cSample2.txt
Executable file
21
assignment-1c/examples/Hw1cSample2.txt
Executable file
|
@ -0,0 +1,21 @@
|
|||
eye 0 0 0
|
||||
viewdir 0 0 -1
|
||||
updir 0 1 0
|
||||
hfov 60
|
||||
imsize 512 256
|
||||
bkgcolor 0.1 0.1 0.1
|
||||
light -2 1 0 1 1 1 1
|
||||
mtlcolor 1 0 1 1 1 1 0.1 0.4 0.4 20
|
||||
|
||||
|
||||
v -2 1 -5
|
||||
v -1 -1 -4
|
||||
v 1 -1 -4
|
||||
v 2 1 -6
|
||||
|
||||
vn -2 1 1
|
||||
vn -1 -1 1
|
||||
vn 2 1 1
|
||||
|
||||
f 1//1 2//2 3//3
|
||||
f 1 3 4
|
10
assignment-1c/examples/Hw1cSample3.txt
Executable file
10
assignment-1c/examples/Hw1cSample3.txt
Executable file
|
@ -0,0 +1,10 @@
|
|||
eye 2 -6 1
|
||||
viewdir -1 3 -0.5
|
||||
updir 0 0 1
|
||||
hfov 50
|
||||
imsize 512 512
|
||||
bkgcolor 0.5 0.7 0.9
|
||||
light 0 1 -1 0 1 1 1
|
||||
mtlcolor 0 1 0 1 1 1 0.2 0.8 0.1 20
|
||||
texture earthtexture.ppm
|
||||
sphere 0 0 0 2
|
|
@ -1,5 +1,7 @@
|
|||
#![doc = include_str!("../README.md")]
|
||||
|
||||
use nalgebra::Vector3;
|
||||
|
||||
#[macro_use]
|
||||
extern crate anyhow;
|
||||
#[macro_use]
|
||||
|
@ -11,3 +13,5 @@ pub mod image;
|
|||
pub mod ray;
|
||||
pub mod scene;
|
||||
pub mod utils;
|
||||
|
||||
pub type Point = Vector3<f64>;
|
||||
|
|
|
@ -5,9 +5,9 @@ use std::fs::File;
|
|||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::Result;
|
||||
use assignment_1b::image::Image;
|
||||
use assignment_1b::ray::Ray;
|
||||
use assignment_1b::scene::Scene;
|
||||
use assignment_1c::image::Image;
|
||||
use assignment_1c::ray::Ray;
|
||||
use assignment_1c::scene::Scene;
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use nalgebra::Vector3;
|
||||
use crate::Point;
|
||||
|
||||
/// A normalized parametric Ray of the form (origin + direction * time)
|
||||
///
|
||||
|
@ -6,13 +6,13 @@ use nalgebra::Vector3;
|
|||
/// time occurs on the ray.
|
||||
#[derive(Debug)]
|
||||
pub struct Ray {
|
||||
pub origin: Vector3<f64>,
|
||||
pub direction: Vector3<f64>,
|
||||
pub origin: Point,
|
||||
pub direction: Point,
|
||||
}
|
||||
|
||||
impl Ray {
|
||||
/// Construct a ray from endpoints
|
||||
pub fn from_endpoints(start: Vector3<f64>, end: Vector3<f64>) -> Self {
|
||||
pub fn from_endpoints(start: Point, end: Point) -> Self {
|
||||
let delta = (end - start).normalize();
|
||||
Ray {
|
||||
origin: start,
|
||||
|
@ -21,7 +21,7 @@ impl Ray {
|
|||
}
|
||||
|
||||
/// Evaluate the ray at a certain point in time, yielding a point
|
||||
pub fn eval(&self, time: f64) -> Vector3<f64> {
|
||||
pub fn eval(&self, time: f64) -> Point {
|
||||
self.origin + self.direction * time
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
use anyhow::Result;
|
||||
use nalgebra::Vector3;
|
||||
|
||||
use ordered_float::NotNan;
|
||||
|
||||
use crate::ray::Ray;
|
||||
use crate::utils::compute_rotation_matrix;
|
||||
use crate::{ray::Ray, Point};
|
||||
|
||||
use super::{illumination::IntersectionContext};
|
||||
use super::illumination::IntersectionContext;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Cylinder {
|
||||
pub center: Vector3<f64>,
|
||||
pub direction: Vector3<f64>,
|
||||
pub center: Point,
|
||||
pub direction: Point,
|
||||
pub radius: f64,
|
||||
pub length: f64,
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ impl Cylinder {
|
|||
) -> Result<Option<IntersectionContext>> {
|
||||
// Determine rotation matrix for turning the cylinder upright along the
|
||||
// Z-axis
|
||||
let target_direction = Vector3::new(0.0, 0.0, 1.0);
|
||||
let target_direction = Point::new(0.0, 0.0, 1.0);
|
||||
let rotation_matrix =
|
||||
compute_rotation_matrix(self.direction, target_direction)?;
|
||||
let inverse_rotation_matrix =
|
||||
|
@ -153,7 +153,7 @@ impl Cylinder {
|
|||
}
|
||||
|
||||
let normal_rotated =
|
||||
Vector3::new(0.0, 0.0, rotated_point.z - rotated_cylinder_center.z)
|
||||
Point::new(0.0, 0.0, rotated_point.z - rotated_cylinder_center.z)
|
||||
.normalize();
|
||||
let normal = inverse_rotation_matrix * normal_rotated;
|
||||
|
||||
|
@ -179,23 +179,21 @@ impl Cylinder {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use nalgebra::Vector3;
|
||||
|
||||
use crate::{ray::Ray};
|
||||
use crate::{ray::Ray, Point};
|
||||
|
||||
use super::Cylinder;
|
||||
|
||||
#[test]
|
||||
fn test_cylinder() {
|
||||
let cylinder = Cylinder {
|
||||
center: Vector3::new(0.0, 0.0, 0.0),
|
||||
direction: Vector3::new(0.0, 1.0, 0.0),
|
||||
center: Point::new(0.0, 0.0, 0.0),
|
||||
direction: Point::new(0.0, 1.0, 0.0),
|
||||
radius: 3.0,
|
||||
length: 4.0,
|
||||
};
|
||||
|
||||
let eye = Vector3::new(0.0, 3.0, 3.0);
|
||||
let end = Vector3::new(0.0, 2.0, 2.0);
|
||||
let eye = Point::new(0.0, 3.0, 3.0);
|
||||
let end = Point::new(0.0, 2.0, 2.0);
|
||||
let ray = Ray::from_endpoints(eye, end);
|
||||
|
||||
let res = cylinder.intersects_ray_at(&ray);
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use std::fmt::Debug;
|
||||
|
||||
use anyhow::Result;
|
||||
use nalgebra::Vector3;
|
||||
|
||||
use crate::image::Color;
|
||||
use crate::ray::Ray;
|
||||
use crate::utils::cross;
|
||||
use crate::Point;
|
||||
|
||||
use super::cylinder::Cylinder;
|
||||
use super::illumination::IntersectionContext;
|
||||
|
@ -46,16 +46,16 @@ pub struct Object {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct Rect {
|
||||
pub upper_left: Vector3<f64>,
|
||||
pub upper_right: Vector3<f64>,
|
||||
pub lower_left: Vector3<f64>,
|
||||
pub lower_right: Vector3<f64>,
|
||||
pub upper_left: Point,
|
||||
pub upper_right: Point,
|
||||
pub lower_left: Point,
|
||||
pub lower_right: Point,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Material {
|
||||
pub diffuse_color: Vector3<f64>,
|
||||
pub specular_color: Vector3<f64>,
|
||||
pub diffuse_color: Point,
|
||||
pub specular_color: Point,
|
||||
|
||||
pub k_a: f64,
|
||||
pub k_d: f64,
|
||||
|
@ -67,7 +67,7 @@ pub struct Material {
|
|||
pub enum LightKind {
|
||||
/// A point light source exists at a point and emits light in all directions
|
||||
Point {
|
||||
location: Vector3<f64>,
|
||||
location: Point,
|
||||
|
||||
/// Whether light attenuation is enabled for this light
|
||||
attenuation: Option<Attenuation>,
|
||||
|
@ -75,7 +75,7 @@ pub enum LightKind {
|
|||
|
||||
/// A directional light source exists at an infinitely far location but emits
|
||||
/// light in a specific direction
|
||||
Directional { direction: Vector3<f64> },
|
||||
Directional { direction: Point },
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -84,13 +84,13 @@ pub struct Light {
|
|||
pub kind: LightKind,
|
||||
|
||||
/// The color, or intensity, of the light source
|
||||
pub color: Vector3<f64>,
|
||||
pub color: Point,
|
||||
}
|
||||
|
||||
impl Light {
|
||||
/// Get the unit directional vector pointing from the given point to this
|
||||
/// light source
|
||||
pub fn direction_from(&self, point: Vector3<f64>) -> Vector3<f64> {
|
||||
pub fn direction_from(&self, point: Point) -> Point {
|
||||
match self.kind {
|
||||
LightKind::Point { location, .. } => location - point,
|
||||
LightKind::Directional { direction } => -direction,
|
||||
|
@ -200,7 +200,7 @@ impl Scene {
|
|||
pub fn pixel_translation_function(
|
||||
&self,
|
||||
distance: f64,
|
||||
) -> impl Fn(usize, usize) -> Vector3<f64> {
|
||||
) -> impl Fn(usize, usize) -> Point {
|
||||
let view_window = self.compute_viewing_window(distance);
|
||||
|
||||
let dx = view_window.upper_right - view_window.upper_left;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use std::iter;
|
||||
|
||||
use nalgebra::Vector3;
|
||||
use ordered_float::NotNan;
|
||||
use rand::Rng;
|
||||
use rayon::prelude::{
|
||||
|
@ -8,7 +7,7 @@ use rayon::prelude::{
|
|||
ParallelIterator,
|
||||
};
|
||||
|
||||
use crate::{image::Color, ray::Ray, utils::dot};
|
||||
use crate::{image::Color, ray::Ray, utils::dot, Point};
|
||||
|
||||
use super::{
|
||||
data::{DepthCueing, Light, LightKind, Object},
|
||||
|
@ -39,7 +38,7 @@ impl Scene {
|
|||
let ambient_component = material.k_a * material.diffuse_color;
|
||||
|
||||
// Diffuse and specular lighting for each separate light
|
||||
let diffuse_and_specular: Vector3<f64> = self
|
||||
let diffuse_and_specular: Point = self
|
||||
.lights
|
||||
.par_iter()
|
||||
.map(|light| {
|
||||
|
@ -131,7 +130,7 @@ impl Scene {
|
|||
pub fn compute_shadow_coefficient(
|
||||
&self,
|
||||
obj_idx: usize,
|
||||
point: Vector3<f64>,
|
||||
point: Point,
|
||||
light: &Light,
|
||||
) -> f64 {
|
||||
let light_direction = light.direction_from(point);
|
||||
|
@ -200,8 +199,8 @@ impl Scene {
|
|||
|
||||
fn compute_soft_shadow_coefficient(
|
||||
&self,
|
||||
light_location: Vector3<f64>,
|
||||
original_intersection_point: Vector3<f64>,
|
||||
light_location: Point,
|
||||
original_intersection_point: Point,
|
||||
object: &Object,
|
||||
) -> f64 {
|
||||
// Soft shadows: jitter some rays here to somewhere close to the
|
||||
|
@ -215,7 +214,7 @@ impl Scene {
|
|||
let x = rng.gen_range(0.0..JITTER_RADIUS);
|
||||
let y = rng.gen_range(0.0..JITTER_RADIUS);
|
||||
let z = rng.gen_range(0.0..JITTER_RADIUS);
|
||||
let delta = Vector3::new(x, y, z);
|
||||
let delta = Point::new(x, y, z);
|
||||
light_location + delta
|
||||
})
|
||||
.take(JITTER_RAYS)
|
||||
|
@ -263,12 +262,12 @@ pub struct IntersectionContext {
|
|||
|
||||
/// The intersection point.
|
||||
#[derivative(PartialEq = "ignore", Ord = "ignore")]
|
||||
pub point: Vector3<f64>,
|
||||
pub point: Point,
|
||||
|
||||
/// The normal vector protruding from the surface of the object at the
|
||||
/// intersection point
|
||||
#[derivative(PartialEq = "ignore", Ord = "ignore")]
|
||||
pub normal: Vector3<f64>,
|
||||
pub normal: Point,
|
||||
}
|
||||
|
||||
impl Eq for IntersectionContext {}
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
use std::{fs::File, io::Read, path::Path};
|
||||
|
||||
use anyhow::Result;
|
||||
use nalgebra::Vector3;
|
||||
|
||||
use crate::scene::{
|
||||
cylinder::Cylinder,
|
||||
data::{Attenuation, Light, LightKind, Material, Object},
|
||||
sphere::Sphere,
|
||||
Scene,
|
||||
use crate::{
|
||||
scene::{
|
||||
cylinder::Cylinder,
|
||||
data::{Attenuation, Light, LightKind, Material, Object},
|
||||
sphere::Sphere,
|
||||
Scene,
|
||||
},
|
||||
Point,
|
||||
};
|
||||
|
||||
use super::data::{DepthCueing, ObjectKind};
|
||||
|
@ -56,11 +58,7 @@ impl Scene {
|
|||
let read_vec3 = |start: usize| {
|
||||
ensure!(parts.len() >= start + 3, "Vec3 requires 3 components.");
|
||||
|
||||
Ok(Vector3::new(
|
||||
parts[start],
|
||||
parts[start + 1],
|
||||
parts[start + 2],
|
||||
))
|
||||
Ok(Point::new(parts[start], parts[start + 1], parts[start + 2]))
|
||||
};
|
||||
|
||||
match keyword {
|
||||
|
|
|
@ -6,9 +6,9 @@ pub mod sphere;
|
|||
|
||||
use nalgebra::Vector3;
|
||||
|
||||
use crate::image::Color;
|
||||
use crate::{image::Color, Point};
|
||||
|
||||
use self::data::{DepthCueing, Light, Material, Object, Attenuation};
|
||||
use self::data::{Attenuation, DepthCueing, Light, Material, Object};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Scene {
|
||||
|
@ -31,4 +31,6 @@ pub struct Scene {
|
|||
pub materials: Vec<Material>,
|
||||
pub lights: Vec<Light>,
|
||||
pub objects: Vec<Object>,
|
||||
|
||||
pub vertices: Vec<Point>,
|
||||
}
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
use anyhow::Result;
|
||||
use nalgebra::Vector3;
|
||||
use ordered_float::NotNan;
|
||||
|
||||
use crate::{ray::Ray, utils::min_f64};
|
||||
use crate::{ray::Ray, utils::min_f64, Point};
|
||||
|
||||
use super::illumination::IntersectionContext;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Sphere {
|
||||
pub center: Vector3<f64>,
|
||||
pub center: Point,
|
||||
pub radius: f64,
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@ use anyhow::Result;
|
|||
use nalgebra::{Matrix3, Vector3};
|
||||
use ordered_float::NotNan;
|
||||
|
||||
use crate::Point;
|
||||
|
||||
/// Finds the minimum of an iterator of f64s, ignoring any NaN values
|
||||
#[inline]
|
||||
pub fn min_f64<I>(i: I) -> Option<f64>
|
||||
|
@ -28,17 +30,17 @@ where
|
|||
|
||||
/// Dot-product between two 3D vectors.
|
||||
#[inline]
|
||||
pub fn dot(a: Vector3<f64>, b: Vector3<f64>) -> f64 {
|
||||
pub fn dot(a: Point, b: Point) -> f64 {
|
||||
a.x * b.x + a.y * b.y + a.z * b.z
|
||||
}
|
||||
|
||||
/// Cross-product between two 3D vectors.
|
||||
#[inline]
|
||||
pub fn cross(a: Vector3<f64>, b: Vector3<f64>) -> Vector3<f64> {
|
||||
pub fn cross(a: Point, b: Point) -> Point {
|
||||
let x = a.y * b.z - a.z * b.y;
|
||||
let y = a.z * b.x - a.x * b.z;
|
||||
let z = a.x * b.y - a.y * b.x;
|
||||
Vector3::new(x, y, z)
|
||||
Point::new(x, y, z)
|
||||
}
|
||||
|
||||
/// Calculate the rotation matrix between the 2 given vectors
|
||||
|
|
Loading…
Reference in a new issue