Added cylinder primitive
This commit is contained in:
@@ -2,6 +2,8 @@ use nalgebra::Point3;
|
|||||||
use pixels::{wgpu, PixelsContext};
|
use pixels::{wgpu, PixelsContext};
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
|
const INIT_FILE: &str = "test.rhai";
|
||||||
|
|
||||||
const BUFFER_PROPORTION_INIT: f32 = 1.0;
|
const BUFFER_PROPORTION_INIT: f32 = 1.0;
|
||||||
const BUFFER_PROPORTION_MIN: f32 = 0.5;
|
const BUFFER_PROPORTION_MIN: f32 = 0.5;
|
||||||
const BUFFER_PROPORTION_MAX: f32 = 1.0;
|
const BUFFER_PROPORTION_MAX: f32 = 1.0;
|
||||||
@@ -83,7 +85,7 @@ impl Gui {
|
|||||||
last_frame: Instant::now(),
|
last_frame: Instant::now(),
|
||||||
last_cursor: None,
|
last_cursor: None,
|
||||||
event: None,
|
event: None,
|
||||||
filename: String::new(),
|
filename: String::from(INIT_FILE),
|
||||||
ray_num: RAYS_INIT,
|
ray_num: RAYS_INIT,
|
||||||
buffer_proportion: BUFFER_PROPORTION_INIT,
|
buffer_proportion: BUFFER_PROPORTION_INIT,
|
||||||
camera_eye: Point3::new(CAMERA_INIT, CAMERA_INIT, CAMERA_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::ray::Ray;
|
||||||
use crate::{EPSILON, EPSILON_VECTOR, INFINITY};
|
use crate::{EPSILON, EPSILON_VECTOR, INFINITY};
|
||||||
use nalgebra::{distance, Point3, Unit, Vector3};
|
use nalgebra::{distance, Point3, Unit, Vector3};
|
||||||
@@ -255,28 +254,130 @@ impl Primitive for Circle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CYLINDER -----------------------------------------------------------------
|
// CYLINDER -----------------------------------------------------------------
|
||||||
struct Cylinder {
|
#[derive(Clone)]
|
||||||
|
pub struct Cylinder {
|
||||||
radius: f32,
|
radius: f32,
|
||||||
base: f32,
|
base: f32,
|
||||||
height: f32,
|
top: f32,
|
||||||
base_circle: Circle,
|
base_circle: Arc<dyn Primitive>,
|
||||||
height_circle: Circle,
|
top_circle: Arc<dyn Primitive>,
|
||||||
material: Arc<Material>,
|
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 {
|
impl Primitive for Cylinder {
|
||||||
fn intersect_ray(&self, ray: &Ray) -> Option<Intersection> {
|
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> {
|
fn get_material(&self) -> Arc<Material> {
|
||||||
todo!()
|
Arc::clone(&self.material)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
|
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 -----------------------------------------------------------------
|
// RECTANGLE -----------------------------------------------------------------
|
||||||
struct Rectangle {
|
#[derive(Clone)]
|
||||||
|
pub struct Rectangle {
|
||||||
position: Point3<f32>,
|
position: Point3<f32>,
|
||||||
normal: Vector3<f32>,
|
normal: Vector3<f32>,
|
||||||
width_direction: Vector3<f32>,
|
width_direction: Vector3<f32>,
|
||||||
@@ -407,7 +509,7 @@ struct Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Rectangle {
|
impl Rectangle {
|
||||||
fn new(
|
pub fn new(
|
||||||
position: Point3<f32>,
|
position: Point3<f32>,
|
||||||
normal: Vector3<f32>,
|
normal: Vector3<f32>,
|
||||||
width_direction: Vector3<f32>,
|
width_direction: Vector3<f32>,
|
||||||
|
|||||||
23
src/scene.rs
23
src/scene.rs
@@ -1,12 +1,6 @@
|
|||||||
#![allow(dead_code)]
|
use crate::camera::Camera;
|
||||||
#![allow(unused_imports)]
|
|
||||||
#![allow(unused_variables)]
|
|
||||||
|
|
||||||
use crate::light::Light;
|
use crate::light::Light;
|
||||||
use crate::primitive::Primitive;
|
|
||||||
use crate::primitive::*;
|
use crate::primitive::*;
|
||||||
use crate::state::State;
|
|
||||||
use crate::{camera::Camera, state};
|
|
||||||
use nalgebra::{Matrix4, Point3, Vector3};
|
use nalgebra::{Matrix4, Point3, Vector3};
|
||||||
use rhai::{Engine, EvalAltResult};
|
use rhai::{Engine, EvalAltResult};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -144,13 +138,16 @@ impl Scene {
|
|||||||
.register_fn("Cone", Cone::new)
|
.register_fn("Cone", Cone::new)
|
||||||
.register_fn("ConeUnit", Cone::unit);
|
.register_fn("ConeUnit", Cone::unit);
|
||||||
engine
|
engine
|
||||||
.register_type::<Sphere>()
|
.register_type::<Cylinder>()
|
||||||
.register_fn("Sphere", Sphere::new)
|
.register_fn("Cylinder", Cylinder::new);
|
||||||
.register_fn("SphereUnit", Sphere::unit);
|
|
||||||
engine
|
engine
|
||||||
.register_type::<Sphere>()
|
.register_type::<Circle>()
|
||||||
.register_fn("Sphere", Sphere::new)
|
.register_fn("Circle", Circle::new)
|
||||||
.register_fn("SphereUnit", Sphere::unit);
|
.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())?;
|
let scene: Scene = engine.eval_file(filename.into())?;
|
||||||
Ok(scene)
|
Ok(scene)
|
||||||
|
|||||||
Reference in New Issue
Block a user