Fixed meshes

This commit is contained in:
STP
2023-11-28 18:21:54 -05:00
parent 055d14fb23
commit e756a001e9
3 changed files with 72 additions and 67 deletions

View File

@@ -21,9 +21,19 @@ scene.addLight("ambient", light);
let tri = TriangleUnit(); let tri = TriangleUnit();
let tri_node = Node(tri, material); let tri_node = Node(tri, material);
tri_node.active(true); tri_node.active(false);
scene.addNode("tri", tri_node); scene.addNode("tri", tri_node);
let circle = CircleUnit();
let circle_node = Node(circle, material);
circle_node.active(false);
scene.addNode("circle", circle_node);
let cone = ConeUnit();
let cone_node = Node(cone, material);
cone_node.active(true);
scene.addNode("cone", cone_node);
let sphere = SphereUnit(); let sphere = SphereUnit();
let sphere_node = Node(sphere, material); let sphere_node = Node(sphere, material);
@@ -39,10 +49,10 @@ ground_node.scale(scale,scale,scale);
ground_node.active(false); ground_node.active(false);
scene.addNode("ground", ground_node); scene.addNode("ground", ground_node);
// let mesh = Mesh("obj/cat.obj"); let mesh = Mesh("obj/cat.obj");
// let mesh_node = Node(mesh, material); let mesh_node = Node(mesh, material);
// mesh_node.active(false); mesh_node.active(false);
// scene.addNode("mesh", mesh_node); scene.addNode("mesh", mesh_node);
scene scene

View File

@@ -2,7 +2,7 @@ use crate::state::run;
use error_iter::ErrorIter; use error_iter::ErrorIter;
const EPSILON: f64 = 1e-8; const EPSILON: f64 = 1e-8;
const INFINITY: f64 = 1e-10; const INFINITY: f64 = 1e10;
use log::error; use log::error;
use std::env; use std::env;

View File

