#![allow(dead_code)] use std::ops::{Add, Div, Mul, Neg, Sub}; use crate::wide4::Float4; use crate::DotProduct; use crate::Vector; /// A surface normal in 3D space. #[derive(Debug, Copy, Clone)] #[repr(transparent)] pub struct Normal(pub(crate) Float4); impl Normal { #[inline(always)] pub fn new(x: f32, y: f32, z: f32) -> Self { Self(Float4::new(x, y, z, 0.0)) } #[inline(always)] pub fn length(self) -> f32 { self.length2().sqrt() } #[inline(always)] pub fn length2(self) -> f32 { let sqr = self.0 * self.0; sqr.a() + sqr.b() + sqr.c() } #[inline(always)] #[must_use] pub fn normalized(self) -> Self { Self(self.0 / self.length()) } #[inline(always)] pub fn into_vector(self) -> Vector { Vector(self.0) } #[inline(always)] pub fn x(self) -> f32 { self.0.a() } #[inline(always)] pub fn y(self) -> f32 { self.0.b() } #[inline(always)] pub fn z(self) -> f32 { self.0.c() } #[inline(always)] #[must_use] pub fn set_x(self, x: f32) -> Self { Self(self.0.set_a(x)) } #[inline(always)] #[must_use] pub fn set_y(self, y: f32) -> Self { Self(self.0.set_b(y)) } #[inline(always)] #[must_use] pub fn set_z(self, z: f32) -> Self { Self(self.0.set_c(z)) } } impl Add for Normal { type Output = Self; #[inline(always)] fn add(self, other: Self) -> Self { Self(self.0 + other.0) } } impl Sub for Normal { type Output = Self; #[inline(always)] fn sub(self, other: Self) -> Self { Self(self.0 - other.0) } } impl Mul for Normal { type Output = Self; #[inline(always)] fn mul(self, other: f32) -> Self { Self(self.0 * other) } } impl Div for Normal { type Output = Self; #[inline(always)] fn div(self, other: f32) -> Self { Self(self.0 / other) } } impl Neg for Normal { type Output = Self; #[inline(always)] fn neg(self) -> Self { Self(-self.0) } } impl DotProduct for Normal { #[inline(always)] fn dot(self, other: Self) -> f32 { Float4::dot_3(self.0, other.0) } #[inline(always)] fn dot_fast(self, other: Self) -> f32 { Float4::dot_3_fast(self.0, other.0) } } // impl CrossProduct for Normal { // #[inline] // fn cross(self, other: Normal) -> Normal { // Normal { // co: self.co.cross(other.co), // } // } // } //------------------------------------------------------------- // #[cfg(test)] // mod tests { // use super::super::{CrossProduct, DotProduct, Transform}; // use super::*; // use approx::assert_ulps_eq; // #[test] // fn add() { // let v1 = Normal::new(1.0, 2.0, 3.0); // let v2 = Normal::new(1.5, 4.5, 2.5); // let v3 = Normal::new(2.5, 6.5, 5.5); // assert_eq!(v3, v1 + v2); // } // #[test] // fn sub() { // let v1 = Normal::new(1.0, 2.0, 3.0); // let v2 = Normal::new(1.5, 4.5, 2.5); // let v3 = Normal::new(-0.5, -2.5, 0.5); // assert_eq!(v3, v1 - v2); // } // #[test] // fn mul_scalar() { // let v1 = Normal::new(1.0, 2.0, 3.0); // let v2 = 2.0; // let v3 = Normal::new(2.0, 4.0, 6.0); // assert_eq!(v3, v1 * v2); // } // #[test] // fn mul_matrix_1() { // let n = Normal::new(1.0, 2.5, 4.0); // let m = Transform::new_from_values( // 1.0, 2.0, 2.0, 1.5, 3.0, 6.0, 7.0, 8.0, 9.0, 2.0, 11.0, 12.0, // ); // let nm = n * m; // let nm2 = Normal::new(-4.0625, 1.78125, -0.03125); // for i in 0..3 { // assert_ulps_eq!(nm.co[i], nm2.co[i], max_ulps = 4); // } // } // #[test] // fn div() { // let v1 = Normal::new(1.0, 2.0, 3.0); // let v2 = 2.0; // let v3 = Normal::new(0.5, 1.0, 1.5); // assert_eq!(v3, v1 / v2); // } // #[test] // fn length() { // let n = Normal::new(1.0, 2.0, 3.0); // assert!((n.length() - 3.7416573867739413).abs() < 0.000001); // } // #[test] // fn length2() { // let n = Normal::new(1.0, 2.0, 3.0); // assert_eq!(n.length2(), 14.0); // } // #[test] // fn normalized() { // let n1 = Normal::new(1.0, 2.0, 3.0); // let n2 = Normal::new(0.2672612419124244, 0.5345224838248488, 0.8017837257372732); // let n3 = n1.normalized(); // assert!((n3.x() - n2.x()).abs() < 0.000001); // assert!((n3.y() - n2.y()).abs() < 0.000001); // assert!((n3.z() - n2.z()).abs() < 0.000001); // } // #[test] // fn dot_test() { // let v1 = Normal::new(1.0, 2.0, 3.0); // let v2 = Normal::new(1.5, 4.5, 2.5); // let v3 = 18.0f32; // assert_eq!(v3, v1.dot(v2)); // } // #[test] // fn cross_test() { // let v1 = Normal::new(1.0, 0.0, 0.0); // let v2 = Normal::new(0.0, 1.0, 0.0); // let v3 = Normal::new(0.0, 0.0, 1.0); // assert_eq!(v3, v1.cross(v2)); // } // }