Changed to f64 floating point
This commit is contained in:
@@ -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));
|
||||
|
||||
19
src/gui.rs
19
src/gui.rs
@@ -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));
|
||||
}
|
||||
|
||||
10
src/light.rs
10
src/light.rs
@@ -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)
|
||||
|
||||
12
src/main.rs
12
src/main.rs
@@ -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;
|
||||
|
||||
148
src/primitive.rs
148
src/primitive.rs
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
278
src/state.rs
278
src/state.rs
@@ -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(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user