Changed to f64 floating point

This commit is contained in:
STP
2023-11-25 14:35:11 -05:00
parent 348be665c9
commit 4721a3cc09
10 changed files with 326 additions and 273 deletions

View File

@@ -2,32 +2,32 @@ use crate::ray::Ray;
use crate::{EPSILON, INFINITY};
use nalgebra::{Matrix4, Perspective3, Point3, Unit, Vector3};
const ZNEAR: f32 = EPSILON;
const ZFAR: f32 = INFINITY;
const ZNEAR: f64 = EPSILON;
const ZFAR: f64 = INFINITY;
#[allow(dead_code)]
#[derive(Clone)]
pub struct Camera {
eye: Point3<f32>,
target: Point3<f32>,
up: Vector3<f32>,
fovy: f32,
eye: Point3<f64>,
target: Point3<f64>,
up: Vector3<f64>,
fovy: f64,
width: u32,
height: u32,
matrix: Matrix4<f32>,
inverse: Matrix4<f32>,
matrix: Matrix4<f64>,
inverse: Matrix4<f64>,
pub rays: Vec<Ray>,
}
#[allow(dead_code)]
impl Camera {
pub fn new(
eye: Point3<f32>,
target: Point3<f32>,
up: Vector3<f32>,
eye: Point3<f64>,
target: Point3<f64>,
up: Vector3<f64>,
width: u32,
height: u32,
fovy: f32,
fovy: f64,
) -> Self {
let (matrix, inverse) = build_matrix_and_inverse(&eye, &target, &up, width, height, fovy);
let rays = cast_rays(&eye, &target, &up, width, height, fovy);
@@ -45,10 +45,10 @@ impl Camera {
}
pub fn new_sizeless(
eye: Point3<f32>,
target: Point3<f32>,
up: Vector3<f32>,
fovy: f32,
eye: Point3<f64>,
target: Point3<f64>,
up: Vector3<f64>,
fovy: f64,
) -> Self {
Camera::new(eye, target, up, 1, 1, fovy)
}
@@ -71,7 +71,7 @@ impl Camera {
)
}
pub fn build_matrix_and_inverse(&self) -> (Matrix4<f32>, Matrix4<f32>) {
pub fn build_matrix_and_inverse(&self) -> (Matrix4<f64>, Matrix4<f64>) {
build_matrix_and_inverse(
&self.eye,
&self.target,
@@ -92,21 +92,21 @@ impl Camera {
let h_width = 2.0 * (fovh_radians / 2.0).tan();
let v_height = 2.0 * (fovy_radians / 2.0).tan();
//All good
let d_hor_vec = hor * (h_width / self.width as f64) as f32;
let d_vert_vec = vert * (v_height / self.height as f64) as f32;
let d_hor_vec = hor * (h_width / self.width as f64) as f64;
let d_vert_vec = vert * (v_height / self.height as f64) as f64;
let half_w = self.width as i32 / 2;
let half_h = self.height as i32 / 2;
let horizontal = (x as i32 - half_w) as f32 * (d_hor_vec);
let vertical = (-(y as i32) + half_h) as f32 * (d_vert_vec);
let horizontal = (x as i32 - half_w) as f64 * (d_hor_vec);
let vertical = (-(y as i32) + half_h) as f64 * (d_vert_vec);
let direction = view_direction + horizontal + vertical;
Ray::new(self.eye, Unit::new_normalize(direction))
}
pub fn set_position(&mut self, eye: Point3<f32>) {
pub fn set_position(&mut self, eye: Point3<f64>) {
self.eye = eye;
}
@@ -119,15 +119,15 @@ impl Camera {
}
fn build_matrix_and_inverse(
eye: &Point3<f32>,
target: &Point3<f32>,
up: &Vector3<f32>,
eye: &Point3<f64>,
target: &Point3<f64>,
up: &Vector3<f64>,
width: u32,
height: u32,
fovy: f32,
) -> (Matrix4<f32>, Matrix4<f32>) {
fovy: f64,
) -> (Matrix4<f64>, Matrix4<f64>) {
let view = Matrix4::look_at_lh(eye, target, up);
let aspect = width as f32 / height as f32;
let aspect = width as f64 / height as f64;
let proj = Perspective3::new(aspect, fovy, ZNEAR, ZFAR);
let matrix = proj.as_matrix() * view;
let inverse = view.try_inverse().expect("No view") * proj.inverse();
@@ -135,12 +135,12 @@ fn build_matrix_and_inverse(
}
fn cast_rays(
eye: &Point3<f32>,
target: &Point3<f32>,
up: &Vector3<f32>,
eye: &Point3<f64>,
target: &Point3<f64>,
up: &Vector3<f64>,
width: u32,
height: u32,
fovy: f32,
fovy: f64,
) -> Vec<Ray> {
let aspect = width as f64 / height as f64;
let fovy_radians = (fovy as f64).to_radians();
@@ -148,11 +148,11 @@ fn cast_rays(
let view_direction = (target - eye).normalize();
let hor = (view_direction.cross(&up)).normalize();
let vert = (view_direction.cross(&hor)).normalize();
let h_width = 2.0 * (fovh_radians / 2.0).tan() as f32;
let v_height = 2.0 * (fovy_radians / 2.0).tan() as f32;
let h_width = 2.0 * (fovh_radians / 2.0).tan() as f64;
let v_height = 2.0 * (fovy_radians / 2.0).tan() as f64;
//All good
let d_hor_vec = hor * (h_width / width as f32);
let d_vert_vec = vert * (v_height / height as f32);
let d_hor_vec = hor * (h_width / width as f64);
let d_vert_vec = vert * (v_height / height as f64);
let mut rays = Vec::with_capacity(width as usize * height as usize);
@@ -161,8 +161,8 @@ fn cast_rays(
for j in 0..height as i32 {
for i in 0..width as i32 {
let horizontal = (i - half_w) as f32 * (d_hor_vec);
let vertical = (-j + half_h) as f32 * (d_vert_vec);
let horizontal = (i - half_w) as f64 * (d_hor_vec);
let vertical = (-j + half_h) as f64 * (d_vert_vec);
let direction = view_direction + horizontal + vertical;
let ray = Ray::new(eye.clone(), Unit::new_normalize(direction));

View File

@@ -1,4 +1,4 @@
use crate::{camera::Camera, scene::Scene, state::INIT_FILE, UP_VECTOR, ZERO_VECTOR};
use crate::{camera::Camera, scene::Scene, state::INIT_FILE, UP_VECTOR_F32, ZERO_VECTOR_F32};
use imgui::*;
use nalgebra::{Point3, Vector3};
use pixels::{wgpu, PixelsContext};
@@ -102,8 +102,8 @@ impl Gui {
buffer_proportion: BUFFER_PROPORTION_INIT,
camera_eye: [CAMERA_INIT, CAMERA_INIT, CAMERA_INIT],
camera_target: ZERO_VECTOR.into(),
camera_up: UP_VECTOR.into(),
camera_target: ZERO_VECTOR_F32.into(),
camera_up: UP_VECTOR_F32.into(),
camera_fov: 110.0,
}
}
@@ -171,13 +171,18 @@ impl Gui {
// Create three input fields for x, y, and z components
if ui.button("Apply Camera") {
println!("Camera changed: {:?}", self.camera_eye);
let (eye, target, up) = (&self.camera_eye, &self.camera_target, &self.camera_up);
let (ex, ey, ez) = (eye[0] as f64, eye[1] as f64, eye[2] as f64);
let (tx, ty, tz) = (target[0] as f64, target[1] as f64, target[2] as f64);
let (ux, uy, uz) = (up[0] as f64, up[1] as f64, up[2] as f64);
let camera = Camera::new(
Point3::from_slice(&self.camera_eye),
Point3::from_slice(&self.camera_target),
Vector3::from_row_slice(&self.camera_up),
Point3::new(ex, ey, ez),
Point3::new(tx, ty, tz),
Vector3::new(ux, uy, uz),
1,
1,
self.camera_fov,
self.camera_fov as f64,
);
self.event = Some(GuiEvent::CameraUpdate(camera));
}

View File

@@ -2,20 +2,20 @@ use nalgebra::{Point3, Vector3};
#[derive(Clone)]
pub struct Light {
pub position: Point3<f32>,
pub colour: Vector3<f32>,
pub falloff: Vector3<f32>,
pub position: Point3<f64>,
pub colour: Vector3<f64>,
pub falloff: Vector3<f64>,
}
impl Light {
pub fn new(position: Point3<f32>, colour: Vector3<f32>, falloff: Vector3<f32>) -> Self {
pub fn new(position: Point3<f64>, colour: Vector3<f64>, falloff: Vector3<f64>) -> Self {
Light {
position,
colour,
falloff,
}
}
pub fn white(position: Point3<f32>) -> Self {
pub fn white(position: Point3<f64>) -> Self {
let colour = Vector3::new(1.0, 1.0, 1.0);
let falloff = Vector3::new(1.0, 0.0, 0.0);
Light::new(position, colour, falloff)

View File

@@ -1,11 +1,13 @@
use crate::state::run;
use error_iter::ErrorIter;
const EPSILON: f32 = 1e-9;
const INFINITY: f32 = f32::MAX;
const EPSILON_VECTOR: Vector3<f32> = Vector3::new(EPSILON, EPSILON, EPSILON);
static ZERO_VECTOR: Vector3<f32> = Vector3::new(0.0, 0.0, 0.0);
static UP_VECTOR: Vector3<f32> = Vector3::new(0.0, 1.0, 0.0);
const EPSILON: f64 = 1e-9;
const INFINITY: f64 = f64::MAX;
const EPSILON_VECTOR: Vector3<f64> = Vector3::new(EPSILON, EPSILON, EPSILON);
static ZERO_VECTOR: Vector3<f64> = Vector3::new(0.0, 0.0, 0.0);
static UP_VECTOR: Vector3<f64> = Vector3::new(0.0, 1.0, 0.0);
static ZERO_VECTOR_F32: Vector3<f32> = Vector3::new(0.0, 0.0, 0.0);
static UP_VECTOR_F32: Vector3<f32> = Vector3::new(0.0, 1.0, 0.0);
use log::error;
use std::env;

View File

@@ -10,12 +10,12 @@ use std::sync::Arc;
// MATERIAL -----------------------------------------------------------------
#[derive(Clone)]
pub struct Material {
pub kd: Vector3<f32>,
pub ks: Vector3<f32>,
pub shininess: f32,
pub kd: Vector3<f64>,
pub ks: Vector3<f64>,
pub shininess: f64,
}
impl Material {
pub fn new(kd: Vector3<f32>, ks: Vector3<f32>, shininess: f32) -> Arc<Self> {
pub fn new(kd: Vector3<f64>, ks: Vector3<f64>, shininess: f64) -> Arc<Self> {
Arc::new(Material { kd, ks, shininess })
}
pub fn magenta() -> Arc<Self> {
@@ -52,26 +52,26 @@ impl Material {
// INTERSECTION -----------------------------------------------------------------
pub struct Intersection {
// Information about an intersection
pub point: Point3<f32>,
pub normal: Unit<Vector3<f32>>,
pub incidence: Unit<Vector3<f32>>,
pub point: Point3<f64>,
pub normal: Unit<Vector3<f64>>,
pub incidence: Unit<Vector3<f64>>,
pub material: Arc<Material>,
pub distance: f32,
pub distance: f64,
}
// BOUNDING BOX -----------------------------------------------------------------
#[derive(Clone)]
struct BoundingBox {
bln: Point3<f32>,
trf: Point3<f32>,
bln: Point3<f64>,
trf: Point3<f64>,
}
impl BoundingBox {
fn new(bln: Point3<f32>, trf: Point3<f32>) -> Self {
fn new(bln: Point3<f64>, trf: Point3<f64>) -> Self {
let bln = bln - EPSILON_VECTOR;
let trf = trf + EPSILON_VECTOR;
BoundingBox { bln, trf }
}
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f64>> {
let t1 = (self.bln - ray.a).component_div(&ray.b);
let t2 = (self.trf - ray.a).component_div(&ray.b);
@@ -84,28 +84,28 @@ impl BoundingBox {
None
}
}
fn get_centroid(&self) -> Point3<f32> {
fn get_centroid(&self) -> Point3<f64> {
self.bln + (self.trf - self.bln) / 2.0
}
}
// PRIMITIVE TRAIT -----------------------------------------------------------------
pub trait Primitive: Send + Sync {
fn intersect_ray(&self, ray: &Ray) -> Option<Intersection>;
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>>;
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f64>>;
fn get_material(&self) -> Arc<Material>;
}
// SPHERE -----------------------------------------------------------------
#[derive(Clone)]
pub struct Sphere {
position: Point3<f32>,
radius: f32,
position: Point3<f64>,
radius: f64,
bounding_box: BoundingBox,
material: Arc<Material>,
}
impl Sphere {
pub fn new(position: Point3<f32>, radius: f32, material: Arc<Material>) -> Arc<dyn Primitive> {
pub fn new(position: Point3<f64>, radius: f64, material: Arc<Material>) -> Arc<dyn Primitive> {
let radius_vec = Vector3::new(radius, radius, radius);
let bln = position - radius_vec;
let trf = position + radius_vec;
@@ -166,7 +166,7 @@ impl Primitive for Sphere {
Arc::clone(&self.material)
}
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f64>> {
return self.bounding_box.intersect_bounding_box(ray);
}
}
@@ -174,18 +174,18 @@ impl Primitive for Sphere {
// CIRCLE -----------------------------------------------------------------
#[derive(Clone)]
pub struct Circle {
position: Point3<f32>,
radius: f32,
normal: Vector3<f32>,
position: Point3<f64>,
radius: f64,
normal: Vector3<f64>,
material: Arc<Material>,
bounding_box: BoundingBox,
}
impl Circle {
pub fn new(
position: Point3<f32>,
radius: f32,
normal: Vector3<f32>,
position: Point3<f64>,
radius: f64,
normal: Vector3<f64>,
material: Arc<Material>,
) -> Arc<dyn Primitive> {
let radius_vec = Vector3::new(radius, radius, radius);
@@ -249,7 +249,7 @@ impl Primitive for Circle {
Arc::clone(&self.material)
}
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f64>> {
self.bounding_box.intersect_bounding_box(ray)
}
}
@@ -257,9 +257,9 @@ impl Primitive for Circle {
// CYLINDER -----------------------------------------------------------------
#[derive(Clone)]
pub struct Cylinder {
radius: f32,
base: f32,
top: f32,
radius: f64,
base: f64,
top: f64,
base_circle: Arc<dyn Primitive>,
top_circle: Arc<dyn Primitive>,
material: Arc<Material>,
@@ -267,7 +267,7 @@ pub struct Cylinder {
}
impl Cylinder {
pub fn new(radius: f32, base: f32, top: f32, material: Arc<Material>) -> Arc<dyn Primitive> {
pub fn new(radius: f64, base: f64, top: f64, material: Arc<Material>) -> Arc<dyn Primitive> {
let base_circle = Circle::new(
Point3::new(0.0, base, 0.0),
radius,
@@ -377,7 +377,7 @@ impl Primitive for Cylinder {
Arc::clone(&self.material)
}
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f64>> {
self.bounding_box.intersect_bounding_box(ray)
}
}
@@ -385,16 +385,16 @@ impl Primitive for Cylinder {
// CONE -----------------------------------------------------------------
#[derive(Clone)]
pub struct Cone {
radius: f32,
base: f32,
apex: f32,
radius: f64,
base: f64,
apex: f64,
circle: Arc<dyn Primitive>,
material: Arc<Material>,
bounding_box: BoundingBox,
}
impl Cone {
pub fn new(radius: f32, apex: f32, base: f32, material: Arc<Material>) -> Arc<dyn Primitive> {
pub fn new(radius: f64, apex: f64, base: f64, material: Arc<Material>) -> Arc<dyn Primitive> {
let circle = Circle::new(
Point3::new(0.0, base, 0.0),
radius,
@@ -416,7 +416,7 @@ impl Cone {
Cone::new(1.0, 2.0, -1.0, material)
}
pub fn get_normal(&self, intersect: Point3<f32>) -> Vector3<f32> {
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);
@@ -492,7 +492,7 @@ impl Primitive for Cone {
Arc::clone(&self.material)
}
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f64>> {
self.bounding_box.intersect_bounding_box(ray)
}
}
@@ -500,22 +500,22 @@ impl Primitive for Cone {
// RECTANGLE -----------------------------------------------------------------
#[derive(Clone)]
pub struct Rectangle {
position: Point3<f32>,
normal: Vector3<f32>,
width_direction: Vector3<f32>,
position: Point3<f64>,
normal: Vector3<f64>,
width_direction: Vector3<f64>,
material: Arc<Material>,
width: f32,
height: f32,
width: f64,
height: f64,
bounding_box: BoundingBox,
}
impl Rectangle {
pub fn new(
position: Point3<f32>,
normal: Vector3<f32>,
width_direction: Vector3<f32>,
width: f32,
height: f32,
position: Point3<f64>,
normal: Vector3<f64>,
width_direction: Vector3<f64>,
width: f64,
height: f64,
material: Arc<Material>,
) -> Arc<dyn Primitive> {
let normal = normal.normalize();
@@ -580,7 +580,7 @@ impl Primitive for Rectangle {
Arc::clone(&self.material)
}
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f64>> {
self.bounding_box.intersect_bounding_box(ray)
}
}
@@ -588,15 +588,15 @@ impl Primitive for Rectangle {
// BOX -----------------------------------------------------------------
#[derive(Clone)]
pub struct Cube {
width: f32,
height: f32,
depth: f32,
width: f64,
height: f64,
depth: f64,
material: Arc<Material>,
bounding_box: BoundingBox,
}
impl Cube {
pub fn new(width: f32, height: f32, depth: f32, material: Arc<Material>) -> Arc<dyn Primitive> {
pub fn new(width: f64, height: f64, depth: f64, material: Arc<Material>) -> Arc<dyn Primitive> {
let trf = Point3::new(width / 2.0, height / 2.0, depth / 2.0);
let bln = Point3::new(-width / 2.0, -height / 2.0, -depth / 2.0);
Arc::new(Cube {
@@ -665,7 +665,7 @@ impl Primitive for Cube {
}
}
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f64>> {
self.bounding_box.intersect_bounding_box(ray)
}
@@ -676,19 +676,19 @@ impl Primitive for Cube {
// TRIANGLE -----------------------------------------------------------------
struct Triangle {
u: Point3<f32>,
v: Point3<f32>,
w: Point3<f32>,
normal: Vector3<f32>,
u: Point3<f64>,
v: Point3<f64>,
w: Point3<f64>,
normal: Vector3<f64>,
material: Arc<Material>,
bounding_box: BoundingBox,
}
impl Triangle {
fn new(
u: Point3<f32>,
v: Point3<f32>,
w: Point3<f32>,
u: Point3<f64>,
v: Point3<f64>,
w: Point3<f64>,
material: Arc<Material>,
) -> Arc<dyn Primitive> {
let uv = v - u;
@@ -759,7 +759,7 @@ impl Primitive for Triangle {
Arc::clone(&self.material)
}
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f64>> {
self.bounding_box.intersect_bounding_box(ray)
}
}
@@ -800,7 +800,7 @@ impl Mesh {
fn from_file(filename: &str, material: Arc<Material>) -> Arc<dyn Primitive> {
let mut triangles: Vec<Arc<dyn Primitive>> = Vec::new();
let mut vertices: Vec<Point3<f32>> = Vec::new();
let mut vertices: Vec<Point3<f64>> = Vec::new();
let file = File::open(filename).expect("Failed to open file");
let reader = BufReader::new(file);
@@ -815,9 +815,9 @@ impl Mesh {
if let (Some(x_str), Some(y_str), Some(z_str)) =
(parts.next(), parts.next(), parts.next())
{
let x: f32 = x_str.parse().expect("Failed to parse vertex X");
let y: f32 = y_str.parse().expect("Failed to parse vertex Y");
let z: f32 = z_str.parse().expect("Failed to parse vertex Z");
let x: f64 = x_str.parse().expect("Failed to parse vertex X");
let y: f64 = y_str.parse().expect("Failed to parse vertex Y");
let z: f64 = z_str.parse().expect("Failed to parse vertex Z");
vertices.push(Point3::new(x, y, z));
}
}
@@ -873,7 +873,7 @@ impl Primitive for Mesh {
Arc::clone(&self.material)
}
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f64>> {
self.bounding_box.intersect_bounding_box(ray)
}
}
@@ -968,7 +968,7 @@ impl Primitive for SteinerSurface {
})
}
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f64>> {
self.bounding_box.intersect_bounding_box(ray)
}
@@ -977,7 +977,7 @@ impl Primitive for SteinerSurface {
}
}
fn smallest_non_zero(arr: &[f32]) -> Option<f32> {
fn smallest_non_zero(arr: &[f64]) -> Option<f64> {
for &num in arr {
if num >= 0.0 {
return Some(num);
@@ -988,13 +988,13 @@ fn smallest_non_zero(arr: &[f32]) -> Option<f32> {
#[derive(Clone)]
pub struct Torus {
inner_rad: f32,
outer_rad: f32,
inner_rad: f64,
outer_rad: f64,
material: Arc<Material>,
bounding_box: BoundingBox,
}
impl Torus {
pub fn new(inner_rad: f32, outer_rad: f32, material: Arc<Material>) -> Arc<dyn Primitive> {
pub fn new(inner_rad: f64, outer_rad: f64, material: Arc<Material>) -> Arc<dyn Primitive> {
// I need to find the bounding box for this shape
let trf = Point3::new(1.0, 1.0, 1.0);
let bln = Point3::new(-1.0, -1.0, -1.0);
@@ -1109,7 +1109,7 @@ impl Primitive for Torus {
})
}
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f64>> {
self.bounding_box.intersect_bounding_box(ray)
}
@@ -1178,7 +1178,7 @@ impl Primitive for AdamShape {
distance: t,
})
}
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f64>> {
self.bounding_box.intersect_bounding_box(ray)
}
@@ -1255,7 +1255,7 @@ impl Primitive for AdamShape2 {
distance: t,
})
}
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f64>> {
self.bounding_box.intersect_bounding_box(ray)
}
@@ -1342,7 +1342,7 @@ impl Primitive for AdamShape3 {
distance: t,
})
}
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f64>> {
self.bounding_box.intersect_bounding_box(ray)
}

View File

@@ -8,12 +8,12 @@ use nalgebra::{Point3, Unit, Vector3};
#[derive(Clone)]
pub struct Ray {
pub a: Point3<f32>,
pub b: Unit<Vector3<f32>>,
pub a: Point3<f64>,
pub b: Unit<Vector3<f64>>,
}
impl Ray {
pub fn new(a: Point3<f32>, b: Unit<Vector3<f32>>) -> Ray {
pub fn new(a: Point3<f64>, b: Unit<Vector3<f64>>) -> Ray {
Ray { a, b }
}
pub fn unit() -> Ray {
@@ -21,7 +21,7 @@ impl Ray {
let b = Unit::new_normalize(Vector3::new(0.0, 1.0, 0.0));
Ray { a, b }
}
pub fn at_t(&self, t: f32) -> Point3<f32> {
pub fn at_t(&self, t: f64) -> Point3<f64> {
self.a + self.b.into_inner() * (t + EPSILON)
}
//Shade a single ray

View File

@@ -68,11 +68,11 @@ impl Scene {
let mut engine = Engine::new();
engine
.register_type::<Vector3<f32>>()
.register_fn("V", Vector3::<f32>::new);
.register_type::<Vector3<f64>>()
.register_fn("V", Vector3::<f64>::new);
engine
.register_type::<Point3<f32>>()
.register_fn("P", Point3::<f32>::new);
.register_type::<Point3<f64>>()
.register_fn("P", Point3::<f64>::new);
engine
.register_type::<Scene>()
.register_fn("Scene", Scene::empty)

View File

@@ -4,6 +4,9 @@ use crate::camera::Camera;
use crate::{gui::Gui, scene::Scene};
use crate::{gui::GuiEvent, log_error};
use rand::seq::SliceRandom;
use rand::thread_rng;
use std::error::Error;
use std::sync::{Arc, Mutex};
@@ -21,6 +24,146 @@ const COLOUR_CLEAR: [u8; 4] = [0x22, 0x00, 0x11, 0xff];
pub const INIT_FILE: &str = "scene.rhai";
pub struct State {
scene: Scene,
camera: Camera,
window: Window,
buffer_width: u32,
buffer_height: u32,
pixels: Arc<Mutex<Pixels>>,
gui: Gui,
ray_queue: Vec<usize>,
}
impl State {
pub fn new(window: Window, pixels: Pixels, gui: Gui) -> Self {
let scene = Scene::empty();
let window_size = window.inner_size();
let camera = Camera::unit();
Self {
scene,
camera,
window,
buffer_width: window_size.width as u32,
buffer_height: window_size.height as u32,
pixels: Arc::new(Mutex::new(pixels)),
gui,
ray_queue: Vec::new(),
}
}
fn update(&mut self) -> Result<(), Box<dyn Error>> {
if let Some(event) = self.gui.event.take() {
match event {
GuiEvent::BufferResize(proportion) => self.resize_buffer(proportion)?,
GuiEvent::CameraUpdate(camera) => self.set_camera(camera)?,
GuiEvent::SceneLoad(scene) => {
self.scene = scene;
self.clear()?;
}
}
};
Ok(())
}
fn resize_buffer(&mut self, proportion: f32) -> Result<(), Box<dyn Error>> {
let size = self.window.inner_size();
self.buffer_width = (size.width as f32 * proportion) as u32;
self.buffer_height = (size.height as f32 * proportion) as u32;
self.camera.set_size(self.buffer_width, self.buffer_height);
self.clear()?;
let mut pixels = self.pixels.lock().unwrap();
pixels.resize_buffer(self.buffer_width, self.buffer_height)?;
Ok(())
}
fn resize(&mut self, size: &PhysicalSize<u32>) -> Result<(), Box<dyn Error>> {
let mut pixels = self.pixels.lock().unwrap();
pixels.resize_surface(size.width, size.height)?;
Ok(())
}
fn keyboard_input(&mut self, key: &KeyboardInput) {
if let Some(VirtualKeyCode::A) = key.virtual_keycode {
// Handle 'A' key event here
}
}
fn mouse_input(&mut self, _button: &MouseButton) {
// Handle mouse input here
}
fn draw(&mut self) -> Result<(), Box<dyn Error>> {
for _ in 0..self.gui.ray_num {
//Get random index from queue
let index = self.ray_queue.pop().unwrap();
//Shade colour for selected ray
let colour = &self.camera.rays[index].shade_ray(&self.scene);
//Assign colour to frame
let rgba = colour.map_or(COLOUR_CLEAR, |colour| [colour.x, colour.y, colour.z, 255]);
let mut pixels = self.pixels.lock().unwrap();
let frame = pixels.frame_mut();
frame[index * 4..(index + 1) * 4].copy_from_slice(&rgba);
if self.ray_queue.is_empty() {
break;
};
}
Ok(())
}
fn clear(&mut self) -> Result<(), Box<dyn Error>> {
let mut pixels = self.pixels.lock().unwrap();
let frame = pixels.frame_mut();
for pixel in frame.chunks_exact_mut(4) {
pixel.copy_from_slice(&[0x00, 0x00, 0x00, 0xff]);
}
Ok(())
}
fn set_camera(&mut self, camera: Camera) -> Result<(), Box<dyn Error>> {
self.clear()?;
self.reset_queue();
self.camera = camera;
self.camera.set_size(self.buffer_width, self.buffer_height);
Ok(())
}
fn reset_queue(&mut self) {
let size = self.buffer_height as usize * self.buffer_width as usize;
let mut ray_queue: Vec<usize> = (0..size).collect();
ray_queue.shuffle(&mut thread_rng());
self.ray_queue = ray_queue;
}
fn render(&mut self) -> Result<(), Box<dyn Error>> {
self.update()?; //Update state
if !self.ray_queue.is_empty() {
self.draw()?;
}
let pixels = self.pixels.lock().unwrap();
self.gui
.prepare(&self.window)
.expect("gui.prepare() failed"); //Prepare imgui
if let Err(e) = pixels.render_with(|encoder, render_target, context| {
context.scaling_renderer.render(encoder, render_target); // Render pixels
self.gui
.render(&self.window, encoder, render_target, context)?;
Ok(())
}) {
log_error("pixels.render", e);
};
Ok(())
}
}
pub fn run() -> Result<(), Box<dyn Error>> {
let event_loop = EventLoop::new();
let window = create_window(&event_loop);
@@ -83,138 +226,3 @@ fn handle_window_event(
};
Ok(())
}
pub struct State {
scene: Scene,
camera: Camera,
window: Window,
buffer_width: u32,
buffer_height: u32,
pixels: Arc<Mutex<Pixels>>,
gui: Gui,
index: usize,
finished: bool,
}
impl State {
pub fn new(window: Window, pixels: Pixels, gui: Gui) -> Self {
let scene = Scene::empty();
let window_size = window.inner_size();
let camera = Camera::unit();
Self {
scene,
camera,
window,
buffer_width: window_size.width as u32,
buffer_height: window_size.height as u32,
pixels: Arc::new(Mutex::new(pixels)),
gui,
index: 0,
finished: false,
}
}
fn update(&mut self) -> Result<(), Box<dyn Error>> {
if let Some(event) = self.gui.event.take() {
match event {
GuiEvent::BufferResize(proportion) => self.resize_buffer(proportion)?,
GuiEvent::CameraUpdate(camera) => self.set_camera(camera)?,
GuiEvent::SceneLoad(scene) => {
self.scene = scene;
self.clear()?;
}
}
};
Ok(())
}
fn resize_buffer(&mut self, proportion: f32) -> Result<(), Box<dyn Error>> {
let size = self.window.inner_size();
self.buffer_width = (size.width as f32 * proportion) as u32;
self.buffer_height = (size.height as f32 * proportion) as u32;
self.camera.set_size(self.buffer_width, self.buffer_height);
self.clear()?;
let mut pixels = self.pixels.lock().unwrap();
pixels.resize_buffer(self.buffer_width, self.buffer_height)?;
Ok(())
}
fn resize(&mut self, size: &PhysicalSize<u32>) -> Result<(), Box<dyn Error>> {
let mut pixels = self.pixels.lock().unwrap();
pixels.resize_surface(size.width, size.height)?;
Ok(())
}
fn keyboard_input(&mut self, key: &KeyboardInput) {
if let Some(VirtualKeyCode::A) = key.virtual_keycode {
// Handle 'A' key event here
}
}
fn mouse_input(&mut self, _button: &MouseButton) {
// Handle mouse input here
}
fn draw(&mut self) -> Result<(), Box<dyn Error>> {
for _ in 0..self.gui.ray_num {
let i = self.index as usize;
let camera = &self.camera;
let colour = camera.rays[i].shade_ray(&self.scene);
let rgba = colour.map_or(COLOUR_CLEAR, |colour| [colour.x, colour.y, colour.z, 255]);
let mut pixels = self.pixels.lock().unwrap();
let frame = pixels.frame_mut();
frame[i * 4..(i + 1) * 4].copy_from_slice(&rgba);
self.index = self.index + 1;
if self.index >= frame.len() / 4 {
self.finished = true;
return Ok(());
};
}
Ok(())
}
fn clear(&mut self) -> Result<(), Box<dyn Error>> {
self.index = 0;
self.finished = false;
let mut pixels = self.pixels.lock().unwrap();
let frame = pixels.frame_mut();
for pixel in frame.chunks_exact_mut(4) {
pixel.copy_from_slice(&[0x00, 0x00, 0x00, 0xff]);
}
Ok(())
}
fn set_camera(&mut self, camera: Camera) -> Result<(), Box<dyn Error>> {
self.clear()?;
self.camera = camera;
self.camera.set_size(self.buffer_width, self.buffer_height);
Ok(())
}
fn render(&mut self) -> Result<(), Box<dyn Error>> {
self.update()?; //Update state
if !self.finished {
self.draw()?;
}; //Draw to pixels
let pixels = self.pixels.lock().unwrap();
self.gui
.prepare(&self.window)
.expect("gui.prepare() failed"); //Prepare imgui
if let Err(e) = pixels.render_with(|encoder, render_target, context| {
context.scaling_renderer.render(encoder, render_target); // Render pixels
self.gui
.render(&self.window, encoder, render_target, context)?;
Ok(())
}) {
log_error("pixels.render", e);
};
Ok(())
}
}