From 7353855119b42ae15da6b5cfe56940d21267cbf4 Mon Sep 17 00:00:00 2001 From: ishanjain28 Date: Sat, 14 Mar 2020 16:38:55 +0530 Subject: [PATCH] Removed my own Vec3 implementation with ultraviolet::vec::Vec3 --- Cargo.lock | 25 ++++ Cargo.toml | 1 + README.md | 2 +- src/camera.rs | 33 ++--- src/demos/defocus_blur.rs | 27 ++-- src/demos/dielectric_material.rs | 21 +-- src/demos/diffuse_materials.rs | 29 ++-- src/demos/final_scene.rs | 47 +++--- src/demos/hitable_sphere.rs | 33 +++-- src/demos/linear_gradient_rectangle.rs | 25 ++-- src/demos/materials.rs | 21 +-- src/demos/mod.rs | 10 +- src/demos/positionable_camera.rs | 25 ++-- src/demos/simple_antialiasing.rs | 27 ++-- src/demos/simple_rectangle.rs | 2 +- src/demos/simple_sphere.rs | 35 ++--- src/demos/surface_normal_sphere.rs | 39 ++--- src/main.rs | 2 +- src/types/hitable.rs | 9 +- src/types/hitable_list.rs | 2 +- src/types/material.rs | 42 +++--- src/types/mod.rs | 2 - src/types/ray.rs | 4 +- src/types/sphere.rs | 19 +-- src/types/vec3.rs | 192 ------------------------- 25 files changed, 263 insertions(+), 411 deletions(-) delete mode 100644 src/types/vec3.rs diff --git a/Cargo.lock b/Cargo.lock index 270261d..86c643b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12,6 +12,12 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +[[package]] +name = "bytemuck" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37fa13df2292ecb479ec23aa06f4507928bef07839be9ef15281411076629431" + [[package]] name = "c2-chacha" version = "0.2.3" @@ -207,6 +213,7 @@ dependencies = [ "rand", "rayon", "sdl2", + "ultraviolet", ] [[package]] @@ -261,8 +268,26 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +[[package]] +name = "ultraviolet" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae513d44058e41a4669dc336b13a017ea96ad6984bac3797a3d49744e3ffa0ba" +dependencies = [ + "wide", +] + [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wide" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528f4316973b7d116d4d87634a4360c97de5d8664352104a130403c32e4b48e8" +dependencies = [ + "bytemuck", +] diff --git a/Cargo.toml b/Cargo.toml index 19c8102..99fd3e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,3 +8,4 @@ edition = "2018" sdl2 = "0.33.0" rand = "0.7.3" rayon = "1.3.0" +ultraviolet = "0.4.5" diff --git a/README.md b/README.md index aecbccf..73bbeba 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ fn render(&self, buf: &mut vec, width: usize, height: usize, samples: u8) { .into_par_iter() .for_each(move |i| { let world = self.world(); - let camera = self.camera(nx as f64 / ny as f64); + let camera = self.camera(nx as f32 / ny as f32); let start_y = j * ny; let start_x = i * nx; diff --git a/src/camera.rs b/src/camera.rs index abd8bf3..d2c0c01 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -1,14 +1,11 @@ -use { - crate::types::{Ray, Vec3}, - rand::Rng, -}; +use {crate::types::Ray, rand::Rng, ultraviolet::vec::Vec3}; pub struct Camera { origin: Vec3, horizontal: Vec3, vertical: Vec3, lower_left_corner: Vec3, - lens_radius: f64, + lens_radius: f32, // position vectors u: Vec3, @@ -26,20 +23,20 @@ impl Camera { look_from: Vec3, look_at: Vec3, v_up: Vec3, - vertical_fov: f64, - aspect: f64, - aperture: f64, - focus_distance: f64, + vertical_fov: f32, + aspect: f32, + aperture: f32, + focus_distance: f32, ) -> Self { // convert degree to radian - let angle = vertical_fov * std::f64::consts::PI / 180.0; + let angle = vertical_fov * std::f32::consts::PI / 180.0; let half_height = (angle / 2.0).tan(); let half_width = aspect * half_height; let origin = look_from; - let w = (look_from - look_at).unit_vector(); - let u = v_up.cross(&w).unit_vector(); - let v = w.cross(&u); + let w = (look_from - look_at).normalized(); + let u = v_up.cross(w).normalized(); + let v = w.cross(u); let lower_left_corner = origin - u * focus_distance * half_width @@ -61,10 +58,10 @@ impl Camera { } } - pub fn get_ray(&self, u: f64, v: f64) -> Ray { + pub fn get_ray(&self, u: f32, v: f32) -> Ray { let mut rng = rand::thread_rng(); let rd = random_in_unit_disk(&mut rng) * self.lens_radius; - let offset = self.u * rd.x() + self.v * rd.y(); + let offset = self.u * rd.x + self.v * rd.y; Ray::new( self.origin + offset, self.lower_left_corner + self.horizontal * u + self.vertical * v - self.origin - offset, @@ -73,10 +70,10 @@ impl Camera { } fn random_in_unit_disk(rng: &mut rand::rngs::ThreadRng) -> Vec3 { - let mut p = Vec3::new(rng.gen::(), rng.gen::(), 0.0) * 2.0 - Vec3::new(1.0, 1.0, 0.0); + let mut p = Vec3::new(rng.gen::(), rng.gen::(), 0.0) * 2.0 - Vec3::new(1.0, 1.0, 0.0); - while p.dot(&p) >= 1.0 { - p = Vec3::new(rng.gen::(), rng.gen::(), 0.0) * 2.0 - Vec3::new(1.0, 0.0, 0.0); + while p.dot(p) >= 1.0 { + p = Vec3::new(rng.gen::(), rng.gen::(), 0.0) * 2.0 - Vec3::new(1.0, 0.0, 0.0); } p } diff --git a/src/demos/defocus_blur.rs b/src/demos/defocus_blur.rs index e684af5..dda99b4 100644 --- a/src/demos/defocus_blur.rs +++ b/src/demos/defocus_blur.rs @@ -3,11 +3,12 @@ use { demos::{Chunk, Demo}, types::{ material::{Dielectric, Lambertian, Metal}, - Hitable, HitableList, Ray, Sphere, Vec3, + Hitable, HitableList, Ray, Sphere, }, Camera, }, rand::Rng, + ultraviolet::vec::Vec3, }; pub struct DefocusBlur; @@ -18,7 +19,7 @@ impl Demo for DefocusBlur { } fn world(&self) -> Option { - let radius = (std::f64::consts::PI / 4.0).cos(); + let radius = (std::f32::consts::PI / 4.0).cos(); Some(HitableList { list: vec![ Box::new(Sphere::with_material( @@ -45,11 +46,11 @@ impl Demo for DefocusBlur { }) } - fn camera(&self, aspect_ratio: f64) -> Option { + fn camera(&self, aspect_ratio: f32) -> Option { let lookfrom = Vec3::new(3.0, 3.0, 3.0); let lookat = Vec3::new(0.0, 0.0, -1.0); let aperture = 2.0; - let distance_to_focus = (lookfrom - lookat).length(); + let distance_to_focus = (lookfrom - lookat).mag(); let camera = Camera::new( lookfrom, lookat, @@ -88,19 +89,19 @@ impl Demo for DefocusBlur { for i in start_x..start_x + nx { let mut color = Vec3::new(0.0, 0.0, 0.0); for _s in 0..samples { - let u = (i as f64 + rng.gen::()) / x as f64; - let v = (j as f64 + rng.gen::()) / y as f64; + let u = (i as f32 + rng.gen::()) / x as f32; + let v = (j as f32 + rng.gen::()) / y as f32; let ray = camera.get_ray(u, v); color += calc_color(ray, &world, 0); } - color /= samples as f64; + color /= samples as f32; // gamma 2 corrected - buffer[offset] = (255.99 * color.r().sqrt()) as u8; - buffer[offset + 1] = (255.99 * color.g().sqrt()) as u8; - buffer[offset + 2] = (255.99 * color.b().sqrt()) as u8; + buffer[offset] = (255.99 * color.x.sqrt()) as u8; + buffer[offset + 1] = (255.99 * color.y.sqrt()) as u8; + buffer[offset + 2] = (255.99 * color.z.sqrt()) as u8; offset += 4; } } @@ -108,7 +109,7 @@ impl Demo for DefocusBlur { } fn calc_color(ray: Ray, world: &HitableList, depth: u32) -> Vec3 { - if let Some(hit_rec) = world.hit(&ray, 0.001, std::f64::MAX) { + if let Some(hit_rec) = world.hit(&ray, 0.001, std::f32::MAX) { if depth >= 50 { Vec3::new(0.0, 0.0, 0.0) } else { @@ -120,8 +121,8 @@ fn calc_color(ray: Ray, world: &HitableList, depth: u32) -> Vec3 { } } } else { - let unit_direction = ray.direction().unit_vector(); - let t = 0.5 * (unit_direction.y() + 1.0); + let unit_direction = ray.direction().normalized(); + let t = 0.5 * (unit_direction.y + 1.0); Vec3::new(1.0, 1.0, 1.0) * (1.0 - t) + Vec3::new(0.5, 0.7, 1.0) * t } } diff --git a/src/demos/dielectric_material.rs b/src/demos/dielectric_material.rs index 2f369db..c32b254 100644 --- a/src/demos/dielectric_material.rs +++ b/src/demos/dielectric_material.rs @@ -3,11 +3,12 @@ use { demos::{Chunk, Demo}, types::{ material::{Dielectric, Lambertian, Metal}, - Hitable, HitableList, Ray, Sphere, Vec3, + Hitable, HitableList, Ray, Sphere, }, Camera, }, rand::Rng, + ultraviolet::vec::Vec3, }; pub struct DielectricMaterial; @@ -75,19 +76,19 @@ impl Demo for DielectricMaterial { for i in start_x..start_x + nx { let mut color = Vec3::new(0.0, 0.0, 0.0); for _s in 0..samples { - let u = (i as f64 + rng.gen::()) / x as f64; - let v = (j as f64 + rng.gen::()) / y as f64; + let u = (i as f32 + rng.gen::()) / x as f32; + let v = (j as f32 + rng.gen::()) / y as f32; let ray = camera.get_ray(u, v); color += calc_color(ray, &world, 0); } - color /= samples as f64; + color /= samples as f32; // gamma 2 corrected - buffer[offset] = (255.99 * color.r().sqrt()) as u8; - buffer[offset + 1] = (255.99 * color.g().sqrt()) as u8; - buffer[offset + 2] = (255.99 * color.b().sqrt()) as u8; + buffer[offset] = (255.99 * color.x.sqrt()) as u8; + buffer[offset + 1] = (255.99 * color.y.sqrt()) as u8; + buffer[offset + 2] = (255.99 * color.z.sqrt()) as u8; offset += 4; } } @@ -95,7 +96,7 @@ impl Demo for DielectricMaterial { } fn calc_color(ray: Ray, world: &HitableList, depth: u32) -> Vec3 { - if let Some(hit_rec) = world.hit(&ray, 0.001, std::f64::MAX) { + if let Some(hit_rec) = world.hit(&ray, 0.001, std::f32::MAX) { if depth >= 50 { Vec3::new(0.0, 0.0, 0.0) } else { @@ -107,8 +108,8 @@ fn calc_color(ray: Ray, world: &HitableList, depth: u32) -> Vec3 { } } } else { - let unit_direction = ray.direction().unit_vector(); - let t = 0.5 * (unit_direction.y() + 1.0); + let unit_direction = ray.direction().normalized(); + let t = 0.5 * (unit_direction.y + 1.0); Vec3::new(1.0, 1.0, 1.0) * (1.0 - t) + Vec3::new(0.5, 0.7, 1.0) * t } } diff --git a/src/demos/diffuse_materials.rs b/src/demos/diffuse_materials.rs index 4e780a6..43ec750 100644 --- a/src/demos/diffuse_materials.rs +++ b/src/demos/diffuse_materials.rs @@ -1,10 +1,11 @@ use { crate::{ demos::{Chunk, Demo}, - types::{Hitable, HitableList, Ray, Sphere, Vec3}, + types::{Hitable, HitableList, Ray, Sphere}, Camera, }, rand::Rng, + ultraviolet::vec::Vec3, }; pub struct DiffuseMaterials; @@ -49,13 +50,13 @@ impl Demo for DiffuseMaterials { let mut color = Vec3::new(0.0, 0.0, 0.0); for _s in 0..samples { - let u = (i as f64 + rng.gen::()) / x as f64; - let v = (j as f64 + rng.gen::()) / y as f64; + let u = (i as f32 + rng.gen::()) / x as f32; + let v = (j as f32 + rng.gen::()) / y as f32; let r = camera.get_ray(u, v); color += calc_color(r, &world, &mut rng); } - color /= samples as f64; + color /= samples as f32; // Without taking square root of each color, we get a picture that // is quite dark @@ -63,9 +64,9 @@ impl Demo for DiffuseMaterials { // So, IRL, It *should* look a bit lighter in color // To do that, We apply gamma correction by a factor of 2 // which means multiple rgb values by 1/gamma aka 1/2 - buffer[offset] = (255.99 * color.r().sqrt()) as u8; - buffer[offset + 1] = (255.99 * color.g().sqrt()) as u8; - buffer[offset + 2] = (255.99 * color.b().sqrt()) as u8; + buffer[offset] = (255.99 * color.x.sqrt()) as u8; + buffer[offset + 1] = (255.99 * color.y.sqrt()) as u8; + buffer[offset + 2] = (255.99 * color.z.sqrt()) as u8; offset += 4; } } @@ -73,25 +74,25 @@ impl Demo for DiffuseMaterials { } fn calc_color(ray: Ray, world: &HitableList, rng: &mut rand::rngs::ThreadRng) -> Vec3 { - // The value of t_min here could've been 0.0 but since f32/f64 can only be + // The value of t_min here could've been 0.0 but since f32/f32 can only be // partially compared, It may cause shadow acne effect. // To combat this problem, We set a bias // More information here, https://www.opengl-tutorial.org/intermediate-tutorials/tutorial-16-shadow-mapping/#shadow-acne - if let Some(hit_rec) = world.hit(&ray, 0.001, std::f64::MAX) { + if let Some(hit_rec) = world.hit(&ray, 0.001, std::f32::MAX) { let target = hit_rec.p + hit_rec.normal + random_point_in_unit_sphere(rng); calc_color(Ray::new(hit_rec.p, target - hit_rec.p), &world, rng) * 0.5 } else { - let unit_direction = ray.direction().unit_vector(); - let t = 0.5 * (unit_direction.y() + 1.0); + let unit_direction = ray.direction().normalized(); + let t = 0.5 * (unit_direction.y + 1.0); Vec3::new(1.0, 1.0, 1.0) * (1.0 - t) + Vec3::new(0.5, 0.7, 1.0) * t } } fn random_point_in_unit_sphere(rng: &mut rand::rngs::ThreadRng) -> Vec3 { - let mut point = Vec3::new(rng.gen::(), rng.gen::(), rng.gen::()) * 2.0 + let mut point = Vec3::new(rng.gen::(), rng.gen::(), rng.gen::()) * 2.0 - Vec3::new(1.0, 1.0, 1.0); - while point.sq_len() >= 1.0 { - point = Vec3::new(rng.gen::(), rng.gen::(), rng.gen::()) * 2.0 + while point.mag_sq() >= 1.0 { + point = Vec3::new(rng.gen::(), rng.gen::(), rng.gen::()) * 2.0 - Vec3::new(1.0, 1.0, 1.0); } point diff --git a/src/demos/final_scene.rs b/src/demos/final_scene.rs index 4067c11..5ad0855 100644 --- a/src/demos/final_scene.rs +++ b/src/demos/final_scene.rs @@ -3,11 +3,12 @@ use { demos::{Chunk, Demo}, types::{ material::{Dielectric, Lambertian, Metal}, - Hitable, HitableList, Ray, Sphere, Vec3, + Hitable, HitableList, Ray, Sphere, }, Camera, }, rand::Rng, + ultraviolet::vec::Vec3, }; pub struct FinalScene; @@ -33,22 +34,22 @@ impl Demo for FinalScene { let l = Vec3::new(4.0, 0.2, 0.0); for a in -11..11 { - let a = a as f64; + let a = a as f32; for b in -11..11 { - let b = b as f64; - let choose_material_probability = rng.gen::(); - let center = Vec3::new(a + 0.9 * rng.gen::(), 0.2, b + 0.9 * rng.gen::()); + let b = b as f32; + let choose_material_probability = rng.gen::(); + let center = Vec3::new(a + 0.9 * rng.gen::(), 0.2, b + 0.9 * rng.gen::()); - if (center - l).length() > 0.9 { + if (center - l).mag() > 0.9 { if choose_material_probability < 0.8 { // diffuse material world.push(Box::new(Sphere::with_material( center, radius, Box::new(Lambertian::new(Vec3::new( - rng.gen::() * rng.gen::(), - rng.gen::() * rng.gen::(), - rng.gen::() * rng.gen::(), + rng.gen::() * rng.gen::(), + rng.gen::() * rng.gen::(), + rng.gen::() * rng.gen::(), ))), ))); } else if choose_material_probability < 0.95 { @@ -58,11 +59,11 @@ impl Demo for FinalScene { radius, Box::new(Metal::with_fuzz( Vec3::new( - (1.0 + rng.gen::()) * 0.5, - (1.0 + rng.gen::()) * 0.5, - (1.0 + rng.gen::()) * 0.5, + (1.0 + rng.gen::()) * 0.5, + (1.0 + rng.gen::()) * 0.5, + (1.0 + rng.gen::()) * 0.5, ), - 0.5 * rng.gen::(), + 0.5 * rng.gen::(), )), ))); } else { @@ -96,7 +97,7 @@ impl Demo for FinalScene { Some(world) } - fn camera(&self, aspect_ratio: f64) -> Option { + fn camera(&self, aspect_ratio: f32) -> Option { let lookfrom = Vec3::new(13.0, 2.0, 3.0); let lookat = Vec3::new(0.0, 0.0, 0.0); let camera = Camera::new( @@ -137,19 +138,19 @@ impl Demo for FinalScene { for i in start_x..start_x + nx { let mut color = Vec3::new(0.0, 0.0, 0.0); for _s in 0..samples { - let u = (i as f64 + rng.gen::()) / x as f64; - let v = (j as f64 + rng.gen::()) / y as f64; + let u = (i as f32 + rng.gen::()) / x as f32; + let v = (j as f32 + rng.gen::()) / y as f32; let ray = camera.get_ray(u, v); color += calc_color(ray, &world, 0); } - color /= samples as f64; + color /= samples as f32; // gamma 2 corrected - buffer[offset] = (255.99 * color.r().sqrt()) as u8; - buffer[offset + 1] = (255.99 * color.g().sqrt()) as u8; - buffer[offset + 2] = (255.99 * color.b().sqrt()) as u8; + buffer[offset] = (255.99 * color.x.sqrt()) as u8; + buffer[offset + 1] = (255.99 * color.y.sqrt()) as u8; + buffer[offset + 2] = (255.99 * color.z.sqrt()) as u8; offset += 4; } } @@ -157,7 +158,7 @@ impl Demo for FinalScene { } fn calc_color(ray: Ray, world: &HitableList, depth: u32) -> Vec3 { - if let Some(hit_rec) = world.hit(&ray, 0.001, std::f64::MAX) { + if let Some(hit_rec) = world.hit(&ray, 0.001, std::f32::MAX) { if depth >= 50 { Vec3::new(0.0, 0.0, 0.0) } else { @@ -169,8 +170,8 @@ fn calc_color(ray: Ray, world: &HitableList, depth: u32) -> Vec3 { } } } else { - let unit_direction = ray.direction().unit_vector(); - let t = 0.5 * (unit_direction.y() + 1.0); + let unit_direction = ray.direction().normalized(); + let t = 0.5 * (unit_direction.y + 1.0); Vec3::new(1.0, 1.0, 1.0) * (1.0 - t) + Vec3::new(0.5, 0.7, 1.0) * t } } diff --git a/src/demos/hitable_sphere.rs b/src/demos/hitable_sphere.rs index cdbeaa8..1ec0e86 100644 --- a/src/demos/hitable_sphere.rs +++ b/src/demos/hitable_sphere.rs @@ -1,7 +1,10 @@ -use crate::{ - demos::{Chunk, Demo}, - types::{Hitable, HitableList, Ray, Sphere, Vec3}, - Camera, +use { + crate::{ + demos::{Chunk, Demo}, + types::{Hitable, HitableList, Ray, Sphere}, + Camera, + }, + ultraviolet::vec::Vec3, }; pub struct HitableSphere; @@ -45,14 +48,14 @@ impl Demo for HitableSphere { let mut offset = 0; for j in start_y..start_y + ny { for i in start_x..start_x + nx { - let u = i as f64 / x as f64; - let v = j as f64 / y as f64; + let u = i as f32 / x as f32; + let v = j as f32 / y as f32; let ray = Ray::new(origin, lower_left_corner + horizontal * u + vertical * v); let color = calc_color(ray, &world); - buffer[offset] = (255.99 * color.r()) as u8; - buffer[offset + 1] = (255.99 * color.g()) as u8; - buffer[offset + 2] = (255.99 * color.b()) as u8; + buffer[offset] = (255.99 * color.x) as u8; + buffer[offset + 1] = (255.99 * color.y) as u8; + buffer[offset + 2] = (255.99 * color.z) as u8; offset += 4; } } @@ -60,19 +63,19 @@ impl Demo for HitableSphere { } fn calc_color(ray: Ray, world: &HitableList) -> Vec3 { - if let Some(hit_rec) = world.hit(&ray, 0.0, std::f64::MAX) { + if let Some(hit_rec) = world.hit(&ray, 0.0, std::f32::MAX) { // It's easier to visualise normals as unit vectors // So, This trick of adding 1 to each dimension and then halving // the resulting value shifts the normals from -1<->1 range to // 0<->1 range Vec3::new( - hit_rec.normal.x() + 1.0, - hit_rec.normal.y() + 1.0, - hit_rec.normal.z() + 1.0, + hit_rec.normal.x + 1.0, + hit_rec.normal.y + 1.0, + hit_rec.normal.z + 1.0, ) * 0.5 } else { - let unit_direction = ray.direction().unit_vector(); - let t = unit_direction.y() * 0.5 + 1.0; + let unit_direction = ray.direction().normalized(); + let t = unit_direction.y * 0.5 + 1.0; Vec3::new(1.0, 1.0, 1.0) * (1.0 - t) + Vec3::new(0.5, 0.7, 1.0) * t } } diff --git a/src/demos/linear_gradient_rectangle.rs b/src/demos/linear_gradient_rectangle.rs index 892b62c..17b1f52 100644 --- a/src/demos/linear_gradient_rectangle.rs +++ b/src/demos/linear_gradient_rectangle.rs @@ -1,9 +1,12 @@ pub struct LinearGradientRectangle; -use crate::{ - types::{HitableList, Ray, Vec3}, - Camera, - {demos::Chunk, Demo}, +use { + crate::{ + types::{HitableList, Ray}, + Camera, + {demos::Chunk, Demo}, + }, + ultraviolet::vec::Vec3, }; impl Demo for LinearGradientRectangle { @@ -38,14 +41,14 @@ impl Demo for LinearGradientRectangle { let mut offset = 0; for j in start_y..start_y + ny { for i in start_x..start_x + nx { - let u = i as f64 / x as f64; - let v = j as f64 / y as f64; + let u = i as f32 / x as f32; + let v = j as f32 / y as f32; let ray = Ray::new(origin, lower_left_corner + horizontal * u + vertical * v); let c = color(ray); - buffer[offset] = (255.99 * c.r()) as u8; - buffer[offset + 1] = (255.99 * c.g()) as u8; - buffer[offset + 2] = (255.99 * c.b()) as u8; + buffer[offset] = (255.99 * c.x) as u8; + buffer[offset + 1] = (255.99 * c.y) as u8; + buffer[offset + 2] = (255.99 * c.z) as u8; offset += 4; } } @@ -53,7 +56,7 @@ impl Demo for LinearGradientRectangle { } fn color(ray: Ray) -> Vec3 { - let unit_direction = ray.direction().unit_vector(); - let t = 0.5 * unit_direction.y() + 1.0; + let unit_direction = ray.direction().normalized(); + let t = 0.5 * unit_direction.y + 1.0; Vec3::new(1.0, 1.0, 1.0) * (1.0 - t) + Vec3::new(0.5, 0.7, 1.0) * t } diff --git a/src/demos/materials.rs b/src/demos/materials.rs index e28ac9d..8668b99 100644 --- a/src/demos/materials.rs +++ b/src/demos/materials.rs @@ -3,11 +3,12 @@ use { demos::{Chunk, Demo}, types::{ material::{Lambertian, Metal}, - Hitable, HitableList, Ray, Sphere, Vec3, + Hitable, HitableList, Ray, Sphere, }, Camera, }, rand::Rng, + ultraviolet::vec::Vec3, }; pub struct Materials; @@ -69,19 +70,19 @@ impl Demo for Materials { for i in start_x..start_x + nx { let mut color = Vec3::new(0.0, 0.0, 0.0); for _s in 0..samples { - let u = (i as f64 + rng.gen::()) / x as f64; - let v = (j as f64 + rng.gen::()) / y as f64; + let u = (i as f32 + rng.gen::()) / x as f32; + let v = (j as f32 + rng.gen::()) / y as f32; let ray = camera.get_ray(u, v); color += calc_color(ray, world.unwrap(), 0); } - color /= samples as f64; + color /= samples as f32; // gamma 2 corrected - buffer[offset] = (255.99 * color.r().sqrt()) as u8; - buffer[offset + 1] = (255.99 * color.g().sqrt()) as u8; - buffer[offset + 2] = (255.99 * color.b().sqrt()) as u8; + buffer[offset] = (255.99 * color.x.sqrt()) as u8; + buffer[offset + 1] = (255.99 * color.y.sqrt()) as u8; + buffer[offset + 2] = (255.99 * color.z.sqrt()) as u8; offset += 4; } } @@ -89,7 +90,7 @@ impl Demo for Materials { } fn calc_color(ray: Ray, world: &HitableList, depth: u32) -> Vec3 { - if let Some(hit_rec) = world.hit(&ray, 0.001, std::f64::MAX) { + if let Some(hit_rec) = world.hit(&ray, 0.001, std::f32::MAX) { if depth >= 50 { Vec3::new(0.0, 0.0, 0.0) } else { @@ -101,8 +102,8 @@ fn calc_color(ray: Ray, world: &HitableList, depth: u32) -> Vec3 { } } } else { - let unit_direction = ray.direction().unit_vector(); - let t = 0.5 * (unit_direction.y() + 1.0); + let unit_direction = ray.direction().normalized(); + let t = 0.5 * (unit_direction.y + 1.0); Vec3::new(1.0, 1.0, 1.0) * (1.0 - t) + Vec3::new(0.5, 0.7, 1.0) * t } } diff --git a/src/demos/mod.rs b/src/demos/mod.rs index de4fb1a..31a3f30 100644 --- a/src/demos/mod.rs +++ b/src/demos/mod.rs @@ -25,16 +25,14 @@ pub use simple_sphere::SimpleSphere; pub use surface_normal_sphere::SurfaceNormalSphere; use { - crate::{ - types::{HitableList, Vec3}, - Camera, HORIZONTAL_PARTITION, VERTICAL_PARTITION, - }, + crate::{types::HitableList, Camera, HORIZONTAL_PARTITION, VERTICAL_PARTITION}, rayon::prelude::*, std::{ fs::File, io::Write, sync::{Arc, Mutex}, }, + ultraviolet::vec::Vec3, }; pub struct Chunk { @@ -52,7 +50,7 @@ pub trait Demo: std::marker::Sync { let nx = width / VERTICAL_PARTITION; let ny = height / HORIZONTAL_PARTITION; let world = self.world(); - let camera = self.camera(nx as f64 / ny as f64); + let camera = self.camera(nx as f32 / ny as f32); let buf = Arc::new(Mutex::new(buf)); @@ -93,7 +91,7 @@ pub trait Demo: std::marker::Sync { None } - fn camera(&self, aspect_ratio: f64) -> Option { + fn camera(&self, aspect_ratio: f32) -> Option { let lookfrom = Vec3::new(0.0, 0.0, 0.0); let lookat = Vec3::new(0.0, 0.0, -1.0); Some(Camera::new( diff --git a/src/demos/positionable_camera.rs b/src/demos/positionable_camera.rs index efa2ba8..b329e07 100644 --- a/src/demos/positionable_camera.rs +++ b/src/demos/positionable_camera.rs @@ -3,11 +3,12 @@ use { demos::{Chunk, Demo}, types::{ material::{Dielectric, Lambertian, Metal}, - Hitable, HitableList, Ray, Sphere, Vec3, + Hitable, HitableList, Ray, Sphere, }, Camera, }, rand::Rng, + ultraviolet::vec::Vec3, }; pub struct PositionableCamera; @@ -18,7 +19,7 @@ impl Demo for PositionableCamera { } fn world(&self) -> Option { - let radius = (std::f64::consts::PI / 4.0).cos(); + let radius = (std::f32::consts::PI / 4.0).cos(); Some(HitableList { list: vec![ Box::new(Sphere::with_material( @@ -45,7 +46,7 @@ impl Demo for PositionableCamera { }) } - fn camera(&self, aspect_ratio: f64) -> Option { + fn camera(&self, aspect_ratio: f32) -> Option { let lookfrom = Vec3::new(-2.0, 2.0, 1.0); let lookat = Vec3::new(0.0, 0.0, -1.0); Some(Camera::new( @@ -84,17 +85,17 @@ impl Demo for PositionableCamera { for i in start_x..start_x + nx { let mut color = Vec3::new(0.0, 0.0, 0.0); for _s in 0..samples { - let u = (i as f64 + rng.gen::()) / x as f64; - let v = (j as f64 + rng.gen::()) / y as f64; + let u = (i as f32 + rng.gen::()) / x as f32; + let v = (j as f32 + rng.gen::()) / y as f32; let ray = camera.get_ray(u, v); color += calc_color(ray, &world, 0); } - color /= samples as f64; + color /= samples as f32; // gamma 2 corrected - buffer[offset] = (255.99 * color.r().sqrt()) as u8; - buffer[offset + 1] = (255.99 * color.g().sqrt()) as u8; - buffer[offset + 2] = (255.99 * color.b().sqrt()) as u8; + buffer[offset] = (255.99 * color.x.sqrt()) as u8; + buffer[offset + 1] = (255.99 * color.y.sqrt()) as u8; + buffer[offset + 2] = (255.99 * color.z.sqrt()) as u8; offset += 4; } } @@ -102,7 +103,7 @@ impl Demo for PositionableCamera { } fn calc_color(ray: Ray, world: &HitableList, depth: u32) -> Vec3 { - if let Some(hit_rec) = world.hit(&ray, 0.001, std::f64::MAX) { + if let Some(hit_rec) = world.hit(&ray, 0.001, std::f32::MAX) { if depth >= 50 { Vec3::new(0.0, 0.0, 0.0) } else { @@ -114,8 +115,8 @@ fn calc_color(ray: Ray, world: &HitableList, depth: u32) -> Vec3 { } } } else { - let unit_direction = ray.direction().unit_vector(); - let t = 0.5 * (unit_direction.y() + 1.0); + let unit_direction = ray.direction().normalized(); + let t = 0.5 * (unit_direction.y + 1.0); Vec3::new(1.0, 1.0, 1.0) * (1.0 - t) + Vec3::new(0.5, 0.7, 1.0) * t } } diff --git a/src/demos/simple_antialiasing.rs b/src/demos/simple_antialiasing.rs index e694256..b418d09 100644 --- a/src/demos/simple_antialiasing.rs +++ b/src/demos/simple_antialiasing.rs @@ -1,10 +1,11 @@ use { crate::{ demos::{Chunk, Demo}, - types::{Hitable, HitableList, Ray, Sphere, Vec3}, + types::{Hitable, HitableList, Ray, Sphere}, Camera, }, rand::Rng, + ultraviolet::vec::Vec3, }; pub struct SimpleAntialiasing; @@ -47,16 +48,16 @@ impl Demo for SimpleAntialiasing { for i in start_x..start_x + nx { let mut color = Vec3::new(0.0, 0.0, 0.0); for _s in 0..samples { - let u = (i as f64 + rng.gen::()) / x as f64; - let v = (j as f64 + rng.gen::()) / y as f64; + let u = (i as f32 + rng.gen::()) / x as f32; + let v = (j as f32 + rng.gen::()) / y as f32; let r = camera.get_ray(u, v); color += calc_color(r, world.unwrap()); } - color /= samples as f64; - buffer[offset] = (255.99 * color.r()) as u8; - buffer[offset + 1] = (255.99 * color.g()) as u8; - buffer[offset + 2] = (255.99 * color.b()) as u8; + color /= samples as f32; + buffer[offset] = (255.99 * color.x) as u8; + buffer[offset + 1] = (255.99 * color.y) as u8; + buffer[offset + 2] = (255.99 * color.z) as u8; offset += 4; } } @@ -64,19 +65,19 @@ impl Demo for SimpleAntialiasing { } fn calc_color(ray: Ray, world: &HitableList) -> Vec3 { - if let Some(hit_rec) = world.hit(&ray, 0.0, std::f64::MAX) { + if let Some(hit_rec) = world.hit(&ray, 0.0, std::f32::MAX) { // It's easier to visualise normals as unit vectors // So, This trick of adding 1 to each dimension and then halving // the resulting value shifts the normals from -1<->1 range to // 0<->1 range Vec3::new( - hit_rec.normal.x() + 1.0, - hit_rec.normal.y() + 1.0, - hit_rec.normal.z() + 1.0, + hit_rec.normal.x + 1.0, + hit_rec.normal.y + 1.0, + hit_rec.normal.z + 1.0, ) * 0.5 } else { - let unit_direction = ray.direction().unit_vector(); - let t = unit_direction.y() * 0.5 + 1.0; + let unit_direction = ray.direction().normalized(); + let t = unit_direction.y * 0.5 + 1.0; Vec3::new(1.0, 1.0, 1.0) * (1.0 - t) + Vec3::new(0.5, 0.7, 1.0) * t } } diff --git a/src/demos/simple_rectangle.rs b/src/demos/simple_rectangle.rs index 07d591a..093a27c 100644 --- a/src/demos/simple_rectangle.rs +++ b/src/demos/simple_rectangle.rs @@ -31,7 +31,7 @@ impl Demo for SimpleRectangle { for j in start_y..start_y + ny { for i in start_x..start_x + nx { - let color = [i as f64 / x as f64, j as f64 / y as f64, 0.2]; + let color = [i as f32 / x as f32, j as f32 / y as f32, 0.2]; buffer[offset] = (255.99 * color[0]) as u8; buffer[offset + 1] = (255.99 * color[1]) as u8; buffer[offset + 2] = (255.99 * color[2]) as u8; diff --git a/src/demos/simple_sphere.rs b/src/demos/simple_sphere.rs index 9badcd7..e9979a0 100644 --- a/src/demos/simple_sphere.rs +++ b/src/demos/simple_sphere.rs @@ -1,10 +1,13 @@ -use crate::{ - demos::{Chunk, Demo}, - types::{HitableList, Ray, Vec3}, - Camera, +use { + crate::{ + demos::{Chunk, Demo}, + types::{HitableList, Ray}, + Camera, + }, + ultraviolet::vec::Vec3, }; -const RADIUS: f64 = 0.5; +const RADIUS: f32 = 0.5; pub struct SimpleSphere; @@ -51,21 +54,21 @@ impl Demo for SimpleSphere { for i in start_x..start_x + nx { // relative offsets // current position to total width/length - let u = i as f64 / x as f64; - let v = j as f64 / y as f64; + let u = i as f32 / x as f32; + let v = j as f32 / y as f32; let ray = Ray::new(origin, lower_left_corner + horizontal * u + vertical * v); let color = calc_color(ray); - buffer[offset] = (255.99 * color.r()) as u8; - buffer[offset + 1] = (255.99 * color.g()) as u8; - buffer[offset + 2] = (255.99 * color.b()) as u8; + buffer[offset] = (255.99 * color.x) as u8; + buffer[offset + 1] = (255.99 * color.y) as u8; + buffer[offset + 2] = (255.99 * color.z) as u8; offset += 4; } } } } -fn ray_hit_sphere(center: Vec3, radius: f64, ray: &Ray) -> bool { +fn ray_hit_sphere(center: Vec3, radius: f32, ray: &Ray) -> bool { // For a point to lie on a circle, // (x-cx)^2 + (y-cy)^2 + (z-cz)^2 = R * R // should hold true. This equation can be rewritten as, @@ -81,9 +84,9 @@ fn ray_hit_sphere(center: Vec3, radius: f64, ray: &Ray) -> bool { // Vector from circle center to point let ac = ray.origin() - center; - let a = ray.direction().dot(&ray.direction()); - let b = 2.0 * ray.direction().dot(&ac); - let c = ac.dot(&ac) - radius * radius; + let a = ray.direction().dot(ray.direction()); + let b = 2.0 * ray.direction().dot(ac); + let c = ac.dot(ac) - radius * radius; let discriminant = b * b - 4.0 * a * c; discriminant > 0.0 @@ -100,10 +103,10 @@ fn calc_color(ray: Ray) -> Vec3 { // This will result in a sphere that is red in color return Vec3::new(1.0, 0.0, 0.0); } - let unit_direction = ray.direction().unit_vector(); + let unit_direction = ray.direction().normalized(); // For rays that don't hit sphere, It'll paint the gradient as the background // Linear gradient depends on y - let t = 0.5 * unit_direction.y() + 1.0; + let t = 0.5 * unit_direction.y + 1.0; // start color + end color Vec3::new(1.0, 1.0, 1.0) * (1.0 - t) + Vec3::new(0.5, 0.7, 1.0) * t diff --git a/src/demos/surface_normal_sphere.rs b/src/demos/surface_normal_sphere.rs index d804f0b..19d0c6a 100644 --- a/src/demos/surface_normal_sphere.rs +++ b/src/demos/surface_normal_sphere.rs @@ -1,10 +1,13 @@ -use crate::{ - demos::{Chunk, Demo}, - types::{HitableList, Ray, Vec3}, - Camera, +use { + crate::{ + demos::{Chunk, Demo}, + types::{HitableList, Ray}, + Camera, + }, + ultraviolet::vec::Vec3, }; -const RADIUS: f64 = 0.5; +const RADIUS: f32 = 0.5; pub struct SurfaceNormalSphere; impl Demo for SurfaceNormalSphere { @@ -48,14 +51,14 @@ impl Demo for SurfaceNormalSphere { for j in start_y..start_y + ny { for i in start_x..start_x + nx { - let u = i as f64 / x as f64; - let v = j as f64 / y as f64; + let u = i as f32 / x as f32; + let v = j as f32 / y as f32; let ray = Ray::new(origin, lower_left_corner + horizontal * u + vertical * v); let color = calculate_color(ray); - let ir = (255.99 * color.r()) as u8; - let ig = (255.99 * color.g()) as u8; - let ib = (255.99 * color.b()) as u8; + let ir = (255.99 * color.x) as u8; + let ig = (255.99 * color.y) as u8; + let ib = (255.99 * color.z) as u8; buffer[offset] = ir; buffer[offset + 1] = ig; @@ -69,23 +72,23 @@ impl Demo for SurfaceNormalSphere { fn calculate_color(ray: Ray) -> Vec3 { let t = ray_hit_sphere(Vec3::new(0.0, 0.0, -1.0), RADIUS, &ray); if t > 0.0 { - let n = (ray.point_at_parameter(t) - Vec3::new(0.0, 0.0, -1.0)).unit_vector(); - return Vec3::new(n.x() + 1.0, n.y() + 1.0, n.z() + 1.0) * 0.5; + let n = (ray.point_at_parameter(t) - Vec3::new(0.0, 0.0, -1.0)).normalized(); + return Vec3::new(n.x + 1.0, n.y + 1.0, n.z + 1.0) * 0.5; } - let unit_direction = ray.direction().unit_vector(); + let unit_direction = ray.direction().normalized(); // For rays that don't hit sphere, It'll paint the gradient as the background // Linear gradient depends on y - let t = 0.5 * unit_direction.y() + 1.0; + let t = 0.5 * unit_direction.y + 1.0; // start color + end color Vec3::new(1.0, 1.0, 1.0) * (1.0 - t) + Vec3::new(0.5, 0.7, 1.0) * t } -fn ray_hit_sphere(center: Vec3, radius: f64, ray: &Ray) -> f64 { +fn ray_hit_sphere(center: Vec3, radius: f32, ray: &Ray) -> f32 { let pc = ray.origin() - center; - let a = ray.direction().dot(&ray.direction()); - let b = 2.0 * pc.dot(&ray.direction()); - let c = pc.dot(&pc) - radius * radius; + let a = ray.direction().dot(ray.direction()); + let b = 2.0 * pc.dot(ray.direction()); + let c = pc.dot(pc) - radius * radius; let discriminant = b * b - 4.0 * a * c; if discriminant >= 0.0 { diff --git a/src/main.rs b/src/main.rs index bd6daa1..90e31b8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -143,7 +143,7 @@ fn main() -> Result<(), String> { println!( "Demo {} Time Taken(s) = {}", active_demo.name(), - now.elapsed().as_secs_f64() + now.elapsed().as_secs_f32() ); texture.update(None, &buffer, width * 4).unwrap(); diff --git a/src/types/hitable.rs b/src/types/hitable.rs index 00ccb1b..2c357a0 100644 --- a/src/types/hitable.rs +++ b/src/types/hitable.rs @@ -1,4 +1,7 @@ -use crate::types::{Material, Ray, Vec3}; +use { + crate::types::{Material, Ray}, + ultraviolet::vec::Vec3, +}; pub struct HitRecord<'a> { /// Rays are represented by A + t * B @@ -8,7 +11,7 @@ pub struct HitRecord<'a> { /// t is the point at which a ray intersected another object. /// As in, If we put this value of t in A + t * B equation, We'll get the exact /// point at which a ray intersects some other object - pub t: f64, + pub t: f32, /// Ray object otherwise is represented by the Source/Destination points /// p is what we get when we perform the operation, A + t * B /// i.e. A vector from Ray source to the point t @@ -22,7 +25,7 @@ pub struct HitRecord<'a> { } pub trait Hitable: Send + Sync { - fn hit(&self, _ray: &Ray, _t_min: f64, _t_max: f64) -> Option { + fn hit(&self, _ray: &Ray, _t_min: f32, _t_max: f32) -> Option { None } } diff --git a/src/types/hitable_list.rs b/src/types/hitable_list.rs index f2fac57..cec3490 100644 --- a/src/types/hitable_list.rs +++ b/src/types/hitable_list.rs @@ -5,7 +5,7 @@ pub struct HitableList { } impl Hitable for HitableList { - fn hit(&self, ray: &Ray, t_min: f64, t_max: f64) -> Option { + fn hit(&self, ray: &Ray, t_min: f32, t_max: f32) -> Option { let mut closest_so_far = t_max; let mut hit_rec: Option = None; for obj in &self.list { diff --git a/src/types/material.rs b/src/types/material.rs index f9674fb..d74bcf2 100644 --- a/src/types/material.rs +++ b/src/types/material.rs @@ -1,6 +1,7 @@ use { - crate::types::{HitRecord, Ray, Vec3}, + crate::types::{HitRecord, Ray}, rand::Rng, + ultraviolet::vec::Vec3, }; pub trait Material: Send + Sync { @@ -29,14 +30,14 @@ impl Material for Lambertian { pub struct Metal { albedo: Vec3, - fuzz: f64, + fuzz: f32, } impl Metal { pub fn new(albedo: Vec3) -> Self { Self { albedo, fuzz: 0.0 } } - pub fn with_fuzz(albedo: Vec3, fuzz: f64) -> Self { + pub fn with_fuzz(albedo: Vec3, fuzz: f32) -> Self { Self { albedo, fuzz } } } @@ -45,13 +46,13 @@ impl Material for Metal { fn scatter(&self, ray_in: &Ray, hit_rec: &HitRecord) -> (Vec3, Option) { let mut rng = rand::thread_rng(); - let reflected_ray = reflect(ray_in.direction().unit_vector(), hit_rec.normal); + let reflected_ray = reflect(ray_in.direction().normalized(), hit_rec.normal); let scattered_ray = Ray::new( hit_rec.p, reflected_ray + random_point_in_unit_sphere(&mut rng) * self.fuzz, ); - if scattered_ray.direction().dot(&hit_rec.normal) > 0.0 { + if scattered_ray.direction().dot(hit_rec.normal) > 0.0 { (self.albedo, Some(scattered_ray)) } else { (self.albedo, None) @@ -60,11 +61,11 @@ impl Material for Metal { } pub struct Dielectric { - reflection_index: f64, + reflection_index: f32, } impl Dielectric { - pub fn new(reflection_index: f64) -> Self { + pub fn new(reflection_index: f32) -> Self { Self { reflection_index } } } @@ -76,26 +77,25 @@ impl Material for Dielectric { let attenuation = Vec3::new(1.0, 1.0, 1.0); let mut rng = rand::thread_rng(); - let (outward_normal, ni_over_nt, cosine) = if ray_in.direction().dot(&hit_rec.normal) > 0.0 - { + let (outward_normal, ni_over_nt, cosine) = if ray_in.direction().dot(hit_rec.normal) > 0.0 { ( -hit_rec.normal, self.reflection_index, - (ray_in.direction().dot(&hit_rec.normal) * self.reflection_index) - / ray_in.direction().length(), + (ray_in.direction().dot(hit_rec.normal) * self.reflection_index) + / ray_in.direction().mag(), ) } else { ( hit_rec.normal, 1.0 / self.reflection_index, - (-ray_in.direction().dot(&hit_rec.normal)) / ray_in.direction().length(), + (-ray_in.direction().dot(hit_rec.normal)) / ray_in.direction().mag(), ) }; if let Some(refracted_ray) = refract(ray_in.direction(), outward_normal, ni_over_nt) { let reflect_prob = schlick(cosine, self.reflection_index); - if rng.gen::() < reflect_prob { + if rng.gen::() < reflect_prob { (attenuation, Some(Ray::new(hit_rec.p, reflected_ray))) } else { (attenuation, Some(Ray::new(hit_rec.p, refracted_ray))) @@ -108,20 +108,20 @@ impl Material for Dielectric { // Christophe Schlick's Polynomial approximation to figure out reflectivity as the angle changes // See Fresnel Equations, https://en.wikipedia.org/wiki/Fresnel_equations -fn schlick(cosine: f64, reflection_index: f64) -> f64 { +fn schlick(cosine: f32, reflection_index: f32) -> f32 { let mut r0 = (1.0 - reflection_index) / (1.0 + reflection_index); r0 = r0 * r0; r0 + (1.0 - r0) * (1.0 - cosine).powf(5.0) } fn reflect(incident: Vec3, normal: Vec3) -> Vec3 { - incident - normal * incident.dot(&normal) * 2.0 + incident - normal * incident.dot(normal) * 2.0 } // Snell's Law -fn refract(incident: Vec3, normal: Vec3, ni_over_nt: f64) -> Option { - let uv = incident.unit_vector(); - let dt = uv.dot(&normal); +fn refract(incident: Vec3, normal: Vec3, ni_over_nt: f32) -> Option { + let uv = incident.normalized(); + let dt = uv.dot(normal); let discriminant = 1.0 - ni_over_nt * ni_over_nt * (1.0 - dt * dt); if discriminant > 0.0 { Some((uv - normal * dt) * ni_over_nt - normal * discriminant.sqrt()) @@ -131,10 +131,10 @@ fn refract(incident: Vec3, normal: Vec3, ni_over_nt: f64) -> Option { } fn random_point_in_unit_sphere(rng: &mut rand::rngs::ThreadRng) -> Vec3 { - let mut point = Vec3::new(rng.gen::(), rng.gen::(), rng.gen::()) * 2.0 + let mut point = Vec3::new(rng.gen::(), rng.gen::(), rng.gen::()) * 2.0 - Vec3::new(1.0, 1.0, 1.0); - while point.sq_len() >= 1.0 { - point = Vec3::new(rng.gen::(), rng.gen::(), rng.gen::()) * 2.0 + while point.mag_sq() >= 1.0 { + point = Vec3::new(rng.gen::(), rng.gen::(), rng.gen::()) * 2.0 - Vec3::new(1.0, 1.0, 1.0); } point diff --git a/src/types/mod.rs b/src/types/mod.rs index 215abf0..722b8e3 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -3,11 +3,9 @@ mod hitable_list; pub mod material; mod ray; mod sphere; -mod vec3; pub use hitable::{HitRecord, Hitable}; pub use hitable_list::HitableList; pub use material::Material; pub use ray::Ray; pub use sphere::Sphere; -pub use vec3::Vec3; diff --git a/src/types/ray.rs b/src/types/ray.rs index 4075357..40a0ab0 100644 --- a/src/types/ray.rs +++ b/src/types/ray.rs @@ -1,4 +1,4 @@ -use crate::types::Vec3; +use ultraviolet::vec::Vec3; pub struct Ray { a: Vec3, @@ -18,7 +18,7 @@ impl Ray { self.b } #[inline] - pub fn point_at_parameter(&self, t: f64) -> Vec3 { + pub fn point_at_parameter(&self, t: f32) -> Vec3 { self.a + self.b * t } } diff --git a/src/types/sphere.rs b/src/types/sphere.rs index 417f4a9..8a2c48e 100644 --- a/src/types/sphere.rs +++ b/src/types/sphere.rs @@ -1,20 +1,23 @@ -use crate::types::{HitRecord, Hitable, Material, Ray, Vec3}; +use { + crate::types::{HitRecord, Hitable, Material, Ray}, + ultraviolet::vec::Vec3, +}; pub struct Sphere { center: Vec3, - radius: f64, + radius: f32, material: Option>, } impl Sphere { - pub fn new(center: Vec3, radius: f64) -> Self { + pub fn new(center: Vec3, radius: f32) -> Self { Self { center, radius, material: None, } } - pub fn with_material(center: Vec3, radius: f64, material: Box) -> Self { + pub fn with_material(center: Vec3, radius: f32, material: Box) -> Self { Self { center, radius, @@ -24,11 +27,11 @@ impl Sphere { } impl Hitable for Sphere { - fn hit(&self, ray: &Ray, t_min: f64, t_max: f64) -> Option { + fn hit(&self, ray: &Ray, t_min: f32, t_max: f32) -> Option { let oc = ray.origin() - self.center; - let a = ray.direction().dot(&ray.direction()); - let b = oc.dot(&ray.direction()); - let c = oc.dot(&oc) - self.radius * self.radius; + let a = ray.direction().dot(ray.direction()); + let b = oc.dot(ray.direction()); + let c = oc.dot(oc) - self.radius * self.radius; // The discriminant is calculated using b^2 - 4 * a * c // but in this specific case, If we put the equation in the diff --git a/src/types/vec3.rs b/src/types/vec3.rs deleted file mode 100644 index 12d931e..0000000 --- a/src/types/vec3.rs +++ /dev/null @@ -1,192 +0,0 @@ -use std::{ - fmt::{Display, Formatter, Result as FmtResult}, - ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign}, -}; - -#[derive(Copy, Clone)] -pub struct Vec3([f64; 3]); - -impl Vec3 { - #[inline] - pub const fn new(a: f64, b: f64, c: f64) -> Vec3 { - Vec3([a, b, c]) - } - #[inline] - pub fn x(&self) -> f64 { - self[0] - } - #[inline] - pub fn y(&self) -> f64 { - self[1] - } - #[inline] - pub fn z(&self) -> f64 { - self[2] - } - #[inline] - pub fn r(&self) -> f64 { - self[0] - } - #[inline] - pub fn g(&self) -> f64 { - self[1] - } - #[inline] - pub fn b(&self) -> f64 { - self[2] - } - - #[inline] - pub fn length(&self) -> f64 { - self.sq_len().sqrt() - } - - #[inline] - pub fn sq_len(&self) -> f64 { - self[0] * self[0] + self[1] * self[1] + self[2] * self[2] - } - - #[inline] - pub fn dot(&self, v: &Vec3) -> f64 { - self[0] * v[0] + self[1] * v[1] + self[2] * v[2] - } - - #[inline] - pub fn cross(&self, v: &Vec3) -> Vec3 { - Vec3([ - self[1] * v[2] - self[2] * v[1], - self[2] * v[0] - self[0] * v[2], - self[0] * v[1] - self[1] * v[0], - ]) - } - - #[inline] - pub fn make_unit_vector(&mut self) { - let k = 1.0f64 / (self[0] * self[0] + self[1] * self[1] + self[2] * self[2]); - self[0] *= k; - self[1] *= k; - self[2] *= k; - } - - #[inline] - pub fn unit_vector(&self) -> Vec3 { - let length = self.length(); - Vec3([self[0] / length, self[1] / length, self[2] / length]) - } -} - -impl Add for Vec3 { - type Output = Vec3; - - fn add(self, o: Vec3) -> Vec3 { - Vec3([self[0] + o[0], self[1] + o[1], self[2] + o[2]]) - } -} - -impl AddAssign for Vec3 { - fn add_assign(&mut self, o: Vec3) { - self.0[0] += o.0[0]; - self.0[1] += o.0[1]; - self.0[2] += o.0[2]; - } -} - -impl Sub for Vec3 { - type Output = Vec3; - - fn sub(self, o: Vec3) -> Vec3 { - Vec3([self[0] - o[0], self[1] - o[1], self[2] - o[2]]) - } -} - -impl SubAssign for Vec3 { - fn sub_assign(&mut self, o: Vec3) { - self[0] -= o[0]; - self[1] -= o[1]; - self[2] -= o[2]; - } -} - -impl Neg for Vec3 { - type Output = Vec3; - - fn neg(self) -> Vec3 { - Vec3([-self[0], -self[1], -self[2]]) - } -} - -impl MulAssign for Vec3 { - fn mul_assign(&mut self, o: Vec3) { - self[0] *= o[0]; - self[1] *= o[1]; - self[2] *= o[2]; - } -} - -impl MulAssign for Vec3 { - fn mul_assign(&mut self, o: f64) { - self[0] *= o; - self[1] *= o; - self[2] *= o; - } -} - -impl Mul for Vec3 { - type Output = Vec3; - fn mul(self, o: f64) -> Vec3 { - Vec3([self[0] * o, self[1] * o, self[2] * o]) - } -} - -impl Mul for Vec3 { - type Output = Vec3; - fn mul(self, o: Vec3) -> Vec3 { - Vec3([self[0] * o[0], self[1] * o[1], self[2] * o[2]]) - } -} - -impl Div for Vec3 { - type Output = Vec3; - - fn div(self, o: Vec3) -> Vec3 { - Vec3([self[0] / o[0], self[1] / o[1], self[2] / o[2]]) - } -} - -impl Div for Vec3 { - type Output = Vec3; - - fn div(self, o: f64) -> Vec3 { - let o = 1.0 / o; - Vec3([self[0] * o, self[1] * o, self[2] * o]) - } -} - -impl DivAssign for Vec3 { - fn div_assign(&mut self, o: f64) { - let o = 1.0 / o; - self.0[0] *= o; - self.0[1] *= o; - self.0[2] *= o; - } -} - -impl Index for Vec3 { - type Output = f64; - - fn index(&self, q: usize) -> &f64 { - &self.0[q] - } -} - -impl IndexMut for Vec3 { - fn index_mut(&mut self, q: usize) -> &mut f64 { - &mut self.0[q] - } -} - -impl Display for Vec3 { - fn fmt(&self, f: &mut Formatter) -> FmtResult { - f.write_fmt(format_args!("{} {} {}", self[0], self[1], self[2])) - } -}