@@ -6,7 +6,7 @@ use crate::{
#[allow(dead_code)] #[allow(dead_code)]
use nalgebra::{distance, Point3, Vector3}; use nalgebra::{distance, Point3, Vector3};
use roots::{find_roots_quadratic, find_roots_quartic, Roots}; use roots::{find_roots_quadratic, find_roots_quartic, FloatType, 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;
@@ -89,6 +89,7 @@ pub struct Circle {
position: Point3<f64>, position: Point3<f64>,
radius: f64, radius: f64,
normal: Vector3<f64>, normal: Vector3<f64>,
constant: f64,
bounding_box: BoundingBox, bounding_box: BoundingBox,
} }
@@ -98,51 +99,48 @@ impl Circle {
let bln = position - radius_vec; let bln = position - radius_vec;
let trf = position + radius_vec; let trf = position + radius_vec;
let bounding_box = BoundingBox::new(bln, trf); let bounding_box = BoundingBox::new(bln, trf);
let normal = normal.normalize();
let constant = normal.dot(&position.coords);
Rc::new(Circle { Rc::new(Circle {
position, position,
radius, radius,
normal: normal.normalize(), normal,
constant,
bounding_box, bounding_box,
}) })
} }
pub fn unit() -> 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, 0.0, -1.0);
let radius = 1.0; let radius = 1.0;
Circle::new(position, radius, normal)
let bln = Point3::new(-radius, 0.0, -EPSILON);
let trf = Point3::new(radius, 0.0, EPSILON);
let bounding_box = BoundingBox { bln, trf };
Rc::new(Circle {
position,
normal,
radius,
bounding_box,
})
} }
} }
impl Primitive for Circle { impl Primitive for Circle {
fn intersect_ray(&self, ray: &Ray) -> Option<Intersection> { fn intersect_ray(&self, ray: &Ray) -> Option<Intersection> {
let constant = self.position.coords.dot(&self.normal); let n_dot_a = ray.a.coords.dot(&self.normal);
let denominator = ray.b.dot(&self.normal); let n_dot_b = ray.b.dot(&self.normal);
let t = (constant - ray.a.coords.dot(&self.normal)) / denominator; let t = (self.constant - n_dot_a) / n_dot_b;
if t > INFINITY { if t > INFINITY {
return None; return None;
}; };
let intersect = ray.at_t(t); let intersect = ray.at_t(t);
let distance = distance(&intersect, &self.position); //Distance to center of circle
match distance >= self.radius { let distance = distance(&intersect, &self.position).abs();
true => return None, match distance <= self.radius {
false => { true => {
return Some(Intersection { return Some(Intersection {
point: intersect, point: intersect,
normal: self.normal.normalize(), normal: self.normal,
distance: t, distance: t,
}) })
} }
false => return None,
} }
} }
@@ -271,56 +269,59 @@ impl Primitive for Cylinder {
// CONE ----------------------------------------------------------------- // CONE -----------------------------------------------------------------
#[derive(Clone)] #[derive(Clone)]
pub struct Cone { pub struct Cone {
radius: f64, height: f64,
base: f64, constant: f64,
apex: f64,
circle: Rc<dyn Primitive>, circle: Rc<dyn Primitive>,
bounding_box: BoundingBox, bounding_box: BoundingBox,
} }
impl Cone { impl Cone {
pub fn new(radius: f64, apex: f64, base: f64) -> Rc<dyn Primitive> { pub fn new(radius: f64, height: f64) -> Rc<dyn Primitive> {
let circle = Circle::new( let circle = Circle::new(
Point3::new(0.0, base, 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),
); );
let bln = Point3::new(-radius, base, -radius); let bln = Point3::new(-radius, 0.0, -radius);
let trf = Point3::new(radius, base + apex, radius); let trf = Point3::new(radius, height, radius);
let constant = radius * radius / (height * height);
Rc::new(Cone { Rc::new(Cone {
radius: radius / 2.0, height,
base, constant,
apex,
circle, circle,
bounding_box: BoundingBox { bln, trf }, bounding_box: BoundingBox { bln, trf },
}) })
} }
pub fn unit() -> Rc<dyn Primitive> { pub fn unit() -> Rc<dyn Primitive> {
Cone::new(1.0, 2.0, -1.0) Cone::new(0.5, 1.0)
} }
pub fn get_normal(&self, intersect: Point3<f64>) -> Vector3<f64> { pub fn get_normal(&self, intersect: Point3<f64>) -> Vector3<f64> {
let r = self.radius;
let h = self.apex;
let (x, y, z) = (intersect.x, intersect.y, intersect.z); let (x, y, z) = (intersect.x, intersect.y, intersect.z);
let normal = Vector3::new(2.0 * x, 2.0 * r * r * (h - y), 2.0 * z).normalize(); let dx = 2.0 * x;
normal let dy = 2.0 * self.constant * (self.height - y);
let dz = 2.0 * z;
Vector3::new(dx, dy, dz).normalize()
} }
} }
impl Primitive for Cone { impl Primitive for Cone {
fn intersect_ray(&self, ray: &Ray) -> Option<Intersection> { fn intersect_ray(&self, ray: &Ray) -> Option<Intersection> {
let point = &ray.a; let k1 = self.constant;
let dir = &ray.b; let k2 = self.height;
let (r, h) = (self.radius, self.apex); let a = ray.a.x;
let (a1, a2, a3) = (point.x, point.y, point.z); let b = ray.b.x;
let (b1, b2, b3) = (dir.x, dir.y, dir.z); let c = ray.a.y;
let r2 = r * r; let d = ray.b.y;
let a = b1 * b1 + b3 * b3 - r2 * (b2 * b2); let e = ray.a.z;
let b = 2.0 * (a1 * b1 + a3 * b3 + r2 * (h * b2 - a2 * b2)); let f = ray.b.z;
let c = a1 * a1 + a3 * a3 + r2 * (2.0 * h * a2 - h * h - a2 * a2);
let t = match find_roots_quadratic(a, b, c) { let t0 =
-c.powf(2.0) * k1 + 2.0 * c * k1 * k2 - k1 * k2.powf(2.0) + a.powf(2.0) + e.powf(2.0);
let t1 = -2.0 * c * d * k1 + 2.0 * d * k1 * k2 + 2.0 * a * b + 2.0 * e * f;
let t2 = -d.powf(2.0) * k1 + b.powf(2.0) + f.powf(2.0);
let t = match find_roots_quadratic(t2, t1, t0) {
Roots::No(_) => None, Roots::No(_) => None,
Roots::One([x1]) => Some(x1), Roots::One([x1]) => Some(x1),
Roots::Two([x1, x2]) => { Roots::Two([x1, x2]) => {
@@ -341,7 +342,7 @@ impl Primitive for Cone {
None => None, None => None,
Some(t) => { Some(t) => {
let intersect = ray.at_t(t); let intersect = ray.at_t(t);
match intersect.y >= self.base && intersect.y <= self.apex { match intersect.y >= 0.0 && intersect.y <= self.height {
true => Some(Intersection { true => Some(Intersection {
point: intersect, point: intersect,
normal: self.get_normal(intersect), normal: self.get_normal(intersect),
@@ -358,14 +359,7 @@ impl Primitive for Cone {
(None, None) => None, (None, None) => None,
(Some(cone_intersect), None) => Some(cone_intersect), (Some(cone_intersect), None) => Some(cone_intersect),
(None, Some(circle_intersect)) => Some(circle_intersect), (None, Some(circle_intersect)) => Some(circle_intersect),
(Some(cone_intersect), Some(circle_intersect)) => { (Some(cone_intersect), Some(_)) => Some(cone_intersect),
let circle_distance = distance(&ray.a, &circle_intersect.point);
let cone_distance = distance(&ray.a, &cone_intersect.point);
match cone_distance < circle_distance {
true => Some(cone_intersect),
false => Some(circle_intersect),
}
}
} }
} }
@@ -505,18 +499,19 @@ impl Primitive for Cube {
} }
//Get normal of intersection point //Get normal of intersection point
//t1 is bln t2 is trf
let normal = if tmin == t1.x { let normal = if tmin == t1.x {
Vector3::new(1.0, 0.0, 0.0) Vector3::new(-1.0, 0.0, 0.0)
} else if tmin == t1.y { } else if tmin == t1.y {
Vector3::new(0.0, -1.0, 0.0) Vector3::new(0.0, -1.0, 0.0)
} else if tmin == t1.z { } else if tmin == t1.z {
Vector3::new(0.0, 0.0, 1.0) Vector3::new(0.0, 0.0, -1.0)
} else if tmin == t2.x { } else if tmin == t2.x {
Vector3::new(-1.0, 0.0, 0.0) Vector3::new(1.0, 0.0, 0.0)
} else if tmin == t2.y { } else if tmin == t2.y {
Vector3::new(0.0, 1.0, 0.0) Vector3::new(0.0, 1.0, 0.0)
} else { } else {
Vector3::new(0.0, 0.0, -1.0) Vector3::new(0.0, 0.0, 1.0)
}; };
Some(Intersection { Some(Intersection {