chore: Unit convertor by value, clean stale code
The Vec3::as_unit() function accepts input by reference. It passes back out a copy, however, and some inputs are even temporaries. I bet the optimizer can see through this game and will do the right thing if I give it a value instead. It should perform copy elision as appropriate, even if I'm missing out on Rust's move semantics here. Remove some old, unused, and unuseable functions.
This commit is contained in:
16
src/main.rs
16
src/main.rs
@@ -125,7 +125,7 @@ fn ray_color(r: Ray, world: &dyn Hittable, depth: u32, srng: &mut SmallRng, dist
|
||||
}
|
||||
}
|
||||
|
||||
let unitdir = Vec3::as_unit(&r.dir);
|
||||
let unitdir = Vec3::as_unit(r.dir);
|
||||
let t = 0.5 * (unitdir.y + 1.0);
|
||||
return Vec3::ones() * (1.0 - t) + Vec3::new(0.5, 0.7, 1.0) * t
|
||||
}
|
||||
@@ -134,17 +134,3 @@ fn degrees_to_radians(degrees: f32) -> f32 {
|
||||
degrees * std::f32::consts::PI / 180.0
|
||||
}
|
||||
|
||||
fn hit_sphere(center: Vec3, radius: f32, ray: &Ray) -> f32{
|
||||
let oc = ray.orig - center;
|
||||
let a = ray.dir.length_squared();
|
||||
let half_b = Vec3::dot(oc, ray.dir);
|
||||
let c = oc.length_squared() - radius*radius;
|
||||
let discriminant = half_b*half_b - a*c;
|
||||
|
||||
if discriminant < 0.0 {
|
||||
return -1.0;
|
||||
} else {
|
||||
return (-half_b - discriminant.sqrt()) / a;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
|
||||
use crate::ray::Ray;
|
||||
use crate::hittable::HitRecord;
|
||||
use crate::Vec3;
|
||||
use crate::vec3;
|
||||
use crate::vec3::Vec3;
|
||||
|
||||
use rand::Rng;
|
||||
use rand::rngs::SmallRng;
|
||||
use rand::distributions::Uniform;
|
||||
|
||||
@@ -49,7 +49,7 @@ impl Material {
|
||||
},
|
||||
Material::Metal { albedo, fuzz } => {
|
||||
let reflected = Vec3::reflect(
|
||||
Vec3::as_unit(&ray_in.dir),
|
||||
Vec3::as_unit(ray_in.dir),
|
||||
rec.normal
|
||||
);
|
||||
*scattered = Ray{
|
||||
@@ -63,7 +63,7 @@ impl Material {
|
||||
*attenuation = Vec3::ones();
|
||||
let refraction_ratio = if rec.front_face { 1.0 / index_refraction } else { *index_refraction };
|
||||
|
||||
let unit_direction = Vec3::as_unit(&ray_in.dir);
|
||||
let unit_direction = Vec3::as_unit(ray_in.dir);
|
||||
let refracted = Vec3::refract(unit_direction, rec.normal, refraction_ratio);
|
||||
|
||||
*scattered = Ray {
|
||||
|
||||
77
src/vec3.rs
77
src/vec3.rs
@@ -17,11 +17,7 @@ use rand::Rng;
|
||||
use rand::rngs::SmallRng;
|
||||
use rand::distributions::Uniform;
|
||||
|
||||
#[derive(Copy)]
|
||||
#[derive(Clone)]
|
||||
#[derive(PartialEq)]
|
||||
#[derive(PartialOrd)]
|
||||
#[derive(Debug)]
|
||||
#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
|
||||
pub struct Vec3{
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
@@ -66,7 +62,7 @@ impl Vec3{
|
||||
}
|
||||
|
||||
pub fn rand_unit_vector(srng: &mut SmallRng, distrib: Uniform<f32>) -> Vec3 {
|
||||
return Vec3::as_unit(&Vec3::rand_in_unit_sphere(srng, distrib));
|
||||
return Vec3::as_unit(Vec3::rand_in_unit_sphere(srng, distrib));
|
||||
}
|
||||
|
||||
pub fn length(&self) -> f32 {
|
||||
@@ -74,7 +70,7 @@ impl Vec3{
|
||||
}
|
||||
|
||||
pub fn length_squared(&self) -> f32 {
|
||||
(self.x*self.x) + (self.y*self.y) + (self.z*self.z)
|
||||
(self.x * self.x) + (self.y * self.y) + (self.z * self.z)
|
||||
}
|
||||
|
||||
// roughly equivalent to the `void write_color(...)` in the book
|
||||
@@ -126,9 +122,9 @@ impl Vec3{
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_unit(v: &Vec3) -> Vec3 {
|
||||
pub fn as_unit(v: Vec3) -> Vec3 {
|
||||
let len = v.length();
|
||||
*v / len
|
||||
v / len
|
||||
}
|
||||
|
||||
}
|
||||
@@ -194,7 +190,6 @@ impl Mul<f32> for Vec3{
|
||||
z: self.z * other,
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl MulAssign<Vec3> for Vec3 {
|
||||
@@ -232,9 +227,9 @@ impl Div<f32> for Vec3 {
|
||||
type Output = Vec3;
|
||||
fn div(self, other: f32) -> Vec3 {
|
||||
Vec3 {
|
||||
x: self.x / other,
|
||||
y: self.y / other,
|
||||
z: self.z / other,
|
||||
x: 1.0/other * self.x,
|
||||
y: 1.0/other * self.y,
|
||||
z: 1.0/other * self.z,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -449,6 +444,20 @@ mod test{
|
||||
assert_eq!(Vec3::dot(v1, v2), 1.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dot_acute(){
|
||||
let v1 = Vec3::new(1.0, 1.0, 0.0);
|
||||
let v2 = Vec3::new(0.5, 1.0, 0.0);
|
||||
assert_eq!(Vec3::dot(v1, v2), 1.5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dot_obtuse(){
|
||||
let v1 = Vec3::new(1.0, 1.0, 0.0);
|
||||
let v2 = Vec3::new(0.5, -1.0, 0.0);
|
||||
assert_eq!(Vec3::dot(v1, v2), -0.5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cross_perpendicular(){
|
||||
let v1 = Vec3::new(1.0, 0.0, 0.0);
|
||||
@@ -483,7 +492,7 @@ mod test{
|
||||
let v = Vec3::new(2.0, 0.0, 0.0);
|
||||
let expected = Vec3::new(1.0, 0.0, 0.0);
|
||||
|
||||
assert_eq!(Vec3::as_unit(&v), expected);
|
||||
assert_eq!(Vec3::as_unit(v), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -491,7 +500,7 @@ mod test{
|
||||
let v = Vec3::new(0.5, 0.0, 0.0);
|
||||
let expected = Vec3::new(1.0, 0.0, 0.0);
|
||||
|
||||
assert_eq!(Vec3::as_unit(&v), expected);
|
||||
assert_eq!(Vec3::as_unit(v), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -499,8 +508,42 @@ mod test{
|
||||
let v = Vec3::new(1.0, 1.0, 1.0);
|
||||
let expected = Vec3::new(0.577350269,0.577350269,0.577350269);
|
||||
|
||||
assert!(Vec3::as_unit(&v) <= expected * 1.001); // within very small under-estimate
|
||||
assert!(Vec3::as_unit(&v) >= expected * 0.999); // within very small over-estimate
|
||||
assert!(Vec3::as_unit(v) <= expected * 1.001); // within very small under-estimate
|
||||
assert!(Vec3::as_unit(v) >= expected * 0.999); // within very small over-estimate
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_reflect_flat(){
|
||||
let ray = Vec3::new(1.0, 0.0, 0.0);
|
||||
let normal = Vec3::new(-1.0, 0.0, 0.0);
|
||||
|
||||
let refl = Vec3::reflect(ray, normal);
|
||||
let expected = Vec3::new(-1.0, 0.0, 0.0);
|
||||
assert!(refl == expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_reflect_flat_back(){
|
||||
let ray = Vec3::new(1.0, 0.0, 0.0);
|
||||
let normal = Vec3::new(1.0, 0.0, 0.0);
|
||||
|
||||
let refl = Vec3::reflect(ray, normal);
|
||||
let expected = Vec3::new(-1.0, 0.0, 0.0);
|
||||
assert!(refl == expected);
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_reflect_45(){
|
||||
let ray = Vec3::new(1.0, 0.0, 0.0);
|
||||
let normal = Vec3::as_unit(Vec3::new(-1.0, 1.0, 0.0));
|
||||
|
||||
|
||||
let refl = Vec3::reflect(ray, normal);
|
||||
let expected = Vec3::new(0.0, 1.0, 0.0);
|
||||
let diff = refl - expected;
|
||||
eprintln!("Diff: {}", diff);
|
||||
assert!(Vec3::near_zero(&diff));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user