Added cylinder primitive
This commit is contained in:
@@ -2,6 +2,8 @@ use nalgebra::Point3;
|
||||
use pixels::{wgpu, PixelsContext};
|
||||
use std::time::Instant;
|
||||
|
||||
const INIT_FILE: &str = "test.rhai";
|
||||
|
||||
const BUFFER_PROPORTION_INIT: f32 = 1.0;
|
||||
const BUFFER_PROPORTION_MIN: f32 = 0.5;
|
||||
const BUFFER_PROPORTION_MAX: f32 = 1.0;
|
||||
@@ -83,7 +85,7 @@ impl Gui {
|
||||
last_frame: Instant::now(),
|
||||
last_cursor: None,
|
||||
event: None,
|
||||
filename: String::new(),
|
||||
filename: String::from(INIT_FILE),
|
||||
ray_num: RAYS_INIT,
|
||||
buffer_proportion: BUFFER_PROPORTION_INIT,
|
||||
camera_eye: Point3::new(CAMERA_INIT, CAMERA_INIT, CAMERA_INIT),
|
||||
|
||||
126
src/primitive.rs
126
src/primitive.rs
@@ -1,4 +1,3 @@
|
||||
#[warn(dead_code)]
|
||||
use crate::ray::Ray;
|
||||
use crate::{EPSILON, EPSILON_VECTOR, INFINITY};
|
||||
use nalgebra::{distance, Point3, Unit, Vector3};
|
||||
@@ -255,28 +254,130 @@ impl Primitive for Circle {
|
||||
}
|
||||
|
||||
// CYLINDER -----------------------------------------------------------------
|
||||
struct Cylinder {
|
||||
#[derive(Clone)]
|
||||
pub struct Cylinder {
|
||||
radius: f32,
|
||||
base: f32,
|
||||
height: f32,
|
||||
base_circle: Circle,
|
||||
height_circle: Circle,
|
||||
top: f32,
|
||||
base_circle: Arc<dyn Primitive>,
|
||||
top_circle: Arc<dyn Primitive>,
|
||||
material: Arc<Material>,
|
||||
bounding_box: BoundingBox,
|
||||
}
|
||||
|
||||
impl Cylinder {}
|
||||
impl Cylinder {
|
||||
pub fn new(radius: f32, base: f32, top: f32, material: Arc<Material>) -> Arc<dyn Primitive> {
|
||||
let base_circle = Circle::new(
|
||||
Point3::new(0.0, base, 0.0),
|
||||
radius,
|
||||
Vector3::new(0.0, -1.0, 0.0),
|
||||
Arc::clone(&material),
|
||||
);
|
||||
let top_circle = Circle::new(
|
||||
Point3::new(0.0, top, 0.0),
|
||||
radius,
|
||||
Vector3::new(0.0, 1.0, 0.0),
|
||||
Arc::clone(&material),
|
||||
);
|
||||
let bln = Point3::new(-radius, base, -radius);
|
||||
let trf = Point3::new(radius, top, radius);
|
||||
Arc::new(Cylinder {
|
||||
radius,
|
||||
base,
|
||||
top,
|
||||
base_circle,
|
||||
top_circle,
|
||||
material,
|
||||
bounding_box: BoundingBox { bln, trf },
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Primitive for Cylinder {
|
||||
fn intersect_ray(&self, ray: &Ray) -> Option<Intersection> {
|
||||
todo!()
|
||||
}
|
||||
let point = &ray.a;
|
||||
let dir = &ray.b;
|
||||
let (ax, ay, az) = (point.x, point.y, point.z);
|
||||
let (bx, by, bz) = (dir.x, dir.y, dir.z);
|
||||
let a = bx * bx + bz * bz;
|
||||
let b = 2.0 * ax * bx + 2.0 * az * bz;
|
||||
let c = ax * ax + az * az - self.radius * self.radius;
|
||||
|
||||
let t = match find_roots_quadratic(a, b, c) {
|
||||
Roots::No(_) => return None,
|
||||
Roots::One([x1]) => Some(x1),
|
||||
Roots::Two([x1, x2]) => {
|
||||
if x1 <= 0.0 && x2 <= 0.0 {
|
||||
return None;
|
||||
} else {
|
||||
if x1.abs() < x2.abs() {
|
||||
Some(x1)
|
||||
} else {
|
||||
Some(x2)
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
let cylinder_intersect = match t {
|
||||
None => None,
|
||||
Some(t) => {
|
||||
let intersect = ray.at_t(t);
|
||||
if intersect.y >= self.base && intersect.y <= self.top {
|
||||
let normal = Vector3::new(2.0 * intersect.x, 0.0, 2.0 * intersect.z);
|
||||
Some(Intersection {
|
||||
point: intersect,
|
||||
normal: Unit::new_normalize(normal),
|
||||
material: Arc::clone(&self.material),
|
||||
incidence: ray.b,
|
||||
distance: t,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
};
|
||||
let base_intersect = self.base_circle.intersect_ray(ray);
|
||||
let top_intersect = self.top_circle.intersect_ray(ray);
|
||||
match (cylinder_intersect, base_intersect, top_intersect) {
|
||||
(None, None, None) => None,
|
||||
(Some(intersect), None, None) => Some(intersect),
|
||||
(None, Some(intersect), None) => Some(intersect),
|
||||
(None, None, Some(intersect)) => Some(intersect),
|
||||
(Some(intersect), Some(intersect_base), None) => {
|
||||
let cylinder_distance = distance(&ray.a, &intersect.point);
|
||||
let base_distance = distance(&ray.a, &intersect_base.point);
|
||||
match cylinder_distance < base_distance {
|
||||
true => Some(intersect),
|
||||
false => Some(intersect_base),
|
||||
}
|
||||
}
|
||||
(Some(intersect), None, Some(intersect_top)) => {
|
||||
let cylinder_distance = distance(&ray.a, &intersect.point);
|
||||
let top_distance = distance(&ray.a, &intersect_top.point);
|
||||
match cylinder_distance < top_distance {
|
||||
true => Some(intersect),
|
||||
false => Some(intersect_top),
|
||||
}
|
||||
}
|
||||
(None, Some(intersect_base), Some(intersect_top)) => {
|
||||
let base_distance = distance(&ray.a, &intersect_base.point);
|
||||
let top_distance = distance(&ray.a, &intersect_top.point);
|
||||
match base_distance < top_distance {
|
||||
true => Some(intersect_base),
|
||||
false => Some(intersect_top),
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn get_material(&self) -> Arc<Material> {
|
||||
todo!()
|
||||
Arc::clone(&self.material)
|
||||
}
|
||||
|
||||
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
|
||||
todo!()
|
||||
self.bounding_box.intersect_bounding_box(ray)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,7 +497,8 @@ impl Primitive for Cone {
|
||||
}
|
||||
|
||||
// RECTANGLE -----------------------------------------------------------------
|
||||
struct Rectangle {
|
||||
#[derive(Clone)]
|
||||
pub struct Rectangle {
|
||||
position: Point3<f32>,
|
||||
normal: Vector3<f32>,
|
||||
width_direction: Vector3<f32>,
|
||||
@@ -407,7 +509,7 @@ struct Rectangle {
|
||||
}
|
||||
|
||||
impl Rectangle {
|
||||
fn new(
|
||||
pub fn new(
|
||||
position: Point3<f32>,
|
||||
normal: Vector3<f32>,
|
||||
width_direction: Vector3<f32>,
|
||||
|
||||
23
src/scene.rs
23
src/scene.rs
@@ -1,12 +1,6 @@
|
||||
#![allow(dead_code)]
|
||||
#![allow(unused_imports)]
|
||||
#![allow(unused_variables)]
|
||||
|
||||
use crate::camera::Camera;
|
||||
use crate::light::Light;
|
||||
use crate::primitive::Primitive;
|
||||
use crate::primitive::*;
|
||||
use crate::state::State;
|
||||
use crate::{camera::Camera, state};
|
||||
use nalgebra::{Matrix4, Point3, Vector3};
|
||||
use rhai::{Engine, EvalAltResult};
|
||||
use std::sync::Arc;
|
||||
@@ -144,13 +138,16 @@ impl Scene {
|
||||
.register_fn("Cone", Cone::new)
|
||||
.register_fn("ConeUnit", Cone::unit);
|
||||
engine
|
||||
.register_type::<Sphere>()
|
||||
.register_fn("Sphere", Sphere::new)
|
||||
.register_fn("SphereUnit", Sphere::unit);
|
||||
.register_type::<Cylinder>()
|
||||
.register_fn("Cylinder", Cylinder::new);
|
||||
engine
|
||||
.register_type::<Sphere>()
|
||||
.register_fn("Sphere", Sphere::new)
|
||||
.register_fn("SphereUnit", Sphere::unit);
|
||||
.register_type::<Circle>()
|
||||
.register_fn("Circle", Circle::new)
|
||||
.register_fn("CircleUnit", Circle::unit);
|
||||
engine
|
||||
.register_type::<Rectangle>()
|
||||
.register_fn("Rectangle", Rectangle::new)
|
||||
.register_fn("RectangleUnit", Rectangle::unit);
|
||||
|
||||
let scene: Scene = engine.eval_file(filename.into())?;
|
||||
Ok(scene)
|
||||
|
||||
Reference in New Issue
Block a user