RMath: implement cross product and bring back some unit tests.
This commit is contained in:
parent
42cd282c47
commit
a93a3f09da
|
@ -29,15 +29,22 @@ pub fn dot_fast<T: DotProduct>(a: T, b: T) -> f32 {
|
|||
a.dot_fast(b)
|
||||
}
|
||||
|
||||
// /// Trait for calculating cross products.
|
||||
// pub trait CrossProduct {
|
||||
// fn cross(self, other: Self) -> Self;
|
||||
// }
|
||||
/// Trait for calculating cross products.
|
||||
pub trait CrossProduct {
|
||||
fn cross(self, other: Self) -> Self;
|
||||
|
||||
// #[inline]
|
||||
// pub fn cross<T: CrossProduct>(a: T, b: T) -> T {
|
||||
// a.cross(b)
|
||||
// }
|
||||
fn cross_fast(self, other: Self) -> Self;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn cross<T: CrossProduct>(a: T, b: T) -> T {
|
||||
a.cross(b)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn cross_fast<T: CrossProduct>(a: T, b: T) -> T {
|
||||
a.cross_fast(b)
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
use std::cmp::PartialEq;
|
||||
use std::ops::{Add, Div, Mul, Neg, Sub};
|
||||
|
||||
use crate::wide4::Float4;
|
||||
use crate::xform::XformFull;
|
||||
use crate::DotProduct;
|
||||
use crate::Vector;
|
||||
use crate::{CrossProduct, DotProduct};
|
||||
|
||||
/// A surface normal in 3D space.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
|
@ -138,6 +139,13 @@ impl Neg for Normal {
|
|||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Normal {
|
||||
#[inline(always)]
|
||||
fn eq(&self, rhs: &Self) -> bool {
|
||||
self.0.a() == rhs.0.a() && self.0.b() == rhs.0.b() && self.0.c() == rhs.0.c()
|
||||
}
|
||||
}
|
||||
|
||||
impl DotProduct for Normal {
|
||||
#[inline(always)]
|
||||
fn dot(self, other: Self) -> f32 {
|
||||
|
@ -150,109 +158,132 @@ impl DotProduct for Normal {
|
|||
}
|
||||
}
|
||||
|
||||
// impl CrossProduct for Normal {
|
||||
// #[inline]
|
||||
// fn cross(self, other: Normal) -> Normal {
|
||||
// Normal {
|
||||
// co: self.co.cross(other.co),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
impl CrossProduct for Normal {
|
||||
#[inline(always)]
|
||||
fn cross(self, other: Self) -> Self {
|
||||
Self(Float4::cross_3(self.0, other.0))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn cross_fast(self, other: Self) -> Self {
|
||||
Self(Float4::cross_3_fast(self.0, other.0))
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
|
||||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
// use super::super::{CrossProduct, DotProduct, Transform};
|
||||
// use super::*;
|
||||
// use approx::assert_ulps_eq;
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{CrossProduct, DotProduct, Xform};
|
||||
|
||||
// #[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);
|
||||
#[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);
|
||||
// }
|
||||
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);
|
||||
#[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);
|
||||
// }
|
||||
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);
|
||||
#[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);
|
||||
// }
|
||||
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 xform() {
|
||||
let n = Normal::new(1.0, 2.5, 4.0);
|
||||
let m =
|
||||
Xform::new(1.0, 3.0, 9.0, 2.0, 6.0, 2.0, 2.0, 7.0, 11.0, 1.5, 8.0, 12.0).into_full();
|
||||
|
||||
// #[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!(n.xform(&m), Normal::new(-4.0625, 1.78125, -0.03125));
|
||||
assert_eq!(n.xform(&m).xform_inv(&m), n);
|
||||
}
|
||||
|
||||
// assert_eq!(v3, v1 / v2);
|
||||
// }
|
||||
#[test]
|
||||
fn xform_fast() {
|
||||
let n = Normal::new(1.0, 2.5, 4.0);
|
||||
let m =
|
||||
Xform::new(1.0, 3.0, 9.0, 2.0, 6.0, 2.0, 2.0, 7.0, 11.0, 1.5, 8.0, 12.0).into_full();
|
||||
|
||||
// #[test]
|
||||
// fn length() {
|
||||
// let n = Normal::new(1.0, 2.0, 3.0);
|
||||
// assert!((n.length() - 3.7416573867739413).abs() < 0.000001);
|
||||
// }
|
||||
assert_eq!(n.xform_fast(&m), Normal::new(-4.0625, 1.78125, -0.03125));
|
||||
assert_eq!(n.xform_fast(&m).xform_inv_fast(&m), n);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn length2() {
|
||||
// let n = Normal::new(1.0, 2.0, 3.0);
|
||||
// assert_eq!(n.length2(), 14.0);
|
||||
// }
|
||||
#[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);
|
||||
|
||||
// #[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);
|
||||
// }
|
||||
assert_eq!(v3, v1 / v2);
|
||||
}
|
||||
|
||||
// #[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;
|
||||
#[test]
|
||||
fn length() {
|
||||
let n = Normal::new(1.0, 2.0, 3.0);
|
||||
assert!((n.length() - 3.7416573867739413).abs() < 0.000001);
|
||||
}
|
||||
|
||||
// assert_eq!(v3, v1.dot(v2));
|
||||
// }
|
||||
#[test]
|
||||
fn length2() {
|
||||
let n = Normal::new(1.0, 2.0, 3.0);
|
||||
assert_eq!(n.length2(), 14.0);
|
||||
}
|
||||
|
||||
// #[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);
|
||||
#[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);
|
||||
}
|
||||
|
||||
// assert_eq!(v3, v1.cross(v2));
|
||||
// }
|
||||
// }
|
||||
#[test]
|
||||
fn dot() {
|
||||
let v1 = Normal::new(1.0, 2.0, 3.0);
|
||||
let v2 = Normal::new(1.5, 4.5, 2.5);
|
||||
|
||||
assert_eq!(v1.dot(v2), 18.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dot_fast() {
|
||||
let v1 = Normal::new(1.0, 2.0, 3.0);
|
||||
let v2 = Normal::new(1.5, 4.5, 2.5);
|
||||
|
||||
assert_eq!(v1.dot_fast(v2), 18.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cross() {
|
||||
let v1 = Normal::new(1.0, 0.0, 0.0);
|
||||
let v2 = Normal::new(0.0, 1.0, 0.0);
|
||||
|
||||
assert_eq!(v1.cross(v2), Normal::new(0.0, 0.0, 1.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cross_fast() {
|
||||
let v1 = Normal::new(1.0, 0.0, 0.0);
|
||||
let v2 = Normal::new(0.0, 1.0, 0.0);
|
||||
|
||||
assert_eq!(v1.cross_fast(v2), Normal::new(0.0, 0.0, 1.0));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#![allow(dead_code)]
|
||||
use std::cmp::PartialEq;
|
||||
use std::ops::{Add, Sub};
|
||||
|
||||
use crate::vector::Vector;
|
||||
|
@ -111,76 +112,53 @@ impl Sub<Vector> for Point {
|
|||
}
|
||||
}
|
||||
|
||||
// impl Mul<Transform> for Point {
|
||||
// type Output = Self;
|
||||
|
||||
// #[inline]
|
||||
// fn mul(self, other: Transform) -> Self {
|
||||
// Self {
|
||||
// co: other.0.transform_point3a(self.0),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
impl PartialEq for Point {
|
||||
#[inline(always)]
|
||||
fn eq(&self, rhs: &Self) -> bool {
|
||||
self.0.a() == rhs.0.a() && self.0.b() == rhs.0.b() && self.0.c() == rhs.0.c()
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
|
||||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
// use super::super::{Transform, Vector};
|
||||
// use super::*;
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{Vector, Xform};
|
||||
|
||||
// #[test]
|
||||
// fn add() {
|
||||
// let p1 = Point::new(1.0, 2.0, 3.0);
|
||||
// let v1 = Vector::new(1.5, 4.5, 2.5);
|
||||
// let p2 = Point::new(2.5, 6.5, 5.5);
|
||||
#[test]
|
||||
fn add() {
|
||||
let p1 = Point::new(1.0, 2.0, 3.0);
|
||||
let v1 = Vector::new(1.5, 4.5, 2.5);
|
||||
let p2 = Point::new(2.5, 6.5, 5.5);
|
||||
|
||||
// assert_eq!(p2, p1 + v1);
|
||||
// }
|
||||
assert_eq!(p2, p1 + v1);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn sub() {
|
||||
// let p1 = Point::new(1.0, 2.0, 3.0);
|
||||
// let p2 = Point::new(1.5, 4.5, 2.5);
|
||||
// let v1 = Vector::new(-0.5, -2.5, 0.5);
|
||||
#[test]
|
||||
fn sub() {
|
||||
let p1 = Point::new(1.0, 2.0, 3.0);
|
||||
let p2 = Point::new(1.5, 4.5, 2.5);
|
||||
let v1 = Vector::new(-0.5, -2.5, 0.5);
|
||||
|
||||
// assert_eq!(v1, p1 - p2);
|
||||
// }
|
||||
assert_eq!(v1, p1 - p2);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn mul_matrix_1() {
|
||||
// let p = Point::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 pm = Point::new(15.5, 54.0, 70.0);
|
||||
// assert_eq!(p * m, pm);
|
||||
// }
|
||||
#[test]
|
||||
fn xform() {
|
||||
let p = Point::new(1.0, 2.5, 4.0);
|
||||
let m =
|
||||
Xform::new(1.0, 3.0, 9.0, 2.0, 6.0, 2.0, 2.0, 7.0, 11.0, 1.5, 8.0, 12.0).into_full();
|
||||
assert_eq!(p.xform(&m), Point::new(15.5, 54.0, 70.0));
|
||||
assert_eq!(p.xform(&m).xform_inv(&m), p);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn mul_matrix_2() {
|
||||
// let p = Point::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 pm = Point::new(15.5, 54.0, 70.0);
|
||||
// assert_eq!(p * m, pm);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn mul_matrix_3() {
|
||||
// // Make sure matrix multiplication composes the way one would expect
|
||||
// let p = Point::new(1.0, 2.5, 4.0);
|
||||
// let m1 = 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 m2 =
|
||||
// Transform::new_from_values(4.0, 1.0, 2.0, 3.5, 3.0, 6.0, 5.0, 2.0, 2.0, 2.0, 4.0, 12.0);
|
||||
// println!("{:?}", m1 * m2);
|
||||
|
||||
// let pmm1 = p * (m1 * m2);
|
||||
// let pmm2 = (p * m1) * m2;
|
||||
|
||||
// assert!((pmm1 - pmm2).length2() <= 0.00001); // Assert pmm1 and pmm2 are roughly equal
|
||||
// }
|
||||
// }
|
||||
#[test]
|
||||
fn xform_fast() {
|
||||
let p = Point::new(1.0, 2.5, 4.0);
|
||||
let m =
|
||||
Xform::new(1.0, 3.0, 9.0, 2.0, 6.0, 2.0, 2.0, 7.0, 11.0, 1.5, 8.0, 12.0).into_full();
|
||||
assert_eq!(p.xform_fast(&m), Point::new(15.5, 54.0, 70.0));
|
||||
assert_eq!(p.xform_fast(&m).xform_inv_fast(&m), p);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
use std::cmp::PartialEq;
|
||||
use std::ops::{Add, Div, Mul, Neg, Sub};
|
||||
|
||||
use crate::normal::Normal;
|
||||
use crate::point::Point;
|
||||
use crate::wide4::Float4;
|
||||
use crate::xform::XformFull;
|
||||
use crate::DotProduct;
|
||||
use crate::{CrossProduct, DotProduct};
|
||||
|
||||
/// A direction vector in 3D space.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
|
@ -144,6 +145,13 @@ impl Neg for Vector {
|
|||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Vector {
|
||||
#[inline(always)]
|
||||
fn eq(&self, rhs: &Self) -> bool {
|
||||
self.0.a() == rhs.0.a() && self.0.b() == rhs.0.b() && self.0.c() == rhs.0.c()
|
||||
}
|
||||
}
|
||||
|
||||
impl DotProduct for Vector {
|
||||
#[inline(always)]
|
||||
fn dot(self, other: Self) -> f32 {
|
||||
|
@ -156,113 +164,132 @@ impl DotProduct for Vector {
|
|||
}
|
||||
}
|
||||
|
||||
// impl CrossProduct for Vector {
|
||||
// #[inline]
|
||||
// fn cross(self, other: Self) -> Self {
|
||||
// Self {
|
||||
// co: self.co.cross(other.co),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
impl CrossProduct for Vector {
|
||||
#[inline(always)]
|
||||
fn cross(self, other: Self) -> Self {
|
||||
Self(Float4::cross_3(self.0, other.0))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn cross_fast(self, other: Self) -> Self {
|
||||
Self(Float4::cross_3_fast(self.0, other.0))
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
|
||||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
// use super::super::{CrossProduct, DotProduct, Transform};
|
||||
// use super::*;
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{CrossProduct, DotProduct, Xform};
|
||||
|
||||
// #[test]
|
||||
// fn add() {
|
||||
// let v1 = Vector::new(1.0, 2.0, 3.0);
|
||||
// let v2 = Vector::new(1.5, 4.5, 2.5);
|
||||
// let v3 = Vector::new(2.5, 6.5, 5.5);
|
||||
#[test]
|
||||
fn add() {
|
||||
let v1 = Vector::new(1.0, 2.0, 3.0);
|
||||
let v2 = Vector::new(1.5, 4.5, 2.5);
|
||||
let v3 = Vector::new(2.5, 6.5, 5.5);
|
||||
|
||||
// assert_eq!(v3, v1 + v2);
|
||||
// }
|
||||
assert_eq!(v3, v1 + v2);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn sub() {
|
||||
// let v1 = Vector::new(1.0, 2.0, 3.0);
|
||||
// let v2 = Vector::new(1.5, 4.5, 2.5);
|
||||
// let v3 = Vector::new(-0.5, -2.5, 0.5);
|
||||
#[test]
|
||||
fn sub() {
|
||||
let v1 = Vector::new(1.0, 2.0, 3.0);
|
||||
let v2 = Vector::new(1.5, 4.5, 2.5);
|
||||
let v3 = Vector::new(-0.5, -2.5, 0.5);
|
||||
|
||||
// assert_eq!(v3, v1 - v2);
|
||||
// }
|
||||
assert_eq!(v3, v1 - v2);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn mul_scalar() {
|
||||
// let v1 = Vector::new(1.0, 2.0, 3.0);
|
||||
// let v2 = 2.0;
|
||||
// let v3 = Vector::new(2.0, 4.0, 6.0);
|
||||
#[test]
|
||||
fn mul_scalar() {
|
||||
let v1 = Vector::new(1.0, 2.0, 3.0);
|
||||
let v2 = 2.0;
|
||||
let v3 = Vector::new(2.0, 4.0, 6.0);
|
||||
|
||||
// assert_eq!(v3, v1 * v2);
|
||||
// }
|
||||
assert_eq!(v3, v1 * v2);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn mul_matrix_1() {
|
||||
// let v = Vector::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,
|
||||
// );
|
||||
// assert_eq!(v * m, Vector::new(14.0, 46.0, 58.0));
|
||||
// }
|
||||
#[test]
|
||||
fn xform() {
|
||||
let v = Vector::new(1.0, 2.5, 4.0);
|
||||
let m =
|
||||
Xform::new(1.0, 3.0, 9.0, 2.0, 6.0, 2.0, 2.0, 7.0, 11.0, 1.5, 8.0, 12.0).into_full();
|
||||
|
||||
// #[test]
|
||||
// fn mul_matrix_2() {
|
||||
// let v = Vector::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,
|
||||
// );
|
||||
// assert_eq!(v * m, Vector::new(14.0, 46.0, 58.0));
|
||||
// }
|
||||
assert_eq!(v.xform(&m), Vector::new(14.0, 46.0, 58.0));
|
||||
assert_eq!(v.xform(&m).xform_inv(&m), v);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn div() {
|
||||
// let v1 = Vector::new(1.0, 2.0, 3.0);
|
||||
// let v2 = 2.0;
|
||||
// let v3 = Vector::new(0.5, 1.0, 1.5);
|
||||
#[test]
|
||||
fn xform_fast() {
|
||||
let v = Vector::new(1.0, 2.5, 4.0);
|
||||
let m =
|
||||
Xform::new(1.0, 3.0, 9.0, 2.0, 6.0, 2.0, 2.0, 7.0, 11.0, 1.5, 8.0, 12.0).into_full();
|
||||
|
||||
// assert_eq!(v3, v1 / v2);
|
||||
// }
|
||||
assert_eq!(v.xform_fast(&m), Vector::new(14.0, 46.0, 58.0));
|
||||
assert_eq!(v.xform_fast(&m).xform_inv_fast(&m), v);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn length() {
|
||||
// let v = Vector::new(1.0, 2.0, 3.0);
|
||||
// assert!((v.length() - 3.7416573867739413).abs() < 0.000001);
|
||||
// }
|
||||
#[test]
|
||||
fn div() {
|
||||
let v1 = Vector::new(1.0, 2.0, 3.0);
|
||||
let v2 = 2.0;
|
||||
let v3 = Vector::new(0.5, 1.0, 1.5);
|
||||
|
||||
// #[test]
|
||||
// fn length2() {
|
||||
// let v = Vector::new(1.0, 2.0, 3.0);
|
||||
// assert_eq!(v.length2(), 14.0);
|
||||
// }
|
||||
assert_eq!(v3, v1 / v2);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn normalized() {
|
||||
// let v1 = Vector::new(1.0, 2.0, 3.0);
|
||||
// let v2 = Vector::new(0.2672612419124244, 0.5345224838248488, 0.8017837257372732);
|
||||
// let v3 = v1.normalized();
|
||||
// assert!((v3.x() - v2.x()).abs() < 0.000001);
|
||||
// assert!((v3.y() - v2.y()).abs() < 0.000001);
|
||||
// assert!((v3.z() - v2.z()).abs() < 0.000001);
|
||||
// }
|
||||
#[test]
|
||||
fn length() {
|
||||
let v = Vector::new(1.0, 2.0, 3.0);
|
||||
assert!((v.length() - 3.7416573867739413).abs() < 0.000001);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn dot_test() {
|
||||
// let v1 = Vector::new(1.0, 2.0, 3.0);
|
||||
// let v2 = Vector::new(1.5, 4.5, 2.5);
|
||||
// let v3 = 18.0f32;
|
||||
#[test]
|
||||
fn length2() {
|
||||
let v = Vector::new(1.0, 2.0, 3.0);
|
||||
assert_eq!(v.length2(), 14.0);
|
||||
}
|
||||
|
||||
// assert_eq!(v3, v1.dot(v2));
|
||||
// }
|
||||
#[test]
|
||||
fn normalized() {
|
||||
let v1 = Vector::new(1.0, 2.0, 3.0);
|
||||
let v2 = Vector::new(0.2672612419124244, 0.5345224838248488, 0.8017837257372732);
|
||||
let v3 = v1.normalized();
|
||||
assert!((v3.x() - v2.x()).abs() < 0.000001);
|
||||
assert!((v3.y() - v2.y()).abs() < 0.000001);
|
||||
assert!((v3.z() - v2.z()).abs() < 0.000001);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn cross_test() {
|
||||
// let v1 = Vector::new(1.0, 0.0, 0.0);
|
||||
// let v2 = Vector::new(0.0, 1.0, 0.0);
|
||||
// let v3 = Vector::new(0.0, 0.0, 1.0);
|
||||
#[test]
|
||||
fn dot() {
|
||||
let v1 = Vector::new(1.0, 2.0, 3.0);
|
||||
let v2 = Vector::new(1.5, 4.5, 2.5);
|
||||
|
||||
// assert_eq!(v3, v1.cross(v2));
|
||||
// }
|
||||
// }
|
||||
assert_eq!(v1.dot(v2), 18.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dot_fast() {
|
||||
let v1 = Vector::new(1.0, 2.0, 3.0);
|
||||
let v2 = Vector::new(1.5, 4.5, 2.5);
|
||||
|
||||
assert_eq!(v1.dot_fast(v2), 18.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cross() {
|
||||
let v1 = Vector::new(1.0, 0.0, 0.0);
|
||||
let v2 = Vector::new(0.0, 1.0, 0.0);
|
||||
|
||||
assert_eq!(v1.cross(v2), Vector::new(0.0, 0.0, 1.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cross_fast() {
|
||||
let v1 = Vector::new(1.0, 0.0, 0.0);
|
||||
let v2 = Vector::new(0.0, 1.0, 0.0);
|
||||
|
||||
assert_eq!(v1.cross_fast(v2), Vector::new(0.0, 0.0, 1.0));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::ops::{AddAssign, DivAssign, MulAssign, SubAssign};
|
||||
|
||||
use approx::relative_eq;
|
||||
use approx::ulps_eq;
|
||||
|
||||
use crate::{difference_of_products, two_prod, two_sum};
|
||||
|
||||
|
@ -335,6 +335,20 @@ impl Float4 {
|
|||
c.a() + c.b() + c.c()
|
||||
}
|
||||
|
||||
/// 3D cross product (only uses the first 3 components).
|
||||
#[inline(always)]
|
||||
pub fn cross_3(a: Self, b: Self) -> Self {
|
||||
difference_of_products(a.bcad(), b.cabd(), a.cabd(), b.bcad())
|
||||
}
|
||||
|
||||
/// 3D cross product (only uses the first 3 components).
|
||||
///
|
||||
/// Faster but less precise version.
|
||||
#[inline(always)]
|
||||
pub fn cross_3_fast(a: Self, b: Self) -> Self {
|
||||
(a.bcad() * b.cabd()) - (a.cabd() * b.bcad())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn transpose_3x3(m: [Self; 3]) -> [Self; 3] {
|
||||
[
|
||||
|
@ -504,10 +518,7 @@ impl Float4 {
|
|||
let (s2, s2_err) = two_sum(c, s1);
|
||||
let err2 = c_err + (err1 + s2_err);
|
||||
|
||||
let (s3, s3_err) = two_sum(t, s2);
|
||||
let err3 = err2 + s3_err;
|
||||
|
||||
s3 + err3
|
||||
s2 + err2
|
||||
}
|
||||
|
||||
/// Transforms a 3d point by an affine transform, except it applies
|
||||
|
@ -530,12 +541,12 @@ impl Float4 {
|
|||
///
|
||||
/// Each corresponding element cannot have a relative error exceeding
|
||||
/// `epsilon`.
|
||||
pub(crate) fn aprx_eq(a: Self, b: Self, epsilon: f32) -> bool {
|
||||
pub(crate) fn aprx_eq(a: Self, b: Self, max_ulps: u32) -> bool {
|
||||
let mut eq = true;
|
||||
eq &= relative_eq!(a.a(), b.a(), epsilon = epsilon);
|
||||
eq &= relative_eq!(a.b(), b.b(), epsilon = epsilon);
|
||||
eq &= relative_eq!(a.c(), b.c(), epsilon = epsilon);
|
||||
eq &= relative_eq!(a.d(), b.d(), epsilon = epsilon);
|
||||
eq &= ulps_eq!(a.a(), b.a(), max_ulps = max_ulps);
|
||||
eq &= ulps_eq!(a.b(), b.b(), max_ulps = max_ulps);
|
||||
eq &= ulps_eq!(a.c(), b.c(), max_ulps = max_ulps);
|
||||
eq &= ulps_eq!(a.d(), b.d(), max_ulps = max_ulps);
|
||||
eq
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,9 +14,9 @@ pub struct Xform {
|
|||
}
|
||||
|
||||
impl Xform {
|
||||
/// Creates a new affine transform the specified values:
|
||||
/// Creates a new affine transform with the specified values:
|
||||
///
|
||||
/// ```
|
||||
/// ```text
|
||||
/// a d g j
|
||||
/// b e h k
|
||||
/// c f i l
|
||||
|
@ -78,19 +78,19 @@ impl Xform {
|
|||
/// Returns whether the matrices are approximately equal to each other.
|
||||
/// Each corresponding element in the matrices cannot have a relative
|
||||
/// error exceeding epsilon.
|
||||
pub(crate) fn aprx_eq(&self, other: Xform, epsilon: f32) -> bool {
|
||||
pub(crate) fn aprx_eq(&self, other: Xform, max_ulps: u32) -> bool {
|
||||
let mut eq = true;
|
||||
eq &= Float4::aprx_eq(self.m[0], other.m[0], epsilon);
|
||||
eq &= Float4::aprx_eq(self.m[1], other.m[1], epsilon);
|
||||
eq &= Float4::aprx_eq(self.m[2], other.m[2], epsilon);
|
||||
eq &= Float4::aprx_eq(self.t, other.t, epsilon);
|
||||
eq &= Float4::aprx_eq(self.m[0], other.m[0], max_ulps);
|
||||
eq &= Float4::aprx_eq(self.m[1], other.m[1], max_ulps);
|
||||
eq &= Float4::aprx_eq(self.m[2], other.m[2], max_ulps);
|
||||
eq &= Float4::aprx_eq(self.t, other.t, max_ulps);
|
||||
eq
|
||||
}
|
||||
|
||||
/// Computes a "full" version of the transform, which can do both
|
||||
/// forward and inverse transforms.
|
||||
#[inline]
|
||||
pub fn compute_full(self) -> XformFull {
|
||||
pub fn into_full(self) -> XformFull {
|
||||
XformFull {
|
||||
m: self.m,
|
||||
m_inv: Float4::invert_3x3(self.m).unwrap_or([
|
||||
|
@ -104,7 +104,7 @@ impl Xform {
|
|||
|
||||
/// Faster but less precise version of `compute_full()`.
|
||||
#[inline]
|
||||
pub fn compute_full_fast(self) -> XformFull {
|
||||
pub fn into_full_fast(self) -> XformFull {
|
||||
XformFull {
|
||||
m: self.m,
|
||||
m_inv: Float4::invert_3x3_fast(self.m).unwrap_or([
|
||||
|
|
Loading…
Reference in New Issue
Block a user