RMath: implement transforms for Vector, Point, and Normal.

This commit is contained in:
Nathan Vegdahl 2022-07-14 23:23:22 -07:00
parent d8e1437db1
commit 42cd282c47
5 changed files with 95 additions and 9 deletions

View File

@ -3,13 +3,14 @@
use std::ops::{Add, Div, Mul, Neg, Sub};
use crate::wide4::Float4;
use crate::xform::XformFull;
use crate::DotProduct;
use crate::Vector;
/// A surface normal in 3D space.
#[derive(Debug, Copy, Clone)]
#[repr(transparent)]
pub struct Normal(pub(crate) Float4);
pub struct Normal(pub Float4);
impl Normal {
#[inline(always)]
@ -71,6 +72,25 @@ impl Normal {
pub fn set_z(self, z: f32) -> Self {
Self(self.0.set_c(z))
}
//-------------
// Transforms.
pub fn xform(self, xform: &XformFull) -> Self {
Self(self.0.vec_mul_3x3(&Float4::transpose_3x3(xform.m_inv)))
}
pub fn xform_inv(self, xform: &XformFull) -> Self {
Self(self.0.vec_mul_3x3(&Float4::transpose_3x3(xform.m)))
}
pub fn xform_fast(self, xform: &XformFull) -> Self {
Self(self.0.vec_mul_3x3_fast(&Float4::transpose_3x3(xform.m_inv)))
}
pub fn xform_inv_fast(self, xform: &XformFull) -> Self {
Self(self.0.vec_mul_3x3_fast(&Float4::transpose_3x3(xform.m)))
}
}
impl Add for Normal {

View File

@ -3,11 +3,12 @@ use std::ops::{Add, Sub};
use crate::vector::Vector;
use crate::wide4::Float4;
use crate::xform::XformFull;
/// A position in 3D space.
#[derive(Debug, Copy, Clone)]
#[repr(transparent)]
pub struct Point(pub(crate) Float4);
pub struct Point(pub Float4);
impl Point {
#[inline(always)]
@ -62,6 +63,25 @@ impl Point {
pub fn set_z(self, z: f32) -> Self {
Self(self.0.set_c(z))
}
//-------------
// Transforms.
pub fn xform(self, xform: &XformFull) -> Self {
Self(self.0.vec_mul_affine(&xform.m, xform.t))
}
pub fn xform_inv(self, xform: &XformFull) -> Self {
Self(self.0.vec_mul_affine_rev(&xform.m_inv, -xform.t))
}
pub fn xform_fast(self, xform: &XformFull) -> Self {
Self(self.0.vec_mul_affine_fast(&xform.m, xform.t))
}
pub fn xform_inv_fast(self, xform: &XformFull) -> Self {
Self(self.0.vec_mul_affine_rev_fast(&xform.m_inv, -xform.t))
}
}
impl Add<Vector> for Point {

View File

@ -5,12 +5,13 @@ 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;
/// A direction vector in 3D space.
#[derive(Debug, Copy, Clone)]
#[repr(transparent)]
pub struct Vector(pub(crate) Float4);
pub struct Vector(pub Float4);
impl Vector {
#[inline(always)]
@ -77,6 +78,25 @@ impl Vector {
pub fn set_z(self, z: f32) -> Self {
Self(self.0.set_c(z))
}
//-------------
// Transforms.
pub fn xform(self, xform: &XformFull) -> Self {
Self(self.0.vec_mul_3x3(&xform.m))
}
pub fn xform_inv(self, xform: &XformFull) -> Self {
Self(self.0.vec_mul_3x3(&xform.m_inv))
}
pub fn xform_fast(self, xform: &XformFull) -> Self {
Self(self.0.vec_mul_3x3_fast(&xform.m))
}
pub fn xform_inv_fast(self, xform: &XformFull) -> Self {
Self(self.0.vec_mul_3x3_fast(&xform.m_inv))
}
}
impl Add for Vector {

View File

@ -10,7 +10,6 @@ mod fallback {
use crate::FMulAdd;
#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone)]
#[repr(C, align(16))]
pub struct Float4 {
@ -463,6 +462,18 @@ impl Float4 {
s3 + err3
}
/// Transforms a 3d point by an affine transform.
///
/// Faster but less precise version.
#[inline]
pub fn vec_mul_affine_fast(self, m: &[Self; 3], t: Self) -> Self {
let x = self.aaaa();
let y = self.bbbb();
let z = self.cccc();
(x * m[0]) + (y * m[1]) + (z * m[2]) + t
}
/// Transforms a 3d point by an affine transform, except it applies
/// the translation part before the 3x3 part.
///
@ -499,6 +510,21 @@ impl Float4 {
s3 + err3
}
/// Transforms a 3d point by an affine transform, except it applies
/// the translation part before the 3x3 part.
///
/// Faster but less precise version.
#[inline]
pub fn vec_mul_affine_rev_fast(self, m: &[Self; 3], t: Self) -> Self {
let v = self + t;
let x = v.aaaa();
let y = v.bbbb();
let z = v.cccc();
(x * m[0]) + (y * m[1]) + (z * m[2])
}
/// Returns whether the `Float4`s are approximately equal to each
/// other.
///

View File

@ -9,8 +9,8 @@ use crate::wide4::Float4;
#[derive(Debug, Copy, Clone)]
#[repr(C)]
pub struct Xform {
pub(crate) m: [Float4; 3], // Linear matrix.
pub(crate) t: Float4, // Translation.
pub m: [Float4; 3], // Linear matrix.
pub t: Float4, // Translation.
}
impl Xform {
@ -170,9 +170,9 @@ impl Add for Xform {
#[derive(Debug, Copy, Clone)]
#[repr(C)]
pub struct XformFull {
pub(crate) m: [Float4; 3], // Linear matrix.
pub(crate) m_inv: [Float4; 3], // Inverse of linear matrix.
pub(crate) t: Float4, // Forward translation.
pub m: [Float4; 3], // Forward linear matrix.
pub m_inv: [Float4; 3], // Inverse linear matrix.
pub t: Float4, // Forward translation.
}
//-------------------------------------------------------------