Fixed meshes
This commit is contained in:
@@ -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
|
||||||
@@ -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;
|
||||||
|
|||||||
117
src/primitive.rs
117
src/primitive.rs
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user