Moved node & material to own files
This commit is contained in:
48
src/material.rs
Normal file
48
src/material.rs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#[allow(dead_code)]
|
||||||
|
use nalgebra::Vector3;
|
||||||
|
// MATERIAL -----------------------------------------------------------------
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Material {
|
||||||
|
pub kd: Vector3<f32>,
|
||||||
|
pub ks: Vector3<f32>,
|
||||||
|
pub shininess: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Material {
|
||||||
|
pub fn new(kd: Vector3<f64>, ks: Vector3<f64>, shininess: f64) -> Material {
|
||||||
|
let kd = kd.cast();
|
||||||
|
let ks = ks.cast();
|
||||||
|
let shininess = shininess as f32;
|
||||||
|
Material { kd, ks, shininess }
|
||||||
|
}
|
||||||
|
pub fn magenta() -> Material {
|
||||||
|
let kd = Vector3::new(1.0, 0.0, 1.0);
|
||||||
|
let ks = Vector3::new(1.0, 0.0, 1.0);
|
||||||
|
let shininess = 0.5;
|
||||||
|
Material { kd, ks, shininess }
|
||||||
|
}
|
||||||
|
pub fn turquoise() -> Material {
|
||||||
|
let kd = Vector3::new(0.25, 0.3, 0.7);
|
||||||
|
let ks = Vector3::new(0.25, 0.3, 0.7);
|
||||||
|
let shininess = 0.5;
|
||||||
|
Material { kd, ks, shininess }
|
||||||
|
}
|
||||||
|
pub fn red() -> Material {
|
||||||
|
let kd = Vector3::new(0.8, 0.0, 0.3);
|
||||||
|
let ks = Vector3::new(0.8, 0.3, 0.0);
|
||||||
|
let shininess = 0.5;
|
||||||
|
Material { kd, ks, shininess }
|
||||||
|
}
|
||||||
|
pub fn blue() -> Material {
|
||||||
|
let kd = Vector3::new(0.0, 0.3, 0.6);
|
||||||
|
let ks = Vector3::new(0.3, 0.0, 0.6);
|
||||||
|
let shininess = 0.5;
|
||||||
|
Material { kd, ks, shininess }
|
||||||
|
}
|
||||||
|
pub fn green() -> Material {
|
||||||
|
let kd = Vector3::new(0.0, 1.0, 0.0);
|
||||||
|
let ks = Vector3::new(0.0, 1.0, 0.0);
|
||||||
|
let shininess = 0.5;
|
||||||
|
Material { kd, ks, shininess }
|
||||||
|
}
|
||||||
|
}
|
||||||
97
src/node.rs
Normal file
97
src/node.rs
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
use crate::{material::Material, primitive::*};
|
||||||
|
use nalgebra::{Matrix4, Vector3};
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Node {
|
||||||
|
//Primitive
|
||||||
|
pub primitive: Rc<dyn Primitive>,
|
||||||
|
pub material: Material,
|
||||||
|
//Transformations
|
||||||
|
pub rotation: [f64; 3],
|
||||||
|
pub scale: [f64; 3],
|
||||||
|
pub translation: [f64; 3],
|
||||||
|
//Model matricies
|
||||||
|
pub model: Matrix4<f64>,
|
||||||
|
pub inv_model: Matrix4<f64>,
|
||||||
|
|
||||||
|
pub active: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Node {
|
||||||
|
//New node with no transformations
|
||||||
|
pub fn new(primitive: Rc<dyn Primitive>, material: Material) -> Node {
|
||||||
|
Node {
|
||||||
|
primitive,
|
||||||
|
material,
|
||||||
|
rotation: [0.0, 0.0, 0.0],
|
||||||
|
scale: [1.0, 1.0, 1.0],
|
||||||
|
translation: [0.0, 0.0, 0.0],
|
||||||
|
model: Matrix4::identity(),
|
||||||
|
inv_model: Matrix4::identity(),
|
||||||
|
|
||||||
|
active: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//New node with parent transformations
|
||||||
|
pub fn child(self, primitive: Rc<dyn Primitive>) -> Node {
|
||||||
|
let mut child = self.clone();
|
||||||
|
child.primitive = primitive;
|
||||||
|
child
|
||||||
|
}
|
||||||
|
//Toggle is a mesh is visible or not
|
||||||
|
pub fn set_active(&mut self, active: bool) {
|
||||||
|
self.active = active;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Rotate a mesh by adding to its rotation
|
||||||
|
pub fn rotate(&mut self, roll: f64, pitch: f64, yaw: f64) {
|
||||||
|
//Convert to radians
|
||||||
|
let roll = roll.to_radians();
|
||||||
|
// Convert pitch and yaw to radians
|
||||||
|
let pitch = pitch.to_radians();
|
||||||
|
let yaw = yaw.to_radians();
|
||||||
|
|
||||||
|
// Add the roll, pitch, and yaw to the current rotation
|
||||||
|
self.rotation[0] += roll;
|
||||||
|
self.rotation[1] += pitch;
|
||||||
|
self.rotation[2] += yaw;
|
||||||
|
|
||||||
|
// Recompute the model and inverse model matrices
|
||||||
|
self.compute();
|
||||||
|
}
|
||||||
|
// Translate a mesh by adding to its current position
|
||||||
|
pub fn translate(&mut self, x: f64, y: f64, z: f64) {
|
||||||
|
self.translation[0] += x;
|
||||||
|
self.translation[1] += y;
|
||||||
|
self.translation[2] += z;
|
||||||
|
|
||||||
|
// Recompute the model and inverse model matrices
|
||||||
|
self.compute();
|
||||||
|
}
|
||||||
|
// Scale a mesh by adding to its current scale
|
||||||
|
pub fn scale(&mut self, x: f64, y: f64, z: f64) {
|
||||||
|
self.scale[0] += x;
|
||||||
|
self.scale[1] += y;
|
||||||
|
self.scale[2] += z;
|
||||||
|
|
||||||
|
// Recompute the model and inverse model matrices
|
||||||
|
self.compute();
|
||||||
|
}
|
||||||
|
// This function computes the model and inverse model matrices
|
||||||
|
pub fn compute(&mut self) {
|
||||||
|
//Translation matrix
|
||||||
|
let translation = Vector3::from_row_slice(&self.translation);
|
||||||
|
let translation_matrix = Matrix4::new_translation(&translation);
|
||||||
|
// Scale matrix
|
||||||
|
let scale = &Vector3::from_row_slice(&self.scale);
|
||||||
|
let scale_matrix = Matrix4::new_nonuniform_scaling(&scale);
|
||||||
|
// Rotation matrix
|
||||||
|
let (roll, pitch, yaw) = (self.rotation[0], self.rotation[1], self.rotation[2]);
|
||||||
|
let rotation_matrix = Matrix4::from_euler_angles(roll, pitch, yaw);
|
||||||
|
// Compute the model matrix by combining the translation, rotation, and scale matrices
|
||||||
|
self.model = (translation_matrix * rotation_matrix * scale_matrix).cast();
|
||||||
|
// Compute the inverse model matrix by inverting the model matrix
|
||||||
|
self.inv_model = self.model.try_inverse().unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
333
src/primitive.rs
333
src/primitive.rs
@@ -1,127 +1,19 @@
|
|||||||
|
use crate::{
|
||||||
|
bvh::BoundingBox,
|
||||||
|
ray::{Intersection, Ray},
|
||||||
|
{EPSILON, INFINITY},
|
||||||
|
};
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
use crate::ray::Ray;
|
use nalgebra::{distance, Point3, Vector3};
|
||||||
use crate::{EPSILON, INFINITY};
|
|
||||||
use nalgebra::{distance, Matrix4, Point3, Vector3};
|
|
||||||
use roots::{find_roots_quadratic, find_roots_quartic, Roots};
|
use roots::{find_roots_quadratic, find_roots_quartic, Roots};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{BufRead, BufReader};
|
use std::io::{BufRead, BufReader};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
// MATERIAL -----------------------------------------------------------------
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Material {
|
|
||||||
pub kd: Vector3<f32>,
|
|
||||||
pub ks: Vector3<f32>,
|
|
||||||
pub shininess: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Material {
|
|
||||||
pub fn new(kd: Vector3<f64>, ks: Vector3<f64>, shininess: f64) -> Rc<Self> {
|
|
||||||
let kd = kd.cast();
|
|
||||||
let ks = ks.cast();
|
|
||||||
let shininess = shininess as f32;
|
|
||||||
Rc::new(Material { kd, ks, shininess })
|
|
||||||
}
|
|
||||||
pub fn magenta() -> Rc<Self> {
|
|
||||||
let kd = Vector3::new(1.0, 0.0, 1.0);
|
|
||||||
let ks = Vector3::new(1.0, 0.0, 1.0);
|
|
||||||
let shininess = 0.5;
|
|
||||||
Rc::new(Material { kd, ks, shininess })
|
|
||||||
}
|
|
||||||
pub fn turquoise() -> Rc<Self> {
|
|
||||||
let kd = Vector3::new(0.25, 0.3, 0.7);
|
|
||||||
let ks = Vector3::new(0.25, 0.3, 0.7);
|
|
||||||
let shininess = 0.5;
|
|
||||||
Rc::new(Material { kd, ks, shininess })
|
|
||||||
}
|
|
||||||
pub fn red() -> Rc<Self> {
|
|
||||||
let kd = Vector3::new(0.8, 0.0, 0.3);
|
|
||||||
let ks = Vector3::new(0.8, 0.3, 0.0);
|
|
||||||
let shininess = 0.5;
|
|
||||||
Rc::new(Material { kd, ks, shininess })
|
|
||||||
}
|
|
||||||
pub fn blue() -> Rc<Self> {
|
|
||||||
let kd = Vector3::new(0.0, 0.3, 0.6);
|
|
||||||
let ks = Vector3::new(0.3, 0.0, 0.6);
|
|
||||||
let shininess = 0.5;
|
|
||||||
Rc::new(Material { kd, ks, shininess })
|
|
||||||
}
|
|
||||||
pub fn green() -> Rc<Self> {
|
|
||||||
let kd = Vector3::new(0.0, 1.0, 0.0);
|
|
||||||
let ks = Vector3::new(0.0, 1.0, 0.0);
|
|
||||||
let shininess = 0.5;
|
|
||||||
Rc::new(Material { kd, ks, shininess })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// INTERSECTION -----------------------------------------------------------------
|
|
||||||
pub struct Intersection {
|
|
||||||
// Information about an intersection
|
|
||||||
pub point: Point3<f64>,
|
|
||||||
pub normal: Vector3<f64>,
|
|
||||||
pub incidence: Vector3<f64>,
|
|
||||||
pub material: Rc<Material>,
|
|
||||||
pub distance: f64,
|
|
||||||
}
|
|
||||||
impl Intersection {
|
|
||||||
pub fn transform(&self, trans: &Matrix4<f64>, inv_trans: &Matrix4<f64>) -> Intersection {
|
|
||||||
Intersection {
|
|
||||||
point: trans.transform_point(&self.point),
|
|
||||||
normal: inv_trans.transpose().transform_vector(&self.normal),
|
|
||||||
incidence: trans.transform_vector(&self.incidence),
|
|
||||||
material: self.material.clone(),
|
|
||||||
distance: self.distance,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// BOUNDING BOX -----------------------------------------------------------------
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct BoundingBox {
|
|
||||||
bln: Point3<f64>,
|
|
||||||
trf: Point3<f64>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BoundingBox {
|
|
||||||
fn new(bln: Point3<f64>, trf: Point3<f64>) -> Self {
|
|
||||||
let bln = bln + Vector3::new(EPSILON, EPSILON, EPSILON);
|
|
||||||
let trf = trf - Vector3::new(EPSILON, EPSILON, EPSILON);
|
|
||||||
BoundingBox { bln, trf }
|
|
||||||
}
|
|
||||||
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
|
||||||
let bln = &self.bln;
|
|
||||||
let trf = &self.trf;
|
|
||||||
let t1 = (bln - ray.a).component_div(&ray.b);
|
|
||||||
let t2 = (trf - ray.a).component_div(&ray.b);
|
|
||||||
|
|
||||||
let tmin = t1.inf(&t2).min();
|
|
||||||
let tmax = t1.sup(&t2).max();
|
|
||||||
|
|
||||||
if tmax >= tmin {
|
|
||||||
let intersect = ray.at_t(tmin);
|
|
||||||
|
|
||||||
// Check if the intersection is inside the box
|
|
||||||
if intersect.x > bln.x - EPSILON
|
|
||||||
|| intersect.x < trf.x + EPSILON
|
|
||||||
|| intersect.y > bln.y - EPSILON
|
|
||||||
|| intersect.y < trf.y + EPSILON
|
|
||||||
|| intersect.z > bln.z - EPSILON
|
|
||||||
|| intersect.z < trf.z + EPSILON
|
|
||||||
{
|
|
||||||
return true; // Intersection is outside the box
|
|
||||||
}
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn get_centroid(&self) -> Point3<f64> {
|
|
||||||
self.bln + (self.trf - self.bln) / 2.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// PRIMITIVE TRAIT -----------------------------------------------------------------
|
// PRIMITIVE TRAIT -----------------------------------------------------------------
|
||||||
pub trait Primitive {
|
pub trait Primitive {
|
||||||
fn intersect_ray(&self, ray: &Ray) -> Option<Intersection>;
|
fn intersect_ray(&self, ray: &Ray) -> Option<Intersection>;
|
||||||
fn intersect_bounding_box(&self, ray: &Ray) -> bool;
|
fn intersect_bounding_box(&self, ray: &Ray) -> bool;
|
||||||
fn get_material(&self) -> Rc<Material>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SPHERE -----------------------------------------------------------------
|
// SPHERE -----------------------------------------------------------------
|
||||||
@@ -130,11 +22,10 @@ pub struct Sphere {
|
|||||||
position: Point3<f64>,
|
position: Point3<f64>,
|
||||||
radius: f64,
|
radius: f64,
|
||||||
bounding_box: BoundingBox,
|
bounding_box: BoundingBox,
|
||||||
material: Rc<Material>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sphere {
|
impl Sphere {
|
||||||
pub fn new(position: Point3<f64>, radius: f64, material: Rc<Material>) -> Rc<dyn Primitive> {
|
pub fn new(position: Point3<f64>, radius: f64) -> Rc<dyn Primitive> {
|
||||||
let radius_vec = Vector3::new(radius, radius, radius);
|
let radius_vec = Vector3::new(radius, radius, radius);
|
||||||
let bln = position - radius_vec;
|
let bln = position - radius_vec;
|
||||||
let trf = position + radius_vec;
|
let trf = position + radius_vec;
|
||||||
@@ -143,12 +34,11 @@ impl Sphere {
|
|||||||
position,
|
position,
|
||||||
radius,
|
radius,
|
||||||
bounding_box,
|
bounding_box,
|
||||||
material,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unit(material: Rc<Material>) -> Rc<dyn Primitive> {
|
pub fn unit() -> Rc<dyn Primitive> {
|
||||||
Sphere::new(Point3::new(0.0, 0.0, 0.0), 1.0, material)
|
Sphere::new(Point3::new(0.0, 0.0, 0.0), 1.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,16 +74,10 @@ impl Primitive for Sphere {
|
|||||||
Some(Intersection {
|
Some(Intersection {
|
||||||
point: intersect,
|
point: intersect,
|
||||||
normal,
|
normal,
|
||||||
incidence: ray.b,
|
|
||||||
material: Rc::clone(&self.material),
|
|
||||||
distance: t,
|
distance: t,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_material(&self) -> Rc<Material> {
|
|
||||||
Rc::clone(&self.material)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
||||||
return self.bounding_box.intersect_bounding_box(ray);
|
return self.bounding_box.intersect_bounding_box(ray);
|
||||||
}
|
}
|
||||||
@@ -205,17 +89,11 @@ pub struct Circle {
|
|||||||
position: Point3<f64>,
|
position: Point3<f64>,
|
||||||
radius: f64,
|
radius: f64,
|
||||||
normal: Vector3<f64>,
|
normal: Vector3<f64>,
|
||||||
material: Rc<Material>,
|
|
||||||
bounding_box: BoundingBox,
|
bounding_box: BoundingBox,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Circle {
|
impl Circle {
|
||||||
pub fn new(
|
pub fn new(position: Point3<f64>, radius: f64, normal: Vector3<f64>) -> Rc<dyn Primitive> {
|
||||||
position: Point3<f64>,
|
|
||||||
radius: f64,
|
|
||||||
normal: Vector3<f64>,
|
|
||||||
material: Rc<Material>,
|
|
||||||
) -> Rc<dyn Primitive> {
|
|
||||||
let radius_vec = Vector3::new(radius, radius, radius);
|
let radius_vec = Vector3::new(radius, radius, radius);
|
||||||
let bln = position - radius_vec;
|
let bln = position - radius_vec;
|
||||||
let trf = position + radius_vec;
|
let trf = position + radius_vec;
|
||||||
@@ -224,16 +102,14 @@ impl Circle {
|
|||||||
position,
|
position,
|
||||||
radius,
|
radius,
|
||||||
normal: normal.normalize(),
|
normal: normal.normalize(),
|
||||||
material,
|
|
||||||
bounding_box,
|
bounding_box,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unit(material: Rc<Material>) -> Rc<dyn Primitive> {
|
pub fn unit() -> Rc<dyn Primitive> {
|
||||||
let position = Point3::new(0.0, 0.0, 0.0);
|
let position = Point3::new(0.0, 0.0, 0.0);
|
||||||
let normal = Vector3::new(0.0, 1.0, 0.0);
|
let normal = Vector3::new(0.0, 1.0, 0.0);
|
||||||
let radius = 1.0;
|
let radius = 1.0;
|
||||||
let material = material;
|
|
||||||
|
|
||||||
let bln = Point3::new(-radius, 0.0, -EPSILON);
|
let bln = Point3::new(-radius, 0.0, -EPSILON);
|
||||||
let trf = Point3::new(radius, 0.0, EPSILON);
|
let trf = Point3::new(radius, 0.0, EPSILON);
|
||||||
@@ -243,7 +119,6 @@ impl Circle {
|
|||||||
position,
|
position,
|
||||||
normal,
|
normal,
|
||||||
radius,
|
radius,
|
||||||
material,
|
|
||||||
bounding_box,
|
bounding_box,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -265,18 +140,12 @@ impl Primitive for Circle {
|
|||||||
return Some(Intersection {
|
return Some(Intersection {
|
||||||
point: intersect,
|
point: intersect,
|
||||||
normal: self.normal.normalize(),
|
normal: self.normal.normalize(),
|
||||||
incidence: ray.b,
|
|
||||||
material: Rc::clone(&self.material),
|
|
||||||
distance: t,
|
distance: t,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_material(&self) -> Rc<Material> {
|
|
||||||
Rc::clone(&self.material)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
||||||
self.bounding_box.intersect_bounding_box(ray)
|
self.bounding_box.intersect_bounding_box(ray)
|
||||||
}
|
}
|
||||||
@@ -289,23 +158,20 @@ pub struct Cylinder {
|
|||||||
height: f64,
|
height: f64,
|
||||||
base_circle: Rc<dyn Primitive>,
|
base_circle: Rc<dyn Primitive>,
|
||||||
top_circle: Rc<dyn Primitive>,
|
top_circle: Rc<dyn Primitive>,
|
||||||
material: Rc<Material>,
|
|
||||||
bounding_box: BoundingBox,
|
bounding_box: BoundingBox,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Cylinder {
|
impl Cylinder {
|
||||||
pub fn new(radius: f64, height: f64, material: Rc<Material>) -> Rc<dyn Primitive> {
|
pub fn new(radius: f64, height: f64) -> Rc<dyn Primitive> {
|
||||||
let base_circle = Circle::new(
|
let base_circle = Circle::new(
|
||||||
Point3::new(0.0, 0.0, 0.0),
|
Point3::new(0.0, 0.0, 0.0),
|
||||||
radius,
|
radius,
|
||||||
Vector3::new(0.0, -1.0, 0.0),
|
Vector3::new(0.0, -1.0, 0.0),
|
||||||
Rc::clone(&material),
|
|
||||||
);
|
);
|
||||||
let top_circle = Circle::new(
|
let top_circle = Circle::new(
|
||||||
Point3::new(0.0, height, 0.0),
|
Point3::new(0.0, height, 0.0),
|
||||||
radius,
|
radius,
|
||||||
Vector3::new(0.0, 1.0, 0.0),
|
Vector3::new(0.0, 1.0, 0.0),
|
||||||
Rc::clone(&material),
|
|
||||||
);
|
);
|
||||||
let bln = Point3::new(-radius, 0.0, -radius);
|
let bln = Point3::new(-radius, 0.0, -radius);
|
||||||
let trf = Point3::new(radius, height, radius);
|
let trf = Point3::new(radius, height, radius);
|
||||||
@@ -314,7 +180,6 @@ impl Cylinder {
|
|||||||
height,
|
height,
|
||||||
base_circle,
|
base_circle,
|
||||||
top_circle,
|
top_circle,
|
||||||
material,
|
|
||||||
bounding_box: BoundingBox { bln, trf },
|
bounding_box: BoundingBox { bln, trf },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -356,8 +221,6 @@ impl Primitive for Cylinder {
|
|||||||
Some(Intersection {
|
Some(Intersection {
|
||||||
point: intersect,
|
point: intersect,
|
||||||
normal: normal,
|
normal: normal,
|
||||||
incidence: ray.b,
|
|
||||||
material: Rc::clone(&self.material),
|
|
||||||
distance: t,
|
distance: t,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@@ -400,10 +263,6 @@ impl Primitive for Cylinder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_material(&self) -> Rc<Material> {
|
|
||||||
Rc::clone(&self.material)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
||||||
self.bounding_box.intersect_bounding_box(ray)
|
self.bounding_box.intersect_bounding_box(ray)
|
||||||
}
|
}
|
||||||
@@ -416,17 +275,15 @@ pub struct Cone {
|
|||||||
base: f64,
|
base: f64,
|
||||||
apex: f64,
|
apex: f64,
|
||||||
circle: Rc<dyn Primitive>,
|
circle: Rc<dyn Primitive>,
|
||||||
material: Rc<Material>,
|
|
||||||
bounding_box: BoundingBox,
|
bounding_box: BoundingBox,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Cone {
|
impl Cone {
|
||||||
pub fn new(radius: f64, apex: f64, base: f64, material: Rc<Material>) -> Rc<dyn Primitive> {
|
pub fn new(radius: f64, apex: f64, base: f64) -> Rc<dyn Primitive> {
|
||||||
let circle = Circle::new(
|
let circle = Circle::new(
|
||||||
Point3::new(0.0, base, 0.0),
|
Point3::new(0.0, base, 0.0),
|
||||||
radius,
|
radius,
|
||||||
Vector3::new(0.0, 1.0, 0.0),
|
Vector3::new(0.0, 1.0, 0.0),
|
||||||
Rc::clone(&material),
|
|
||||||
);
|
);
|
||||||
let bln = Point3::new(-radius, base, -radius);
|
let bln = Point3::new(-radius, base, -radius);
|
||||||
let trf = Point3::new(radius, base + apex, radius);
|
let trf = Point3::new(radius, base + apex, radius);
|
||||||
@@ -435,12 +292,11 @@ impl Cone {
|
|||||||
base,
|
base,
|
||||||
apex,
|
apex,
|
||||||
circle,
|
circle,
|
||||||
material,
|
|
||||||
bounding_box: BoundingBox { bln, trf },
|
bounding_box: BoundingBox { bln, trf },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub fn unit(material: Rc<Material>) -> Rc<dyn Primitive> {
|
pub fn unit() -> Rc<dyn Primitive> {
|
||||||
Cone::new(1.0, 2.0, -1.0, material)
|
Cone::new(1.0, 2.0, -1.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_normal(&self, intersect: Point3<f64>) -> Vector3<f64> {
|
pub fn get_normal(&self, intersect: Point3<f64>) -> Vector3<f64> {
|
||||||
@@ -489,8 +345,6 @@ impl Primitive for Cone {
|
|||||||
true => Some(Intersection {
|
true => Some(Intersection {
|
||||||
point: intersect,
|
point: intersect,
|
||||||
normal: self.get_normal(intersect),
|
normal: self.get_normal(intersect),
|
||||||
incidence: ray.b,
|
|
||||||
material: Rc::clone(&self.material),
|
|
||||||
distance: t,
|
distance: t,
|
||||||
}),
|
}),
|
||||||
false => None,
|
false => None,
|
||||||
@@ -515,10 +369,6 @@ impl Primitive for Cone {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_material(&self) -> Rc<Material> {
|
|
||||||
Rc::clone(&self.material)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
||||||
self.bounding_box.intersect_bounding_box(ray)
|
self.bounding_box.intersect_bounding_box(ray)
|
||||||
}
|
}
|
||||||
@@ -530,7 +380,6 @@ pub struct Rectangle {
|
|||||||
position: Point3<f64>,
|
position: Point3<f64>,
|
||||||
normal: Vector3<f64>,
|
normal: Vector3<f64>,
|
||||||
width_direction: Vector3<f64>,
|
width_direction: Vector3<f64>,
|
||||||
material: Rc<Material>,
|
|
||||||
width: f64,
|
width: f64,
|
||||||
height: f64,
|
height: f64,
|
||||||
bounding_box: BoundingBox,
|
bounding_box: BoundingBox,
|
||||||
@@ -543,7 +392,6 @@ impl Rectangle {
|
|||||||
width_direction: Vector3<f64>,
|
width_direction: Vector3<f64>,
|
||||||
width: f64,
|
width: f64,
|
||||||
height: f64,
|
height: f64,
|
||||||
material: Rc<Material>,
|
|
||||||
) -> Rc<dyn Primitive> {
|
) -> Rc<dyn Primitive> {
|
||||||
let normal = normal.normalize();
|
let normal = normal.normalize();
|
||||||
let width_direction = width_direction.normalize();
|
let width_direction = width_direction.normalize();
|
||||||
@@ -556,18 +404,16 @@ impl Rectangle {
|
|||||||
width_direction: width_direction.normalize(),
|
width_direction: width_direction.normalize(),
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
material,
|
|
||||||
bounding_box: BoundingBox { bln, trf },
|
bounding_box: BoundingBox { bln, trf },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub fn unit(material: Rc<Material>) -> Rc<dyn Primitive> {
|
pub fn unit() -> Rc<dyn Primitive> {
|
||||||
Rectangle::new(
|
Rectangle::new(
|
||||||
Point3::new(0.0, 0.0, 0.0),
|
Point3::new(0.0, 0.0, 0.0),
|
||||||
Vector3::new(0.0, 1.0, 0.0),
|
Vector3::new(0.0, 1.0, 0.0),
|
||||||
Vector3::new(1.0, 0.0, 0.0),
|
Vector3::new(1.0, 0.0, 0.0),
|
||||||
2.0,
|
2.0,
|
||||||
2.0,
|
2.0,
|
||||||
material,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -595,18 +441,12 @@ impl Primitive for Rectangle {
|
|||||||
return Some(Intersection {
|
return Some(Intersection {
|
||||||
point: intersect,
|
point: intersect,
|
||||||
normal: self.normal,
|
normal: self.normal,
|
||||||
incidence: ray.b,
|
|
||||||
material: Rc::clone(&self.material),
|
|
||||||
distance: t,
|
distance: t,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_material(&self) -> Rc<Material> {
|
|
||||||
Rc::clone(&self.material)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
||||||
self.bounding_box.intersect_bounding_box(ray)
|
self.bounding_box.intersect_bounding_box(ray)
|
||||||
}
|
}
|
||||||
@@ -617,24 +457,22 @@ impl Primitive for Rectangle {
|
|||||||
pub struct Cube {
|
pub struct Cube {
|
||||||
bln: Point3<f64>,
|
bln: Point3<f64>,
|
||||||
trf: Point3<f64>,
|
trf: Point3<f64>,
|
||||||
material: Rc<Material>,
|
|
||||||
bounding_box: BoundingBox,
|
bounding_box: BoundingBox,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Cube {
|
impl Cube {
|
||||||
pub fn new(bln: Point3<f64>, trf: Point3<f64>, material: Rc<Material>) -> Rc<dyn Primitive> {
|
pub fn new(bln: Point3<f64>, trf: Point3<f64>) -> Rc<dyn Primitive> {
|
||||||
Rc::new(Cube {
|
Rc::new(Cube {
|
||||||
bln,
|
bln,
|
||||||
trf,
|
trf,
|
||||||
material,
|
|
||||||
bounding_box: BoundingBox { bln, trf },
|
bounding_box: BoundingBox { bln, trf },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unit(material: Rc<Material>) -> Rc<dyn Primitive> {
|
pub fn unit() -> Rc<dyn Primitive> {
|
||||||
let bln = Point3::new(-1.0, -1.0, -1.0);
|
let bln = Point3::new(-1.0, -1.0, -1.0);
|
||||||
let trf = Point3::new(1.0, 1.0, 1.0);
|
let trf = Point3::new(1.0, 1.0, 1.0);
|
||||||
Cube::new(bln, trf, material)
|
Cube::new(bln, trf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -651,17 +489,17 @@ impl Primitive for Cube {
|
|||||||
let tmax = t1.sup(&t2).min();
|
let tmax = t1.sup(&t2).min();
|
||||||
|
|
||||||
// Check if there's an intersection between tmin and tmax
|
// Check if there's an intersection between tmin and tmax
|
||||||
if tmax >= tmin {
|
if tmax >= tmin && tmin > EPSILON {
|
||||||
// The ray intersects the box, and tmin is the entry point, tmax is the exit point
|
// The ray intersects the box, and tmin is the entry point, tmax is the exit point
|
||||||
let intersect = ray.at_t(tmin);
|
let intersect = ray.at_t(tmin);
|
||||||
|
|
||||||
// Check if the intersection is outside the box
|
// Check if the intersection is outside the box
|
||||||
if intersect.x < bln.x - EPSILON
|
if intersect.x < bln.x
|
||||||
|| intersect.x > trf.x + EPSILON
|
|| intersect.x > trf.x
|
||||||
|| intersect.y < bln.y - EPSILON
|
|| intersect.y < bln.y
|
||||||
|| intersect.y > trf.y + EPSILON
|
|| intersect.y > trf.y
|
||||||
|| intersect.z < bln.z - EPSILON
|
|| intersect.z < bln.z
|
||||||
|| intersect.z > trf.z + EPSILON
|
|| intersect.z > trf.z
|
||||||
{
|
{
|
||||||
return None; // Intersection is outside the box
|
return None; // Intersection is outside the box
|
||||||
}
|
}
|
||||||
@@ -684,8 +522,6 @@ impl Primitive for Cube {
|
|||||||
Some(Intersection {
|
Some(Intersection {
|
||||||
point: intersect,
|
point: intersect,
|
||||||
normal: normal,
|
normal: normal,
|
||||||
incidence: ray.b,
|
|
||||||
material: Rc::clone(&self.material),
|
|
||||||
distance: tmin,
|
distance: tmin,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@@ -696,10 +532,6 @@ impl Primitive for Cube {
|
|||||||
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
||||||
self.bounding_box.intersect_bounding_box(ray)
|
self.bounding_box.intersect_bounding_box(ray)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_material(&self) -> Rc<Material> {
|
|
||||||
Rc::clone(&self.material)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TRIANGLE -----------------------------------------------------------------
|
// TRIANGLE -----------------------------------------------------------------
|
||||||
@@ -710,17 +542,11 @@ pub struct Triangle {
|
|||||||
v: Point3<f64>,
|
v: Point3<f64>,
|
||||||
w: Point3<f64>,
|
w: Point3<f64>,
|
||||||
normal: Vector3<f64>,
|
normal: Vector3<f64>,
|
||||||
material: Rc<Material>,
|
|
||||||
bounding_box: BoundingBox,
|
bounding_box: BoundingBox,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Triangle {
|
impl Triangle {
|
||||||
pub fn new(
|
pub fn new(u: Point3<f64>, v: Point3<f64>, w: Point3<f64>) -> Rc<dyn Primitive> {
|
||||||
u: Point3<f64>,
|
|
||||||
v: Point3<f64>,
|
|
||||||
w: Point3<f64>,
|
|
||||||
material: Rc<Material>,
|
|
||||||
) -> Rc<dyn Primitive> {
|
|
||||||
let uv = v - u;
|
let uv = v - u;
|
||||||
let uw = w - u;
|
let uw = w - u;
|
||||||
let normal = uv.cross(&uw).normalize();
|
let normal = uv.cross(&uw).normalize();
|
||||||
@@ -732,17 +558,15 @@ impl Triangle {
|
|||||||
v,
|
v,
|
||||||
w,
|
w,
|
||||||
normal,
|
normal,
|
||||||
material,
|
|
||||||
bounding_box,
|
bounding_box,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn unit(material: Rc<Material>) -> Rc<dyn Primitive> {
|
pub fn unit() -> Rc<dyn Primitive> {
|
||||||
let u = Point3::new(-1.0, 0.0, -1.0);
|
let u = Point3::new(-1.0, -1.0, 0.0);
|
||||||
let v = Point3::new(0.0, 0.0, 1.0);
|
let v = Point3::new(0.0, 1.0, 0.0);
|
||||||
let w = Point3::new(1.0, 0.0, -1.0);
|
let w = Point3::new(1.0, -1.0, 0.0);
|
||||||
let material = material;
|
Triangle::new(u, v, w)
|
||||||
Triangle::new(u, v, w, material)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -777,8 +601,6 @@ impl Primitive for Triangle {
|
|||||||
Some(Intersection {
|
Some(Intersection {
|
||||||
point: intersect,
|
point: intersect,
|
||||||
normal: normal,
|
normal: normal,
|
||||||
incidence: ray.b,
|
|
||||||
material: Rc::clone(&self.material),
|
|
||||||
distance: t,
|
distance: t,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@@ -786,10 +608,6 @@ impl Primitive for Triangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_material(&self) -> Rc<Material> {
|
|
||||||
Rc::clone(&self.material)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
||||||
self.bounding_box.intersect_bounding_box(ray)
|
self.bounding_box.intersect_bounding_box(ray)
|
||||||
}
|
}
|
||||||
@@ -799,17 +617,15 @@ impl Primitive for Triangle {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Mesh {
|
pub struct Mesh {
|
||||||
triangles: Vec<Triangle>,
|
triangles: Vec<Triangle>,
|
||||||
material: Rc<Material>,
|
|
||||||
bounding_box: BoundingBox,
|
bounding_box: BoundingBox,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mesh {
|
impl Mesh {
|
||||||
pub fn new(triangles: Vec<Triangle>, material: Rc<Material>) -> Rc<dyn Primitive> {
|
pub fn new(triangles: Vec<Triangle>) -> Rc<dyn Primitive> {
|
||||||
// Calculate the bounding box for the entire mesh based on the bounding boxes of individual triangles
|
// Calculate the bounding box for the entire mesh based on the bounding boxes of individual triangles
|
||||||
let bounding_box = Mesh::compute_bounding_box(&triangles);
|
let bounding_box = Mesh::compute_bounding_box(&triangles);
|
||||||
Rc::new(Mesh {
|
Rc::new(Mesh {
|
||||||
triangles,
|
triangles,
|
||||||
material,
|
|
||||||
bounding_box,
|
bounding_box,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -828,7 +644,7 @@ impl Mesh {
|
|||||||
BoundingBox { bln, trf }
|
BoundingBox { bln, trf }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_file(filename: &str, material: Rc<Material>) -> Rc<dyn Primitive> {
|
pub fn from_file(filename: &str) -> Rc<dyn Primitive> {
|
||||||
let mut triangles: Vec<Triangle> = Vec::new();
|
let mut triangles: Vec<Triangle> = Vec::new();
|
||||||
let mut vertices: Vec<Point3<f64>> = Vec::new();
|
let mut vertices: Vec<Point3<f64>> = Vec::new();
|
||||||
|
|
||||||
@@ -872,13 +688,11 @@ impl Mesh {
|
|||||||
let bln = u.inf(&v).inf(&w);
|
let bln = u.inf(&v).inf(&w);
|
||||||
let trf = u.sup(&v).sup(&w);
|
let trf = u.sup(&v).sup(&w);
|
||||||
let bounding_box = BoundingBox { bln, trf };
|
let bounding_box = BoundingBox { bln, trf };
|
||||||
let material = material.clone();
|
|
||||||
triangles.push(Triangle {
|
triangles.push(Triangle {
|
||||||
u,
|
u,
|
||||||
v,
|
v,
|
||||||
w,
|
w,
|
||||||
normal,
|
normal,
|
||||||
material,
|
|
||||||
bounding_box,
|
bounding_box,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -888,7 +702,7 @@ impl Mesh {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Mesh::new(triangles, material)
|
Mesh::new(triangles)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -913,10 +727,6 @@ impl Primitive for Mesh {
|
|||||||
closest_intersect
|
closest_intersect
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_material(&self) -> Rc<Material> {
|
|
||||||
Rc::clone(&self.material)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
||||||
self.bounding_box.intersect_bounding_box(ray)
|
self.bounding_box.intersect_bounding_box(ray)
|
||||||
}
|
}
|
||||||
@@ -927,19 +737,17 @@ impl Primitive for Mesh {
|
|||||||
pub struct Torus {
|
pub struct Torus {
|
||||||
inner_rad: f64,
|
inner_rad: f64,
|
||||||
outer_rad: f64,
|
outer_rad: f64,
|
||||||
material: Rc<Material>,
|
|
||||||
bounding_box: BoundingBox,
|
bounding_box: BoundingBox,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Torus {
|
impl Torus {
|
||||||
pub fn new(inner_rad: f64, outer_rad: f64, material: Rc<Material>) -> Rc<dyn Primitive> {
|
pub fn new(inner_rad: f64, outer_rad: f64) -> Rc<dyn Primitive> {
|
||||||
// I need to find the bounding box for this shape
|
// I need to find the bounding box for this shape
|
||||||
let trf = Point3::new(1.0, 1.0, 1.0);
|
let trf = Point3::new(1.0, 1.0, 1.0);
|
||||||
let bln = Point3::new(-1.0, -1.0, -1.0);
|
let bln = Point3::new(-1.0, -1.0, -1.0);
|
||||||
Rc::new(Torus {
|
Rc::new(Torus {
|
||||||
inner_rad,
|
inner_rad,
|
||||||
outer_rad,
|
outer_rad,
|
||||||
material,
|
|
||||||
bounding_box: BoundingBox { bln, trf },
|
bounding_box: BoundingBox { bln, trf },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1042,8 +850,6 @@ impl Primitive for Torus {
|
|||||||
Some(Intersection {
|
Some(Intersection {
|
||||||
point,
|
point,
|
||||||
normal,
|
normal,
|
||||||
incidence: ray.b,
|
|
||||||
material: Rc::clone(&self.material),
|
|
||||||
distance: t,
|
distance: t,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1051,10 +857,6 @@ impl Primitive for Torus {
|
|||||||
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
||||||
self.bounding_box.intersect_bounding_box(ray)
|
self.bounding_box.intersect_bounding_box(ray)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_material(&self) -> Rc<Material> {
|
|
||||||
Rc::clone(&self.material)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GNOMON -----------------------------------------------------------------
|
// GNOMON -----------------------------------------------------------------
|
||||||
@@ -1063,28 +865,24 @@ pub struct Gnonom {
|
|||||||
x_cube: Rc<dyn Primitive>,
|
x_cube: Rc<dyn Primitive>,
|
||||||
y_cube: Rc<dyn Primitive>,
|
y_cube: Rc<dyn Primitive>,
|
||||||
z_cube: Rc<dyn Primitive>,
|
z_cube: Rc<dyn Primitive>,
|
||||||
material: Rc<Material>,
|
|
||||||
bounding_box: BoundingBox,
|
bounding_box: BoundingBox,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Gnonom {
|
impl Gnonom {
|
||||||
const GNONOM_WIDTH: f64 = 0.1;
|
const GNONOM_WIDTH: f64 = 0.1;
|
||||||
const GNONOM_LENGTH: f64 = 2.0;
|
const GNONOM_LENGTH: f64 = 2.0;
|
||||||
pub fn new(material: Rc<Material>) -> Rc<dyn Primitive> {
|
pub fn new() -> Rc<dyn Primitive> {
|
||||||
let x_cube = Cube::new(
|
let x_cube = Cube::new(
|
||||||
Point3::new(0.0, -Self::GNONOM_WIDTH, -Self::GNONOM_WIDTH),
|
Point3::new(0.0, -Self::GNONOM_WIDTH, -Self::GNONOM_WIDTH),
|
||||||
Point3::new(Self::GNONOM_LENGTH, Self::GNONOM_WIDTH, Self::GNONOM_WIDTH),
|
Point3::new(Self::GNONOM_LENGTH, Self::GNONOM_WIDTH, Self::GNONOM_WIDTH),
|
||||||
material.clone(),
|
|
||||||
);
|
);
|
||||||
let y_cube = Cube::new(
|
let y_cube = Cube::new(
|
||||||
Point3::new(-Self::GNONOM_WIDTH, 0.0, -Self::GNONOM_WIDTH),
|
Point3::new(-Self::GNONOM_WIDTH, 0.0, -Self::GNONOM_WIDTH),
|
||||||
Point3::new(Self::GNONOM_WIDTH, Self::GNONOM_LENGTH, Self::GNONOM_WIDTH),
|
Point3::new(Self::GNONOM_WIDTH, Self::GNONOM_LENGTH, Self::GNONOM_WIDTH),
|
||||||
material.clone(),
|
|
||||||
);
|
);
|
||||||
let z_cube = Cube::new(
|
let z_cube = Cube::new(
|
||||||
Point3::new(-Self::GNONOM_WIDTH, -Self::GNONOM_WIDTH, 0.0),
|
Point3::new(-Self::GNONOM_WIDTH, -Self::GNONOM_WIDTH, 0.0),
|
||||||
Point3::new(Self::GNONOM_WIDTH, Self::GNONOM_WIDTH, Self::GNONOM_LENGTH),
|
Point3::new(Self::GNONOM_WIDTH, Self::GNONOM_WIDTH, Self::GNONOM_LENGTH),
|
||||||
material.clone(),
|
|
||||||
);
|
);
|
||||||
let bounding_box = BoundingBox {
|
let bounding_box = BoundingBox {
|
||||||
bln: Point3::new(
|
bln: Point3::new(
|
||||||
@@ -1102,7 +900,6 @@ impl Gnonom {
|
|||||||
x_cube,
|
x_cube,
|
||||||
y_cube,
|
y_cube,
|
||||||
z_cube,
|
z_cube,
|
||||||
material,
|
|
||||||
bounding_box,
|
bounding_box,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1128,26 +925,20 @@ impl Primitive for Gnonom {
|
|||||||
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
||||||
self.bounding_box.intersect_bounding_box(ray)
|
self.bounding_box.intersect_bounding_box(ray)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_material(&self) -> Rc<Material> {
|
|
||||||
self.material.clone()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CROSS CAP ---------
|
// CROSS CAP ---------
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct CrossCap {
|
pub struct CrossCap {
|
||||||
material: Rc<Material>,
|
|
||||||
bounding_box: BoundingBox,
|
bounding_box: BoundingBox,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CrossCap {
|
impl CrossCap {
|
||||||
pub fn new(material: Rc<Material>) -> Rc<dyn Primitive> {
|
pub fn new() -> Rc<dyn Primitive> {
|
||||||
// I need to find the bounding box for this shape
|
// I need to find the bounding box for this shape
|
||||||
let trf = Point3::new(1.0, 1.0, 1.0);
|
let trf = Point3::new(1.0, 1.0, 1.0);
|
||||||
let bln = Point3::new(-1.0, -1.0, -1.0);
|
let bln = Point3::new(-1.0, -1.0, -1.0);
|
||||||
Rc::new(CrossCap {
|
Rc::new(CrossCap {
|
||||||
material,
|
|
||||||
bounding_box: BoundingBox { bln, trf },
|
bounding_box: BoundingBox { bln, trf },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1219,8 +1010,6 @@ impl Primitive for CrossCap {
|
|||||||
Some(Intersection {
|
Some(Intersection {
|
||||||
point,
|
point,
|
||||||
normal,
|
normal,
|
||||||
incidence: ray.b,
|
|
||||||
material: Rc::clone(&self.material),
|
|
||||||
distance: t,
|
distance: t,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1228,10 +1017,6 @@ impl Primitive for CrossCap {
|
|||||||
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
||||||
self.bounding_box.intersect_bounding_box(ray)
|
self.bounding_box.intersect_bounding_box(ray)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_material(&self) -> Rc<Material> {
|
|
||||||
Rc::clone(&self.material)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CROSS CAP 2 ---------
|
// CROSS CAP 2 ---------
|
||||||
@@ -1239,19 +1024,17 @@ impl Primitive for CrossCap {
|
|||||||
pub struct CrossCap2 {
|
pub struct CrossCap2 {
|
||||||
p: f64,
|
p: f64,
|
||||||
q: f64,
|
q: f64,
|
||||||
material: Rc<Material>,
|
|
||||||
bounding_box: BoundingBox,
|
bounding_box: BoundingBox,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CrossCap2 {
|
impl CrossCap2 {
|
||||||
pub fn new(p: f64, q: f64, material: Rc<Material>) -> Rc<dyn Primitive> {
|
pub fn new(p: f64, q: f64) -> Rc<dyn Primitive> {
|
||||||
// I need to find the bounding box for this shape
|
// I need to find the bounding box for this shape
|
||||||
let trf = Point3::new(1.0, 1.0, 1.0);
|
let trf = Point3::new(1.0, 1.0, 1.0);
|
||||||
let bln = Point3::new(-1.0, -1.0, -1.0);
|
let bln = Point3::new(-1.0, -1.0, -1.0);
|
||||||
Rc::new(CrossCap2 {
|
Rc::new(CrossCap2 {
|
||||||
p,
|
p,
|
||||||
q,
|
q,
|
||||||
material,
|
|
||||||
bounding_box: BoundingBox { bln, trf },
|
bounding_box: BoundingBox { bln, trf },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1348,8 +1131,6 @@ impl Primitive for CrossCap2 {
|
|||||||
Some(Intersection {
|
Some(Intersection {
|
||||||
point,
|
point,
|
||||||
normal,
|
normal,
|
||||||
incidence: ray.b,
|
|
||||||
material: Rc::clone(&self.material),
|
|
||||||
distance: t,
|
distance: t,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1357,26 +1138,20 @@ impl Primitive for CrossCap2 {
|
|||||||
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
||||||
self.bounding_box.intersect_bounding_box(ray)
|
self.bounding_box.intersect_bounding_box(ray)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_material(&self) -> Rc<Material> {
|
|
||||||
Rc::clone(&self.material)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Steiner ---------
|
// Steiner ---------
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Steiner {
|
pub struct Steiner {
|
||||||
material: Rc<Material>,
|
|
||||||
bounding_box: BoundingBox,
|
bounding_box: BoundingBox,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Steiner {
|
impl Steiner {
|
||||||
pub fn new(material: Rc<Material>) -> Rc<dyn Primitive> {
|
pub fn new() -> Rc<dyn Primitive> {
|
||||||
// I need to find the bounding box for this shape
|
// I need to find the bounding box for this shape
|
||||||
let trf = Point3::new(1.0, 1.0, 1.0);
|
let trf = Point3::new(1.0, 1.0, 1.0);
|
||||||
let bln = Point3::new(-1.0, -1.0, -1.0);
|
let bln = Point3::new(-1.0, -1.0, -1.0);
|
||||||
Rc::new(Steiner {
|
Rc::new(Steiner {
|
||||||
material,
|
|
||||||
bounding_box: BoundingBox { bln, trf },
|
bounding_box: BoundingBox { bln, trf },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1437,8 +1212,6 @@ impl Primitive for Steiner {
|
|||||||
Some(Intersection {
|
Some(Intersection {
|
||||||
point,
|
point,
|
||||||
normal,
|
normal,
|
||||||
incidence: ray.b,
|
|
||||||
material: Rc::clone(&self.material),
|
|
||||||
distance: t,
|
distance: t,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1446,26 +1219,20 @@ impl Primitive for Steiner {
|
|||||||
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
||||||
self.bounding_box.intersect_bounding_box(ray)
|
self.bounding_box.intersect_bounding_box(ray)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_material(&self) -> Rc<Material> {
|
|
||||||
Rc::clone(&self.material)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Steiner 2 ---------
|
// Steiner 2 ---------
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Steiner2 {
|
pub struct Steiner2 {
|
||||||
material: Rc<Material>,
|
|
||||||
bounding_box: BoundingBox,
|
bounding_box: BoundingBox,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Steiner2 {
|
impl Steiner2 {
|
||||||
pub fn new(material: Rc<Material>) -> Rc<dyn Primitive> {
|
pub fn new() -> Rc<dyn Primitive> {
|
||||||
// I need to find the bounding box for this shape
|
// I need to find the bounding box for this shape
|
||||||
let trf = Point3::new(1.0, 1.0, 1.0);
|
let trf = Point3::new(1.0, 1.0, 1.0);
|
||||||
let bln = Point3::new(-1.0, -1.0, -1.0);
|
let bln = Point3::new(-1.0, -1.0, -1.0);
|
||||||
Rc::new(Steiner2 {
|
Rc::new(Steiner2 {
|
||||||
material,
|
|
||||||
bounding_box: BoundingBox { bln, trf },
|
bounding_box: BoundingBox { bln, trf },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1537,8 +1304,6 @@ impl Primitive for Steiner2 {
|
|||||||
Some(Intersection {
|
Some(Intersection {
|
||||||
point,
|
point,
|
||||||
normal,
|
normal,
|
||||||
incidence: ray.b,
|
|
||||||
material: Rc::clone(&self.material),
|
|
||||||
distance: t,
|
distance: t,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1546,28 +1311,22 @@ impl Primitive for Steiner2 {
|
|||||||
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
||||||
self.bounding_box.intersect_bounding_box(ray)
|
self.bounding_box.intersect_bounding_box(ray)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_material(&self) -> Rc<Material> {
|
|
||||||
Rc::clone(&self.material)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Roman ---------
|
// Roman ---------
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Roman {
|
pub struct Roman {
|
||||||
k: f64,
|
k: f64,
|
||||||
material: Rc<Material>,
|
|
||||||
bounding_box: BoundingBox,
|
bounding_box: BoundingBox,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Roman {
|
impl Roman {
|
||||||
pub fn new(k: f64, material: Rc<Material>) -> Rc<dyn Primitive> {
|
pub fn new(k: f64) -> Rc<dyn Primitive> {
|
||||||
// I need to find the bounding box for this shape
|
// I need to find the bounding box for this shape
|
||||||
let trf = Point3::new(1.0, 1.0, 1.0);
|
let trf = Point3::new(1.0, 1.0, 1.0);
|
||||||
let bln = Point3::new(-1.0, -1.0, -1.0);
|
let bln = Point3::new(-1.0, -1.0, -1.0);
|
||||||
Rc::new(Roman {
|
Rc::new(Roman {
|
||||||
k,
|
k,
|
||||||
material,
|
|
||||||
bounding_box: BoundingBox { bln, trf },
|
bounding_box: BoundingBox { bln, trf },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1656,8 +1415,6 @@ impl Primitive for Roman {
|
|||||||
Some(Intersection {
|
Some(Intersection {
|
||||||
point,
|
point,
|
||||||
normal,
|
normal,
|
||||||
incidence: ray.b,
|
|
||||||
material: Rc::clone(&self.material),
|
|
||||||
distance: t,
|
distance: t,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1665,10 +1422,6 @@ impl Primitive for Roman {
|
|||||||
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
fn intersect_bounding_box(&self, ray: &Ray) -> bool {
|
||||||
self.bounding_box.intersect_bounding_box(ray)
|
self.bounding_box.intersect_bounding_box(ray)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_material(&self) -> Rc<Material> {
|
|
||||||
Rc::clone(&self.material)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn smallest_non_zero(arr: &[f64]) -> Option<f64> {
|
fn smallest_non_zero(arr: &[f64]) -> Option<f64> {
|
||||||
|
|||||||
92
src/scene.rs
92
src/scene.rs
@@ -1,96 +1,10 @@
|
|||||||
use crate::camera::Camera;
|
use crate::{camera::Camera, light::Light, material::*, node::*};
|
||||||
use crate::light::Light;
|
|
||||||
use crate::primitive::*;
|
|
||||||
use nalgebra::{Matrix4, Vector3};
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::rc::Rc;
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Node {
|
|
||||||
//Primitive
|
|
||||||
pub primitive: Rc<dyn Primitive>,
|
|
||||||
//Transformations
|
|
||||||
pub rotation: [f64; 3],
|
|
||||||
pub scale: [f64; 3],
|
|
||||||
pub translation: [f64; 3],
|
|
||||||
//Model matricies
|
|
||||||
pub model: Matrix4<f64>,
|
|
||||||
pub inv_model: Matrix4<f64>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Node {
|
|
||||||
//New node with no transformations
|
|
||||||
pub fn new(primitive: Rc<dyn Primitive>) -> Node {
|
|
||||||
Node {
|
|
||||||
primitive,
|
|
||||||
rotation: [0.0, 0.0, 0.0],
|
|
||||||
scale: [1.0, 1.0, 1.0],
|
|
||||||
translation: [0.0, 0.0, 0.0],
|
|
||||||
model: Matrix4::identity(),
|
|
||||||
inv_model: Matrix4::identity(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//New node with parent transformations
|
|
||||||
pub fn child(self, primitive: Rc<dyn Primitive>) -> Node {
|
|
||||||
let mut child = self.clone();
|
|
||||||
child.primitive = primitive;
|
|
||||||
child
|
|
||||||
}
|
|
||||||
//Rotate a mesh by adding to its rotation
|
|
||||||
pub fn rotate(&mut self, roll: f64, pitch: f64, yaw: f64) {
|
|
||||||
//Convert to radians
|
|
||||||
let roll = roll.to_radians();
|
|
||||||
// Convert pitch and yaw to radians
|
|
||||||
let pitch = pitch.to_radians();
|
|
||||||
let yaw = yaw.to_radians();
|
|
||||||
|
|
||||||
// Add the roll, pitch, and yaw to the current rotation
|
|
||||||
self.rotation[0] += roll;
|
|
||||||
self.rotation[1] += pitch;
|
|
||||||
self.rotation[2] += yaw;
|
|
||||||
|
|
||||||
// Recompute the model and inverse model matrices
|
|
||||||
self.compute();
|
|
||||||
}
|
|
||||||
// Translate a mesh by adding to its current position
|
|
||||||
pub fn translate(&mut self, x: f64, y: f64, z: f64) {
|
|
||||||
self.translation[0] += x;
|
|
||||||
self.translation[1] += y;
|
|
||||||
self.translation[2] += z;
|
|
||||||
|
|
||||||
// Recompute the model and inverse model matrices
|
|
||||||
self.compute();
|
|
||||||
}
|
|
||||||
// Scale a mesh by adding to its current scale
|
|
||||||
pub fn scale(&mut self, x: f64, y: f64, z: f64) {
|
|
||||||
self.scale[0] += x;
|
|
||||||
self.scale[1] += y;
|
|
||||||
self.scale[2] += z;
|
|
||||||
|
|
||||||
// Recompute the model and inverse model matrices
|
|
||||||
self.compute();
|
|
||||||
}
|
|
||||||
// This function computes the model and inverse model matrices
|
|
||||||
pub fn compute(&mut self) {
|
|
||||||
//Translation matrix
|
|
||||||
let translation = Vector3::from_row_slice(&self.translation);
|
|
||||||
let translation_matrix = Matrix4::new_translation(&translation);
|
|
||||||
// Scale matrix
|
|
||||||
let scale = &Vector3::from_row_slice(&self.scale);
|
|
||||||
let scale_matrix = Matrix4::new_nonuniform_scaling(&scale);
|
|
||||||
// Rotation matrix
|
|
||||||
let (roll, pitch, yaw) = (self.rotation[0], self.rotation[1], self.rotation[2]);
|
|
||||||
let rotation_matrix = Matrix4::from_euler_angles(roll, pitch, yaw);
|
|
||||||
// Compute the model matrix by combining the translation, rotation, and scale matrices
|
|
||||||
self.model = (translation_matrix * rotation_matrix * scale_matrix).cast();
|
|
||||||
// Compute the inverse model matrix by inverting the model matrix
|
|
||||||
self.inv_model = self.model.try_inverse().unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Scene {
|
pub struct Scene {
|
||||||
pub nodes: HashMap<String, Node>,
|
pub nodes: HashMap<String, Node>,
|
||||||
pub materials: HashMap<String, Rc<Material>>,
|
pub materials: HashMap<String, Material>,
|
||||||
pub lights: HashMap<String, Light>,
|
pub lights: HashMap<String, Light>,
|
||||||
pub cameras: HashMap<String, Camera>,
|
pub cameras: HashMap<String, Camera>,
|
||||||
}
|
}
|
||||||
@@ -110,7 +24,7 @@ impl Scene {
|
|||||||
self.nodes.insert(label, node);
|
self.nodes.insert(label, node);
|
||||||
}
|
}
|
||||||
// Adds a material to the scene
|
// Adds a material to the scene
|
||||||
pub fn add_material(&mut self, label: String, material: Rc<Material>) {
|
pub fn add_material(&mut self, label: String, material: Material) {
|
||||||
self.materials.insert(label, material);
|
self.materials.insert(label, material);
|
||||||
}
|
}
|
||||||
// Adds a light to the scene
|
// Adds a light to the scene
|
||||||
|
|||||||
Reference in New Issue
Block a user