167 lines
3.6 KiB
Rust
167 lines
3.6 KiB
Rust
#![allow(dead_code)]
|
|
use std::cmp::PartialEq;
|
|
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 Float4);
|
|
|
|
impl Point {
|
|
#[inline(always)]
|
|
pub fn new(x: f32, y: f32, z: f32) -> Self {
|
|
Self(Float4::new(x, y, z, 0.0))
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub fn min(self, other: Self) -> Self {
|
|
Self(self.0.min(other.0))
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub fn max(self, other: Self) -> Self {
|
|
Self(self.0.max(other.0))
|
|
}
|
|
|
|
#[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))
|
|
}
|
|
|
|
//-------------
|
|
// 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 {
|
|
type Output = Self;
|
|
|
|
#[inline(always)]
|
|
fn add(self, other: Vector) -> Self {
|
|
Self(self.0 + other.0)
|
|
}
|
|
}
|
|
|
|
impl Sub for Point {
|
|
type Output = Vector;
|
|
|
|
#[inline(always)]
|
|
fn sub(self, other: Self) -> Vector {
|
|
Vector(self.0 - other.0)
|
|
}
|
|
}
|
|
|
|
impl Sub<Vector> for Point {
|
|
type Output = Self;
|
|
|
|
#[inline(always)]
|
|
fn sub(self, other: Vector) -> Self {
|
|
Self(self.0 - other.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::*;
|
|
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);
|
|
|
|
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);
|
|
|
|
assert_eq!(v1, p1 - p2);
|
|
}
|
|
|
|
#[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()
|
|
.unwrap();
|
|
assert_eq!(p.xform(&m), Point::new(15.5, 54.0, 70.0));
|
|
assert_eq!(p.xform(&m).xform_inv(&m), p);
|
|
}
|
|
|
|
#[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()
|
|
.unwrap();
|
|
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);
|
|
}
|
|
}
|