From 95de5863cc2fd75a9326739799a5579b912fd77a Mon Sep 17 00:00:00 2001 From: Bill Thiede Date: Sun, 18 Jul 2021 17:18:08 -0700 Subject: [PATCH] all: s/f32/Float/g now using customer Float alias. --- rtchallenge/Cargo.toml | 1 + rtchallenge/src/camera.rs | 51 +++++++++++---------- rtchallenge/src/intersections.rs | 8 ++-- rtchallenge/src/lib.rs | 24 +++++++++- rtchallenge/src/materials.rs | 16 +++---- rtchallenge/src/matrices.rs | 76 ++++++++++++++------------------ rtchallenge/src/rays.rs | 4 +- rtchallenge/src/spheres.rs | 20 ++++----- rtchallenge/src/tuples.rs | 70 ++++++++++++++++------------- 9 files changed, 147 insertions(+), 123 deletions(-) diff --git a/rtchallenge/Cargo.toml b/rtchallenge/Cargo.toml index f7035ae..bf830f2 100644 --- a/rtchallenge/Cargo.toml +++ b/rtchallenge/Cargo.toml @@ -8,6 +8,7 @@ edition = "2018" [features] disable_inverse_cache = [] +float-as-double = [] [dependencies] anyhow = "1.0.41" diff --git a/rtchallenge/src/camera.rs b/rtchallenge/src/camera.rs index bc07f01..08141b0 100644 --- a/rtchallenge/src/camera.rs +++ b/rtchallenge/src/camera.rs @@ -12,7 +12,9 @@ use rayon::iter::{IntoParallelIterator, ParallelIterator}; use serde::Deserialize; use structopt::StructOpt; -use crate::{canvas::Canvas, matrices::Matrix4x4, rays::Ray, tuples::Tuple, world::World, BLACK}; +use crate::{ + canvas::Canvas, matrices::Matrix4x4, rays::Ray, tuples::Tuple, world::World, Float, BLACK, +}; #[derive(Copy, Clone, StructOpt, Debug, Deserialize)] #[serde(rename_all = "kebab-case")] @@ -32,12 +34,12 @@ impl FromStr for RenderStrategy { pub struct Camera { hsize: usize, vsize: usize, - field_of_view: f32, + field_of_view: Float, transform: Matrix4x4, inverse_transform: Matrix4x4, - pixel_size: f32, - half_width: f32, - half_height: f32, + pixel_size: Float, + half_width: Float, + half_height: Float, pub render_strategy: RenderStrategy, } @@ -55,9 +57,7 @@ impl Camera { /// /// # Examples /// ``` - /// use std::f32::consts::PI; - /// - /// use rtchallenge::{camera::Camera, matrices::Matrix4x4}; + /// use rtchallenge::{camera::Camera, float::consts::PI, matrices::Matrix4x4}; /// /// let hsize = 160; /// let vsize = 120; @@ -75,15 +75,15 @@ impl Camera { /// let c = Camera::new(150, 200, PI / 2.); /// assert_eq!(c.pixel_size(), 0.01); /// ``` - pub fn new(hsize: usize, vsize: usize, field_of_view: f32) -> Camera { + pub fn new(hsize: usize, vsize: usize, field_of_view: Float) -> Camera { let half_view = (field_of_view / 2.).tan(); - let aspect = hsize as f32 / vsize as f32; + let aspect = hsize as Float / vsize as Float; let (half_width, half_height) = if aspect >= 1. { (half_view, half_view / aspect) } else { (half_view * aspect, half_view) }; - let pixel_size = 2. * half_width / hsize as f32; + let pixel_size = 2. * half_width / hsize as Float; Camera { hsize, vsize, @@ -102,7 +102,7 @@ impl Camera { pub fn vsize(&self) -> usize { self.vsize } - pub fn field_of_view(&self) -> f32 { + pub fn field_of_view(&self) -> Float { self.field_of_view } pub fn transform(&self) -> Matrix4x4 { @@ -112,7 +112,7 @@ impl Camera { self.transform = t; self.inverse_transform = t.inverse(); } - pub fn pixel_size(&self) -> f32 { + pub fn pixel_size(&self) -> Float { self.pixel_size } pub fn supersample_rays_for_pixel(&self, px: usize, py: usize, samples: usize) -> Vec { @@ -121,8 +121,8 @@ impl Camera { (0..samples) .map(|_| { // The offset from the edge of the canvas to the pixel's corner. - let xoffset = (px as f32 + rng.gen::()) * self.pixel_size; - let yoffset = (py as f32 + rng.gen::()) * self.pixel_size; + let xoffset = (px as Float + rng.gen::()) * self.pixel_size; + let yoffset = (py as Float + rng.gen::()) * self.pixel_size; // The untransformed coordinates of the pixle in world space. // (Remember that the camera looks toward -z, so +x is to the left.) @@ -146,9 +146,9 @@ impl Camera { /// /// # Examples /// ``` - /// use std::f32::consts::PI; - /// - /// use rtchallenge::{camera::Camera, matrices::Matrix4x4, tuples::Tuple}; + /// use rtchallenge::{ + /// camera::Camera, float::consts::PI, matrices::Matrix4x4, tuples::Tuple, Float, + /// }; /// /// // Constructing a ray through the center of the canvas. /// let c = Camera::new(201, 101, PI / 2.); @@ -169,14 +169,14 @@ impl Camera { /// assert_eq!(r.origin, Tuple::point(0., 2., -5.)); /// assert_eq!( /// r.direction, - /// Tuple::vector(2_f32.sqrt() / 2., 0., -2_f32.sqrt() / 2.) + /// Tuple::vector((2. as Float).sqrt() / 2., 0., -(2. as Float).sqrt() / 2.) /// ); /// ``` #[cfg(not(feature = "disable_inverse_cache"))] pub fn ray_for_pixel(&self, px: usize, py: usize) -> Ray { // The offset from the edge of the canvas to the pixel's corner. - let xoffset = (px as f32 + 0.5) * self.pixel_size; - let yoffset = (py as f32 + 0.5) * self.pixel_size; + let xoffset = (px as Float + 0.5) * self.pixel_size; + let yoffset = (py as Float + 0.5) * self.pixel_size; // The untransformed coordinates of the pixle in world space. // (Remember that the camera looks toward -z, so +x is to the left.) @@ -195,8 +195,8 @@ impl Camera { #[cfg(feature = "disable_inverse_cache")] pub fn ray_for_pixel(&self, px: usize, py: usize) -> Ray { // The offset from the edge of the canvas to the pixel's corner. - let xoffset = (px as f32 + 0.5) * self.pixel_size; - let yoffset = (py as f32 + 0.5) * self.pixel_size; + let xoffset = (px as Float + 0.5) * self.pixel_size; + let yoffset = (py as Float + 0.5) * self.pixel_size; // The untransformed coordinates of the pixle in world space. // (Remember that the camera looks toward -z, so +x is to the left.) @@ -216,10 +216,9 @@ impl Camera { /// Use camera to render an image of the given world. /// # Examples /// ``` - /// use std::f32::consts::PI; - /// /// use rtchallenge::{ /// camera::Camera, + /// float::consts::PI, /// transformations::view_transform, /// tuples::{Color, Tuple}, /// world::World, @@ -330,7 +329,7 @@ impl Camera { .iter() .map(|ray| w.color_at(&ray)) .fold(BLACK, |acc, c| acc + c); - row_image.set(x, 0, color / SAMPLES as f32); + row_image.set(x, 0, color / SAMPLES as Float); } else { let ray = self.ray_for_pixel(x, y); let color = w.color_at(&ray); diff --git a/rtchallenge/src/intersections.rs b/rtchallenge/src/intersections.rs index ac24b2d..c4bd263 100644 --- a/rtchallenge/src/intersections.rs +++ b/rtchallenge/src/intersections.rs @@ -4,12 +4,12 @@ use crate::{ rays::Ray, spheres::Sphere, tuples::{dot, Tuple}, - EPSILON, + Float, EPSILON, }; #[derive(Debug, Clone, PartialEq)] pub struct Intersection<'i> { - pub t: f32, + pub t: Float, pub object: &'i Sphere, } @@ -26,7 +26,7 @@ impl<'i> Intersection<'i> { /// assert_eq!(i.t, 3.5); /// assert_eq!(i.object, &s); /// ``` - pub fn new(t: f32, object: &Sphere) -> Intersection { + pub fn new(t: Float, object: &Sphere) -> Intersection { Intersection { t, object } } } @@ -137,7 +137,7 @@ impl<'i> Index for Intersections<'i> { #[derive(Debug)] pub struct PrecomputedData<'i> { - pub t: f32, + pub t: Float, pub object: &'i Sphere, pub point: Tuple, pub over_point: Tuple, diff --git a/rtchallenge/src/lib.rs b/rtchallenge/src/lib.rs index d941f0c..8b7839f 100644 --- a/rtchallenge/src/lib.rs +++ b/rtchallenge/src/lib.rs @@ -11,7 +11,29 @@ pub mod tuples; pub mod world; /// Value considered close enough for PartialEq implementations. -pub const EPSILON: f32 = 0.00001; +pub const EPSILON: Float = 0.00001; pub const BLACK: tuples::Color = tuples::Color::new(0., 0., 0.); pub const WHITE: tuples::Color = tuples::Color::new(1., 1., 1.); + +#[cfg(feature = "float-as-double")] +/// submodule to defined types, constants and methods when `Float` is defined as a `f64` using the +/// "float-as-double" cargo feature. +pub mod float { + pub use std::f64::*; + /// Alias of the `f64` type, to be used through out the codebase anywhere a default sized + /// `Float` is necessary. + pub type Float = f64; +} + +#[cfg(not(feature = "float-as-double"))] +/// submodule to defined types, constants and methods when `Float` is defined as a `f32` when not using the +/// "float-as-double" cargo feature. +pub mod float { + pub use std::f32::*; + /// Alias of the `f32` type, to be used through out the codebase anywhere a default sized + /// `Float` is necessary. + pub type Float = f32; +} + +pub use float::Float; diff --git a/rtchallenge/src/materials.rs b/rtchallenge/src/materials.rs index 671bf08..a65e4bc 100644 --- a/rtchallenge/src/materials.rs +++ b/rtchallenge/src/materials.rs @@ -2,15 +2,15 @@ use crate::{ lights::PointLight, tuples::Color, tuples::{dot, reflect, Tuple}, - BLACK, WHITE, + Float, BLACK, WHITE, }; #[derive(Debug, PartialEq, Clone)] pub struct Material { pub color: Color, - pub ambient: f32, - pub diffuse: f32, - pub specular: f32, - pub shininess: f32, + pub ambient: Float, + pub diffuse: Float, + pub specular: Float, + pub shininess: Float, } impl Default for Material { @@ -51,7 +51,7 @@ impl Default for Material { /// lights::PointLight, /// materials::{lighting, Material}, /// tuples::{Color, Tuple}, -/// WHITE, +/// Float, WHITE, /// }; /// /// let in_shadow = false; @@ -66,7 +66,7 @@ impl Default for Material { /// assert_eq!(result, Color::new(1.9, 1.9, 1.9)); /// /// // Lighting with the eye between the light and the surface, eye offset 45°. -/// let eyev = Tuple::vector(0., 2_f32.sqrt() / 2., -2_f32.sqrt() / 2.); +/// let eyev = Tuple::vector(0., (2. as Float).sqrt() / 2., -(2. as Float).sqrt() / 2.); /// let normalv = Tuple::vector(0., 0., -1.); /// let light = PointLight::new(Tuple::point(0., 0., -10.), WHITE); /// let result = lighting(&m, &light, position, eyev, normalv, in_shadow); @@ -80,7 +80,7 @@ impl Default for Material { /// assert_eq!(result, Color::new(0.7364, 0.7364, 0.7364)); /// /// // Lighting with the eye in the path of the reflection vector. -/// let eyev = Tuple::vector(0., -2_f32.sqrt() / 2., -2_f32.sqrt() / 2.); +/// let eyev = Tuple::vector(0., -(2.0 as Float).sqrt() / 2., -(2.0 as Float).sqrt() / 2.); /// let normalv = Tuple::vector(0., 0., -1.); /// let light = PointLight::new(Tuple::point(0., 10., -10.), WHITE); /// let result = lighting(&m, &light, position, eyev, normalv, in_shadow); diff --git a/rtchallenge/src/matrices.rs b/rtchallenge/src/matrices.rs index 1fda39d..046aa94 100644 --- a/rtchallenge/src/matrices.rs +++ b/rtchallenge/src/matrices.rs @@ -1,15 +1,15 @@ use std::fmt; use std::ops::{Index, IndexMut, Mul, Sub}; -use crate::{tuples::Tuple, EPSILON}; +use crate::{tuples::Tuple, Float, EPSILON}; #[derive(Debug)] pub struct Matrix2x2 { - m: [[f32; 2]; 2], + m: [[Float; 2]; 2], } impl Matrix2x2 { /// Create a `Matrix2x2` with each of the given rows. - pub fn new(r0: [f32; 2], r1: [f32; 2]) -> Matrix2x2 { + pub fn new(r0: [Float; 2], r1: [Float; 2]) -> Matrix2x2 { Matrix2x2 { m: [r0, r1] } } @@ -24,13 +24,13 @@ impl Matrix2x2 { /// /// assert_eq!(a.determinant(), 17.); /// ``` - pub fn determinant(&self) -> f32 { + pub fn determinant(&self) -> Float { let m = self; m[(0, 0)] * m[(1, 1)] - m[(0, 1)] * m[(1, 0)] } } impl Index<(usize, usize)> for Matrix2x2 { - type Output = f32; + type Output = Float; fn index(&self, (row, col): (usize, usize)) -> &Self::Output { &self.m[row][col] } @@ -53,11 +53,11 @@ impl PartialEq for Matrix2x2 { #[derive(Debug)] pub struct Matrix3x3 { - m: [[f32; 3]; 3], + m: [[Float; 3]; 3], } impl Matrix3x3 { /// Create a `Matrix3x2` with each of the given rows. - pub fn new(r0: [f32; 3], r1: [f32; 3], r2: [f32; 3]) -> Matrix3x3 { + pub fn new(r0: [Float; 3], r1: [Float; 3], r2: [Float; 3]) -> Matrix3x3 { Matrix3x3 { m: [r0, r1, r2] } } /// submatrix extracts a 2x2 matrix ignoring the 0-based `row` and `col` given. @@ -101,7 +101,7 @@ impl Matrix3x3 { /// assert_eq!(b.determinant(), 25.0); /// assert_eq!(b.determinant(), a.minor(1, 0)); /// ``` - pub fn minor(&self, row: usize, col: usize) -> f32 { + pub fn minor(&self, row: usize, col: usize) -> Float { self.submatrix(row, col).determinant() } @@ -117,7 +117,7 @@ impl Matrix3x3 { /// assert_eq!(a.minor(1, 0), 25.); /// assert_eq!(a.cofactor(1, 0), -25.); /// ``` - pub fn cofactor(&self, row: usize, col: usize) -> f32 { + pub fn cofactor(&self, row: usize, col: usize) -> Float { let negate = if (row + col) % 2 == 0 { 1. } else { -1. }; self.submatrix(row, col).determinant() * negate } @@ -134,12 +134,12 @@ impl Matrix3x3 { /// assert_eq!(a.cofactor(0, 2), -46.); /// assert_eq!(a.determinant(), -196.); /// ``` - pub fn determinant(&self) -> f32 { + pub fn determinant(&self) -> Float { (0..3).map(|i| self.cofactor(0, i) * self[(0, i)]).sum() } } impl Index<(usize, usize)> for Matrix3x3 { - type Output = f32; + type Output = Float; fn index(&self, (row, col): (usize, usize)) -> &Self::Output { &self.m[row][col] } @@ -166,9 +166,7 @@ impl PartialEq for Matrix3x3 { /// /// # Examples /// ``` -/// use std::f32::consts::PI; -/// -/// use rtchallenge::{matrices::Matrix4x4, tuples::Tuple}; +/// use rtchallenge::{float::consts::PI, matrices::Matrix4x4, tuples::Tuple}; /// /// // Individual transformations are applied in sequence. /// let p = Tuple::point(1., 0., 1.); @@ -195,11 +193,11 @@ impl PartialEq for Matrix3x3 { /// ``` #[derive(Copy, Clone, Default)] pub struct Matrix4x4 { - m: [[f32; 4]; 4], + m: [[Float; 4]; 4], } -impl From<[f32; 16]> for Matrix4x4 { - fn from(t: [f32; 16]) -> Self { +impl From<[Float; 16]> for Matrix4x4 { + fn from(t: [Float; 16]) -> Self { Matrix4x4 { m: [ [t[0], t[1], t[2], t[3]], @@ -238,7 +236,7 @@ impl Matrix4x4 { } /// Create a `Matrix4x4` with each of the given rows. - pub fn new(r0: [f32; 4], r1: [f32; 4], r2: [f32; 4], r3: [f32; 4]) -> Matrix4x4 { + pub fn new(r0: [Float; 4], r1: [Float; 4], r2: [Float; 4], r3: [Float; 4]) -> Matrix4x4 { Matrix4x4 { m: [r0, r1, r2, r3], } @@ -261,7 +259,7 @@ impl Matrix4x4 { /// let v = Tuple::vector(-3., 4., 5.); /// assert_eq!(transform * v, v); /// ``` - pub fn translation(x: f32, y: f32, z: f32) -> Matrix4x4 { + pub fn translation(x: Float, y: Float, z: Float) -> Matrix4x4 { Matrix4x4::new( [1., 0., 0., x], [0., 1., 0., y], @@ -295,7 +293,7 @@ impl Matrix4x4 { /// let p = Tuple::point(2., 3., 4.); /// assert_eq!(transform * p, Tuple::point(-2., 3., 4.)); /// ``` - pub fn scaling(x: f32, y: f32, z: f32) -> Matrix4x4 { + pub fn scaling(x: Float, y: Float, z: Float) -> Matrix4x4 { Matrix4x4::new( [x, 0., 0., 0.], [0., y, 0., 0.], @@ -309,9 +307,7 @@ impl Matrix4x4 { /// # Examples /// /// ``` - /// use std::f32::consts::PI; - /// - /// use rtchallenge::{matrices::Matrix4x4, tuples::Tuple}; + /// use rtchallenge::{float::consts::PI, matrices::Matrix4x4, tuples::Tuple, Float}; /// /// // A scaling matrix applied to a point. /// let p = Tuple::point(0., 1., 0.); @@ -320,11 +316,11 @@ impl Matrix4x4 { /// /// assert_eq!( /// half_quarter * p, - /// Tuple::point(0., 2_f32.sqrt() / 2., 2_f32.sqrt() / 2.) + /// Tuple::point(0., (2.0 as Float).sqrt() / 2., (2.0 as Float).sqrt() / 2.) /// ); /// assert_eq!(full_quarter * p, Tuple::point(0., 0., 1.),); /// ``` - pub fn rotation_x(radians: f32) -> Matrix4x4 { + pub fn rotation_x(radians: Float) -> Matrix4x4 { let r = radians; Matrix4x4::new( [1., 0., 0., 0.], @@ -339,9 +335,7 @@ impl Matrix4x4 { /// # Examples /// /// ``` - /// use std::f32::consts::PI; - /// - /// use rtchallenge::{matrices::Matrix4x4, tuples::Tuple}; + /// use rtchallenge::{float::consts::PI, matrices::Matrix4x4, tuples::Tuple, Float}; /// /// // A scaling matrix applied to a point. /// let p = Tuple::point(0., 0., 1.); @@ -350,11 +344,11 @@ impl Matrix4x4 { /// /// assert_eq!( /// half_quarter * p, - /// Tuple::point(2_f32.sqrt() / 2., 0., 2_f32.sqrt() / 2.) + /// Tuple::point((2.0 as Float).sqrt() / 2., 0., (2.0 as Float).sqrt() / 2.) /// ); /// assert_eq!(full_quarter * p, Tuple::point(1., 0., 0.,),); /// ``` - pub fn rotation_y(radians: f32) -> Matrix4x4 { + pub fn rotation_y(radians: Float) -> Matrix4x4 { let r = radians; Matrix4x4::new( [r.cos(), 0., r.sin(), 0.], @@ -369,9 +363,7 @@ impl Matrix4x4 { /// # Examples /// /// ``` - /// use std::f32::consts::PI; - /// - /// use rtchallenge::{matrices::Matrix4x4, tuples::Tuple}; + /// use rtchallenge::{float::consts::PI, matrices::Matrix4x4, tuples::Tuple, Float}; /// /// // A scaling matrix applied to a point. /// let p = Tuple::point(0., 1., 0.); @@ -380,11 +372,11 @@ impl Matrix4x4 { /// /// assert_eq!( /// half_quarter * p, - /// Tuple::point(-2_f32.sqrt() / 2., 2_f32.sqrt() / 2., 0.) + /// Tuple::point(-(2.0 as Float).sqrt() / 2., (2.0 as Float).sqrt() / 2., 0.) /// ); /// assert_eq!(full_quarter * p, Tuple::point(-1., 0., 0.,),); /// ``` - pub fn rotation_z(radians: f32) -> Matrix4x4 { + pub fn rotation_z(radians: Float) -> Matrix4x4 { let r = radians; Matrix4x4::new( [r.cos(), -r.sin(), 0., 0.], @@ -462,7 +454,7 @@ impl Matrix4x4 { /// let p = Tuple::point(2.,3.,4.); /// assert_eq!(transform * p, Tuple::point(2.,3.,7.)); - pub fn shearing(xy: f32, xz: f32, yx: f32, yz: f32, zx: f32, zy: f32) -> Matrix4x4 { + pub fn shearing(xy: Float, xz: Float, yx: Float, yz: Float, zx: Float, zy: Float) -> Matrix4x4 { Matrix4x4::new( [1., xy, xz, 0.], [yx, 1., yz, 0.], @@ -503,7 +495,7 @@ impl Matrix4x4 { for i in 0..4 { let mut irow: usize = 0; let mut icol: usize = 0; - let mut big: f32 = 0.; + let mut big: Float = 0.; // Choose pivot for j in 0..4 { if ipiv[j] != 1 { @@ -538,7 +530,7 @@ impl Matrix4x4 { } // Set $m[icol][icol]$ to one by scaling row _icol_ appropriately - let pivinv: f32 = minv[icol][icol].recip(); + let pivinv: Float = minv[icol][icol].recip(); minv[icol][icol] = 1.; for j in 0..4 { minv[icol][j] *= pivinv; @@ -606,11 +598,11 @@ impl Matrix4x4 { } /// Compute minor of a 4x4 matrix. - pub fn minor(&self, row: usize, col: usize) -> f32 { + pub fn minor(&self, row: usize, col: usize) -> Float { self.submatrix(row, col).determinant() } /// Compute cofactor of a 4x4 matrix. - pub fn cofactor(&self, row: usize, col: usize) -> f32 { + pub fn cofactor(&self, row: usize, col: usize) -> Float { let negate = if (row + col) % 2 == 0 { 1. } else { -1. }; self.submatrix(row, col).determinant() * negate } @@ -632,7 +624,7 @@ impl Matrix4x4 { /// assert_eq!(a.cofactor(0, 3), 51.); /// assert_eq!(a.determinant(), -4071.); /// ``` - pub fn determinant(&self) -> f32 { + pub fn determinant(&self) -> Float { (0..4).map(|i| self.cofactor(0, i) * self[(0, i)]).sum() } @@ -873,7 +865,7 @@ impl PartialEq for Matrix4x4 { } impl Index<(usize, usize)> for Matrix4x4 { - type Output = f32; + type Output = Float; fn index(&self, (row, col): (usize, usize)) -> &Self::Output { &self.m[row][col] } diff --git a/rtchallenge/src/rays.rs b/rtchallenge/src/rays.rs index 23ea5b9..f87a026 100644 --- a/rtchallenge/src/rays.rs +++ b/rtchallenge/src/rays.rs @@ -1,4 +1,4 @@ -use crate::{matrices::Matrix4x4, tuples::Tuple}; +use crate::{matrices::Matrix4x4, tuples::Tuple, Float}; /// Rays have an origin and a direction. This datatype is the 'ray' in 'raytracer'. pub struct Ray { @@ -38,7 +38,7 @@ impl Ray { /// assert_eq!(r.position(-1.), Tuple::point(1., 3., 4.)); /// assert_eq!(r.position(2.5), Tuple::point(4.5, 3., 4.)); /// ``` - pub fn position(&self, t: f32) -> Tuple { + pub fn position(&self, t: Float) -> Tuple { self.origin + self.direction * t } diff --git a/rtchallenge/src/spheres.rs b/rtchallenge/src/spheres.rs index ac85002..cf88ffa 100644 --- a/rtchallenge/src/spheres.rs +++ b/rtchallenge/src/spheres.rs @@ -54,7 +54,7 @@ impl Sphere { /// /// # Examples /// ``` - /// use rtchallenge::{matrices::Matrix4x4, spheres::Sphere, tuples::Tuple}; + /// use rtchallenge::{matrices::Matrix4x4, spheres::Sphere, tuples::Tuple,Float}; /// /// // Normal on X-axis /// let s = Sphere::default(); @@ -74,20 +74,20 @@ impl Sphere { /// // Normal on a sphere at a nonaxial point. /// let s = Sphere::default(); /// let n = s.normal_at(Tuple::point( - /// 3_f32.sqrt() / 3., - /// 3_f32.sqrt() / 3., - /// 3_f32.sqrt() / 3., + /// (3. as Float).sqrt() / 3., + /// (3. as Float).sqrt() / 3., + /// (3. as Float).sqrt() / 3., /// )); /// assert_eq!( /// n, - /// Tuple::vector(3_f32.sqrt() / 3., 3_f32.sqrt() / 3., 3_f32.sqrt() / 3.,) + /// Tuple::vector((3. as Float).sqrt() / 3., (3. as Float).sqrt() / 3., (3. as Float).sqrt() / 3.,) /// ); /// // Normals returned are normalized. /// let s = Sphere::default(); /// let n = s.normal_at(Tuple::point( - /// 3_f32.sqrt() / 3., - /// 3_f32.sqrt() / 3., - /// 3_f32.sqrt() / 3., + /// (3. as Float).sqrt() / 3., + /// (3. as Float).sqrt() / 3., + /// (3. as Float).sqrt() / 3., /// )); /// assert_eq!(n, n.normalize()); /// @@ -98,11 +98,11 @@ impl Sphere { /// assert_eq!(n, Tuple::vector(0., 0.70711, -0.70711)); /// // Compute the normal on a transformed sphere. - /// use std::f32::consts::PI; + /// use rtchallenge::float::consts::PI; /// /// let mut s = Sphere::default(); /// s.set_transform ( Matrix4x4::scaling(1.,0.5,1.) * Matrix4x4::rotation_z(PI/5.)); - /// let n = s.normal_at(Tuple::point(0., 2_f32.sqrt()/2., -2_f32.sqrt()/2.)); + /// let n = s.normal_at(Tuple::point(0., (2. as Float).sqrt()/2., -(2. as Float).sqrt()/2.)); /// assert_eq!(n, Tuple::vector(0., 0.97014, -0.24254)); /// ``` #[cfg(not(feature = "disable_inverse_cache"))] diff --git a/rtchallenge/src/tuples.rs b/rtchallenge/src/tuples.rs index 7e6dcf0..0575f7b 100644 --- a/rtchallenge/src/tuples.rs +++ b/rtchallenge/src/tuples.rs @@ -1,25 +1,25 @@ use std::ops::{Add, Div, Mul, Neg, Sub}; -use crate::EPSILON; +use crate::{Float, EPSILON}; #[derive(Debug, Copy, Clone)] pub struct Tuple { - pub x: f32, - pub y: f32, - pub z: f32, - pub w: f32, + pub x: Float, + pub y: Float, + pub z: Float, + pub w: Float, } impl Tuple { - pub fn point(x: f32, y: f32, z: f32) -> Tuple { + pub fn point(x: Float, y: Float, z: Float) -> Tuple { Tuple::new(x, y, z, 1.0) } - pub fn vector(x: f32, y: f32, z: f32) -> Tuple { + pub fn vector(x: Float, y: Float, z: Float) -> Tuple { Tuple::new(x, y, z, 0.0) } - pub fn new(x: f32, y: f32, z: f32, w: f32) -> Tuple { + pub fn new(x: Float, y: Float, z: Float, w: Float) -> Tuple { Tuple { x, y, z, w } } @@ -31,7 +31,7 @@ impl Tuple { self.w == 0.0 } - pub fn magnitude(&self) -> f32 { + pub fn magnitude(&self) -> Float { (self.x * self.x + self.y * self.y + self.z * self.z + self.w * self.w).sqrt() } @@ -50,7 +50,10 @@ impl Tuple { /// /// # Examples /// ``` -/// use rtchallenge::tuples::{reflect, Tuple}; +/// use rtchallenge::{ +/// tuples::{reflect, Tuple}, +/// Float, +/// }; /// /// // Reflecting a vector approaching at 45° /// let v = Tuple::vector(1., -1., 0.); @@ -60,7 +63,7 @@ impl Tuple { /// /// // Reflecting off a slanted surface. /// let v = Tuple::vector(0., -1., 0.); -/// let n = Tuple::vector(2_f32.sqrt() / 2., 2_f32.sqrt() / 2., 0.); +/// let n = Tuple::vector((2. as Float).sqrt() / 2., (2. as Float).sqrt() / 2., 0.); /// let r = reflect(v, n); /// assert_eq!(r, Tuple::vector(1., 0., 0.)); /// ``` @@ -80,9 +83,9 @@ impl Add for Tuple { } } -impl Div for Tuple { +impl Div for Tuple { type Output = Self; - fn div(self, rhs: f32) -> Self::Output { + fn div(self, rhs: Float) -> Self::Output { Self::Output { x: self.x / rhs, y: self.y / rhs, @@ -92,9 +95,9 @@ impl Div for Tuple { } } -impl Mul for Tuple { +impl Mul for Tuple { type Output = Self; - fn mul(self, rhs: f32) -> Self::Output { + fn mul(self, rhs: Float) -> Self::Output { Self::Output { x: self.x * rhs, y: self.y * rhs, @@ -104,7 +107,7 @@ impl Mul for Tuple { } } -impl Mul for f32 { +impl Mul for Float { type Output = Tuple; fn mul(self, rhs: Tuple) -> Self::Output { Self::Output { @@ -147,7 +150,7 @@ impl PartialEq for Tuple { && ((self.w - rhs.w).abs() < EPSILON) } } -pub fn dot(a: Tuple, b: Tuple) -> f32 { +pub fn dot(a: Tuple, b: Tuple) -> Float { a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w } pub fn cross(a: Tuple, b: Tuple) -> Tuple { @@ -160,12 +163,12 @@ pub fn cross(a: Tuple, b: Tuple) -> Tuple { #[derive(Copy, Clone, Debug)] pub struct Color { - pub red: f32, - pub green: f32, - pub blue: f32, + pub red: Float, + pub green: Float, + pub blue: Float, } impl Color { - pub const fn new(red: f32, green: f32, blue: f32) -> Color { + pub const fn new(red: Float, green: Float, blue: Float) -> Color { Color { red, green, blue } } } @@ -187,9 +190,9 @@ impl Add for Color { } } -impl Div for Color { +impl Div for Color { type Output = Self; - fn div(self, rhs: f32) -> Self::Output { + fn div(self, rhs: Float) -> Self::Output { Self::Output { red: self.red / rhs, green: self.green / rhs, @@ -198,9 +201,9 @@ impl Div for Color { } } -impl Mul for Color { +impl Mul for Color { type Output = Self; - fn mul(self, rhs: f32) -> Self::Output { + fn mul(self, rhs: Float) -> Self::Output { Self::Output { red: self.red * rhs, green: self.green * rhs, @@ -209,7 +212,7 @@ impl Mul for Color { } } -impl Mul for f32 { +impl Mul for Float { type Output = Color; fn mul(self, rhs: Color) -> Self::Output { Self::Output { @@ -253,7 +256,7 @@ impl Sub for Color { #[cfg(test)] mod tests { - use super::{cross, dot, Color, Tuple, EPSILON}; + use super::{cross, dot, Color, Float, Tuple, EPSILON}; #[test] fn is_point() { // A tuple with w = 1 is a point @@ -341,8 +344,11 @@ mod tests { assert_eq!(1., Tuple::vector(1., 0., 0.).magnitude()); assert_eq!(1., Tuple::vector(0., 1., 0.).magnitude()); assert_eq!(1., Tuple::vector(0., 0., 1.).magnitude()); - assert_eq!(14_f32.sqrt(), Tuple::vector(1., 2., 3.).magnitude()); - assert_eq!(14_f32.sqrt(), Tuple::vector(-1., -2., -3.).magnitude()); + assert_eq!((14. as Float).sqrt(), Tuple::vector(1., 2., 3.).magnitude()); + assert_eq!( + (14. as Float).sqrt(), + Tuple::vector(-1., -2., -3.).magnitude() + ); } #[test] fn vector_normalize() { @@ -351,7 +357,11 @@ mod tests { Tuple::vector(4., 0., 0.).normalize() ); assert_eq!( - Tuple::vector(1. / 14_f32.sqrt(), 2. / 14_f32.sqrt(), 3. / 14_f32.sqrt()), + Tuple::vector( + 1. / (14. as Float).sqrt(), + 2. / (14. as Float).sqrt(), + 3. / (14. as Float).sqrt() + ), Tuple::vector(1., 2., 3.).normalize() ); }