Moved Float4 and Matrix and Vector math into their own sub-crates.

This commit is contained in:
Nathan Vegdahl 2017-05-12 21:01:54 -07:00
parent 5ab1a51f4c
commit 88578b9eae
13 changed files with 442 additions and 275 deletions

17
Cargo.lock generated
View File

@ -55,6 +55,13 @@ name = "crossbeam"
version = "0.2.10" version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "float4"
version = "0.1.0"
dependencies = [
"simd 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "gcc" name = "gcc"
version = "0.3.45" version = "0.3.45"
@ -93,6 +100,13 @@ dependencies = [
"rgb 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)", "rgb 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "math3d"
version = "0.1.0"
dependencies = [
"float4 0.1.0",
]
[[package]] [[package]]
name = "mem_arena" name = "mem_arena"
version = "0.1.0" version = "0.1.0"
@ -141,16 +155,17 @@ version = "0.1.0"
dependencies = [ dependencies = [
"clap 2.23.2 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.23.2 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
"float4 0.1.0",
"halton 0.1.0", "halton 0.1.0",
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"lodepng 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "lodepng 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"math3d 0.1.0",
"mem_arena 0.1.0", "mem_arena 0.1.0",
"nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"openexr 0.1.0 (git+https://github.com/cessen/openexr-rs?rev=612fc6c81c031970ffddcab15509236711613de8)", "openexr 0.1.0 (git+https://github.com/cessen/openexr-rs?rev=612fc6c81c031970ffddcab15509236711613de8)",
"rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
"scoped_threadpool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "scoped_threadpool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"simd 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"sobol 0.1.0", "sobol 0.1.0",
"spectra_xyz 0.1.0", "spectra_xyz 0.1.0",
"time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@ -1,7 +1,9 @@
[workspace] [workspace]
members = [ members = [
"sub_crates/mem_arena", "sub_crates/float4",
"sub_crates/halton", "sub_crates/halton",
"sub_crates/math3d",
"sub_crates/mem_arena",
"sub_crates/sobol", "sub_crates/sobol",
"sub_crates/spectra_xyz" "sub_crates/spectra_xyz"
] ]
@ -12,7 +14,7 @@ version = "0.1.0"
authors = ["Nathan Vegdahl <cessen@cessen.com>"] authors = ["Nathan Vegdahl <cessen@cessen.com>"]
[features] [features]
simd_perf = ["simd"] simd_perf = ["float4/simd_perf", "math3d/simd_perf"]
[profile.release] [profile.release]
debug = true debug = true
@ -28,15 +30,21 @@ crossbeam = "0.2"
num_cpus = "1.0" num_cpus = "1.0"
lodepng = "0.8" lodepng = "0.8"
lazy_static = "0.2" lazy_static = "0.2"
simd = { version = "0.2.0", optional = true }
# Github dependencies # Github dependencies
openexr = { git = "https://github.com/cessen/openexr-rs", rev = "612fc6c81c031970ffddcab15509236711613de8" } openexr = { git = "https://github.com/cessen/openexr-rs", rev = "612fc6c81c031970ffddcab15509236711613de8" }
# Local crate dependencies # Local crate dependencies
[dependencies.float4]
path = "sub_crates/float4"
[dependencies.halton] [dependencies.halton]
path = "sub_crates/halton" path = "sub_crates/halton"
[dependencies.math3d]
path = "sub_crates/math3d"
[dependencies.mem_arena] [dependencies.mem_arena]
path = "sub_crates/mem_arena" path = "sub_crates/mem_arena"

View File

@ -1,5 +1,8 @@
#![allow(dead_code)] #![allow(dead_code)]
use float4;
use math3d::{Matrix4x4, Normal, Point, Vector};
/// Trait for allowing a type to be linearly interpolated. /// Trait for allowing a type to be linearly interpolated.
pub trait Lerp { pub trait Lerp {
fn lerp(self, other: Self, alpha: f32) -> Self; fn lerp(self, other: Self, alpha: f32) -> Self;
@ -73,6 +76,46 @@ impl<T: Lerp> Lerp for (T, T) {
} }
} }
impl Lerp for float4::Float4 {
fn lerp(self, other: float4::Float4, alpha: f32) -> float4::Float4 {
(self * (1.0 - alpha)) + (other * alpha)
}
}
impl Lerp for Matrix4x4 {
fn lerp(self, other: Matrix4x4, alpha: f32) -> Matrix4x4 {
let alpha_minus = 1.0 - alpha;
Matrix4x4 {
values: [(self[0] * alpha_minus) + (other[0] * alpha),
(self[1] * alpha_minus) + (other[1] * alpha),
(self[2] * alpha_minus) + (other[2] * alpha),
(self[3] * alpha_minus) + (other[3] * alpha)],
}
}
}
impl Lerp for Normal {
fn lerp(self, other: Normal, alpha: f32) -> Normal {
(self * (1.0 - alpha)) + (other * alpha)
}
}
impl Lerp for Point {
fn lerp(self, other: Point, alpha: f32) -> Point {
let s = self.norm();
let o = other.norm();
Point { co: (s.co * (1.0 - alpha)) + (o.co * alpha) }
}
}
impl Lerp for Vector {
fn lerp(self, other: Vector, alpha: f32) -> Vector {
(self * (1.0 - alpha)) + (other * alpha)
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
@ -152,4 +195,176 @@ mod tests {
assert_eq!(2.5, lerp_slice(&s[..], alpha)); assert_eq!(2.5, lerp_slice(&s[..], alpha));
} }
#[test]
fn lerp_matrix() {
let a = Matrix4x4::new_from_values(0.0,
2.0,
2.0,
3.0,
4.0,
5.0,
6.0,
7.0,
8.0,
9.0,
10.0,
11.0,
12.0,
13.0,
14.0,
15.0);
let b = Matrix4x4::new_from_values(-1.0,
1.0,
3.0,
4.0,
5.0,
6.0,
7.0,
8.0,
9.0,
10.0,
11.0,
12.0,
13.0,
14.0,
15.0,
16.0);
let c1 = Matrix4x4::new_from_values(-0.25,
1.75,
2.25,
3.25,
4.25,
5.25,
6.25,
7.25,
8.25,
9.25,
10.25,
11.25,
12.25,
13.25,
14.25,
15.25);
let c2 = Matrix4x4::new_from_values(-0.5,
1.5,
2.5,
3.5,
4.5,
5.5,
6.5,
7.5,
8.5,
9.5,
10.5,
11.5,
12.5,
13.5,
14.5,
15.5);
let c3 = Matrix4x4::new_from_values(-0.75,
1.25,
2.75,
3.75,
4.75,
5.75,
6.75,
7.75,
8.75,
9.75,
10.75,
11.75,
12.75,
13.75,
14.75,
15.75);
assert_eq!(a.lerp(b, 0.0), a);
assert_eq!(a.lerp(b, 0.25), c1);
assert_eq!(a.lerp(b, 0.5), c2);
assert_eq!(a.lerp(b, 0.75), c3);
assert_eq!(a.lerp(b, 1.0), b);
}
#[test]
fn lerp_point_1() {
let p1 = Point::new(1.0, 2.0, 1.0);
let p2 = Point::new(-2.0, 1.0, -1.0);
let p3 = Point::new(1.0, 2.0, 1.0);
assert_eq!(p3, p1.lerp(p2, 0.0));
}
#[test]
fn lerp_point_2() {
let p1 = Point::new(1.0, 2.0, 1.0);
let p2 = Point::new(-2.0, 1.0, -1.0);
let p3 = Point::new(-2.0, 1.0, -1.0);
assert_eq!(p3, p1.lerp(p2, 1.0));
}
#[test]
fn lerp_point_3() {
let p1 = Point::new(1.0, 2.0, 1.0);
let p2 = Point::new(-2.0, 1.0, -1.0);
let p3 = Point::new(-0.5, 1.5, 0.0);
assert_eq!(p3, p1.lerp(p2, 0.5));
}
#[test]
fn lerp_normal_1() {
let n1 = Normal::new(1.0, 2.0, 1.0);
let n2 = Normal::new(-2.0, 1.0, -1.0);
let n3 = Normal::new(1.0, 2.0, 1.0);
assert_eq!(n3, n1.lerp(n2, 0.0));
}
#[test]
fn lerp_normal_2() {
let n1 = Normal::new(1.0, 2.0, 1.0);
let n2 = Normal::new(-2.0, 1.0, -1.0);
let n3 = Normal::new(-2.0, 1.0, -1.0);
assert_eq!(n3, n1.lerp(n2, 1.0));
}
#[test]
fn lerp_normal_3() {
let n1 = Normal::new(1.0, 2.0, 1.0);
let n2 = Normal::new(-2.0, 1.0, -1.0);
let n3 = Normal::new(-0.5, 1.5, 0.0);
assert_eq!(n3, n1.lerp(n2, 0.5));
}
#[test]
fn lerp_vector_1() {
let v1 = Vector::new(1.0, 2.0, 1.0);
let v2 = Vector::new(-2.0, 1.0, -1.0);
let v3 = Vector::new(1.0, 2.0, 1.0);
assert_eq!(v3, v1.lerp(v2, 0.0));
}
#[test]
fn lerp_vector_2() {
let v1 = Vector::new(1.0, 2.0, 1.0);
let v2 = Vector::new(-2.0, 1.0, -1.0);
let v3 = Vector::new(-2.0, 1.0, -1.0);
assert_eq!(v3, v1.lerp(v2, 1.0));
}
#[test]
fn lerp_vector_3() {
let v1 = Vector::new(1.0, 2.0, 1.0);
let v2 = Vector::new(-2.0, 1.0, -1.0);
let v3 = Vector::new(-0.5, 1.5, 0.0);
assert_eq!(v3, v1.lerp(v2, 0.5));
}
} }

View File

@ -1,4 +1,7 @@
extern crate float4;
extern crate halton; extern crate halton;
extern crate math3d;
extern crate mem_arena; extern crate mem_arena;
extern crate spectra_xyz; extern crate spectra_xyz;
@ -17,9 +20,6 @@ extern crate nom;
#[macro_use] #[macro_use]
extern crate lazy_static; extern crate lazy_static;
#[cfg(feature = "simd_perf")]
extern crate simd;
mod accel; mod accel;
mod algorithm; mod algorithm;
mod bbox; mod bbox;
@ -28,7 +28,6 @@ mod bitstack;
mod boundable; mod boundable;
mod camera; mod camera;
mod color; mod color;
mod float4;
mod hash; mod hash;
mod hilbert; mod hilbert;
mod image; mod image;

View File

@ -1,35 +1,5 @@
#![allow(dead_code)] #![allow(dead_code)]
pub use math3d::{Matrix4x4, Normal, Point, Vector, DotProduct, dot, CrossProduct, cross};
mod matrix;
mod normal;
mod point;
mod vector;
pub use self::matrix::Matrix4x4;
pub use self::normal::Normal;
pub use self::point::Point;
pub use self::vector::Vector;
/// Trait for calculating dot products.
pub trait DotProduct {
fn dot(self, other: Self) -> f32;
}
pub fn dot<T: DotProduct>(a: T, b: T) -> f32 {
a.dot(b)
}
/// Trait for calculating cross products.
pub trait CrossProduct {
fn cross(self, other: Self) -> Self;
}
pub fn cross<T: CrossProduct>(a: T, b: T) -> T {
a.cross(b)
}
/// Clamps a value between a min and max. /// Clamps a value between a min and max.
pub fn clamp<T: PartialOrd>(v: T, lower: T, upper: T) -> T { pub fn clamp<T: PartialOrd>(v: T, lower: T, upper: T) -> T {

View File

@ -0,0 +1,16 @@
[package]
name = "float4"
version = "0.1.0"
authors = ["Nathan Vegdahl <cessen@cessen.com>"]
license = "MIT"
[lib]
name = "float4"
path = "src/lib.rs"
[features]
simd_perf = ["simd"]
[dependencies]
# Crates.io dependencies
simd = { version = "0.2.0", optional = true }

View File

@ -1,13 +1,14 @@
#![allow(dead_code)] #![allow(dead_code)]
#[cfg(feature = "simd_perf")]
extern crate simd;
use std::cmp::PartialEq; use std::cmp::PartialEq;
use std::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign, Div, DivAssign, BitAnd}; use std::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign, Div, DivAssign, BitAnd};
#[cfg(feature = "simd_perf")] #[cfg(feature = "simd_perf")]
use simd::{f32x4, bool32fx4}; use simd::{f32x4, bool32fx4};
use lerp::Lerp;
/// Essentially a tuple of four floats, which will use SIMD operations /// Essentially a tuple of four floats, which will use SIMD operations
/// where possible on a platform. /// where possible on a platform.
#[cfg(feature = "simd_perf")] #[cfg(feature = "simd_perf")]
@ -24,31 +25,38 @@ pub struct Float4 {
impl Float4 { impl Float4 {
#[cfg(feature = "simd_perf")] #[cfg(feature = "simd_perf")]
#[inline(always)]
pub fn new(a: f32, b: f32, c: f32, d: f32) -> Float4 { pub fn new(a: f32, b: f32, c: f32, d: f32) -> Float4 {
Float4 { data: f32x4::new(a, b, c, d) } Float4 { data: f32x4::new(a, b, c, d) }
} }
#[cfg(not(feature = "simd_perf"))] #[cfg(not(feature = "simd_perf"))]
#[inline(always)]
pub fn new(a: f32, b: f32, c: f32, d: f32) -> Float4 { pub fn new(a: f32, b: f32, c: f32, d: f32) -> Float4 {
Float4 { data: [a, b, c, d] } Float4 { data: [a, b, c, d] }
} }
#[cfg(feature = "simd_perf")] #[cfg(feature = "simd_perf")]
#[inline(always)]
pub fn splat(n: f32) -> Float4 { pub fn splat(n: f32) -> Float4 {
Float4 { data: f32x4::splat(n) } Float4 { data: f32x4::splat(n) }
} }
#[cfg(not(feature = "simd_perf"))] #[cfg(not(feature = "simd_perf"))]
#[inline(always)]
pub fn splat(n: f32) -> Float4 { pub fn splat(n: f32) -> Float4 {
Float4 { data: [n, n, n, n] } Float4 { data: [n, n, n, n] }
} }
#[inline]
pub fn h_sum(&self) -> f32 { pub fn h_sum(&self) -> f32 {
(self.get_0() + self.get_1()) + (self.get_2() + self.get_3()) (self.get_0() + self.get_1()) + (self.get_2() + self.get_3())
} }
#[inline]
pub fn h_product(&self) -> f32 { pub fn h_product(&self) -> f32 {
(self.get_0() * self.get_1()) * (self.get_2() * self.get_3()) (self.get_0() * self.get_1()) * (self.get_2() * self.get_3())
} }
#[inline]
pub fn h_min(&self) -> f32 { pub fn h_min(&self) -> f32 {
let n1 = if self.get_0() < self.get_1() { let n1 = if self.get_0() < self.get_1() {
self.get_0() self.get_0()
@ -63,6 +71,7 @@ impl Float4 {
if n1 < n2 { n1 } else { n2 } if n1 < n2 { n1 } else { n2 }
} }
#[inline]
pub fn h_max(&self) -> f32 { pub fn h_max(&self) -> f32 {
let n1 = if self.get_0() > self.get_1() { let n1 = if self.get_0() > self.get_1() {
self.get_0() self.get_0()
@ -78,10 +87,12 @@ impl Float4 {
} }
#[cfg(feature = "simd_perf")] #[cfg(feature = "simd_perf")]
#[inline(always)]
pub fn v_min(&self, other: Float4) -> Float4 { pub fn v_min(&self, other: Float4) -> Float4 {
Float4 { data: self.data.min(other.data) } Float4 { data: self.data.min(other.data) }
} }
#[cfg(not(feature = "simd_perf"))] #[cfg(not(feature = "simd_perf"))]
#[inline]
pub fn v_min(&self, other: Float4) -> Float4 { pub fn v_min(&self, other: Float4) -> Float4 {
Float4::new(if self.get_0() < other.get_0() { Float4::new(if self.get_0() < other.get_0() {
self.get_0() self.get_0()
@ -107,10 +118,12 @@ impl Float4 {
} }
#[cfg(feature = "simd_perf")] #[cfg(feature = "simd_perf")]
#[inline(always)]
pub fn v_max(&self, other: Float4) -> Float4 { pub fn v_max(&self, other: Float4) -> Float4 {
Float4 { data: self.data.max(other.data) } Float4 { data: self.data.max(other.data) }
} }
#[cfg(not(feature = "simd_perf"))] #[cfg(not(feature = "simd_perf"))]
#[inline]
pub fn v_max(&self, other: Float4) -> Float4 { pub fn v_max(&self, other: Float4) -> Float4 {
Float4::new(if self.get_0() > other.get_0() { Float4::new(if self.get_0() > other.get_0() {
self.get_0() self.get_0()
@ -135,10 +148,12 @@ impl Float4 {
} }
#[cfg(feature = "simd_perf")] #[cfg(feature = "simd_perf")]
#[inline(always)]
pub fn lt(&self, other: Float4) -> Bool4 { pub fn lt(&self, other: Float4) -> Bool4 {
Bool4 { data: self.data.lt(other.data) } Bool4 { data: self.data.lt(other.data) }
} }
#[cfg(not(feature = "simd_perf"))] #[cfg(not(feature = "simd_perf"))]
#[inline]
pub fn lt(&self, other: Float4) -> Bool4 { pub fn lt(&self, other: Float4) -> Bool4 {
Bool4 { Bool4 {
data: [self.data[0] < other.data[0], data: [self.data[0] < other.data[0],
@ -149,10 +164,12 @@ impl Float4 {
} }
#[cfg(feature = "simd_perf")] #[cfg(feature = "simd_perf")]
#[inline(always)]
pub fn lte(&self, other: Float4) -> Bool4 { pub fn lte(&self, other: Float4) -> Bool4 {
Bool4 { data: self.data.le(other.data) } Bool4 { data: self.data.le(other.data) }
} }
#[cfg(not(feature = "simd_perf"))] #[cfg(not(feature = "simd_perf"))]
#[inline]
pub fn lte(&self, other: Float4) -> Bool4 { pub fn lte(&self, other: Float4) -> Bool4 {
Bool4 { Bool4 {
data: [self.data[0] <= other.data[0], data: [self.data[0] <= other.data[0],
@ -163,10 +180,12 @@ impl Float4 {
} }
#[cfg(feature = "simd_perf")] #[cfg(feature = "simd_perf")]
#[inline(always)]
pub fn gt(&self, other: Float4) -> Bool4 { pub fn gt(&self, other: Float4) -> Bool4 {
Bool4 { data: self.data.gt(other.data) } Bool4 { data: self.data.gt(other.data) }
} }
#[cfg(not(feature = "simd_perf"))] #[cfg(not(feature = "simd_perf"))]
#[inline]
pub fn gt(&self, other: Float4) -> Bool4 { pub fn gt(&self, other: Float4) -> Bool4 {
Bool4 { Bool4 {
data: [self.data[0] > other.data[0], data: [self.data[0] > other.data[0],
@ -177,10 +196,12 @@ impl Float4 {
} }
#[cfg(feature = "simd_perf")] #[cfg(feature = "simd_perf")]
#[inline(always)]
pub fn gte(&self, other: Float4) -> Bool4 { pub fn gte(&self, other: Float4) -> Bool4 {
Bool4 { data: self.data.ge(other.data) } Bool4 { data: self.data.ge(other.data) }
} }
#[cfg(not(feature = "simd_perf"))] #[cfg(not(feature = "simd_perf"))]
#[inline]
pub fn gte(&self, other: Float4) -> Bool4 { pub fn gte(&self, other: Float4) -> Bool4 {
Bool4 { Bool4 {
data: [self.data[0] >= other.data[0], data: [self.data[0] >= other.data[0],
@ -208,8 +229,8 @@ impl Float4 {
pub fn set_0(&mut self, n: f32) { pub fn set_0(&mut self, n: f32) {
self.data = self.data.replace(0, n); self.data = self.data.replace(0, n);
} }
#[inline(always)]
#[cfg(not(feature = "simd_perf"))] #[cfg(not(feature = "simd_perf"))]
#[inline(always)]
pub fn set_0(&mut self, n: f32) { pub fn set_0(&mut self, n: f32) {
unsafe { unsafe {
*self.data.get_unchecked_mut(0) = n; *self.data.get_unchecked_mut(0) = n;
@ -321,6 +342,7 @@ impl Float4 {
impl PartialEq for Float4 { impl PartialEq for Float4 {
#[inline]
fn eq(&self, other: &Float4) -> bool { fn eq(&self, other: &Float4) -> bool {
self.get_0() == other.get_0() && self.get_1() == other.get_1() && self.get_0() == other.get_0() && self.get_1() == other.get_1() &&
self.get_2() == other.get_2() && self.get_3() == other.get_3() self.get_2() == other.get_2() && self.get_3() == other.get_3()
@ -332,10 +354,12 @@ impl Add for Float4 {
type Output = Float4; type Output = Float4;
#[cfg(feature = "simd_perf")] #[cfg(feature = "simd_perf")]
#[inline(always)]
fn add(self, other: Float4) -> Float4 { fn add(self, other: Float4) -> Float4 {
Float4 { data: self.data + other.data } Float4 { data: self.data + other.data }
} }
#[cfg(not(feature = "simd_perf"))] #[cfg(not(feature = "simd_perf"))]
#[inline(always)]
fn add(self, other: Float4) -> Float4 { fn add(self, other: Float4) -> Float4 {
Float4 { Float4 {
data: [self.get_0() + other.get_0(), data: [self.get_0() + other.get_0(),
@ -348,6 +372,7 @@ impl Add for Float4 {
impl AddAssign for Float4 { impl AddAssign for Float4 {
#[inline(always)]
fn add_assign(&mut self, rhs: Float4) { fn add_assign(&mut self, rhs: Float4) {
*self = *self + rhs; *self = *self + rhs;
} }
@ -358,10 +383,12 @@ impl Sub for Float4 {
type Output = Float4; type Output = Float4;
#[cfg(feature = "simd_perf")] #[cfg(feature = "simd_perf")]
#[inline(always)]
fn sub(self, other: Float4) -> Float4 { fn sub(self, other: Float4) -> Float4 {
Float4 { data: self.data - other.data } Float4 { data: self.data - other.data }
} }
#[cfg(not(feature = "simd_perf"))] #[cfg(not(feature = "simd_perf"))]
#[inline(always)]
fn sub(self, other: Float4) -> Float4 { fn sub(self, other: Float4) -> Float4 {
Float4 { Float4 {
data: [self.get_0() - other.get_0(), data: [self.get_0() - other.get_0(),
@ -374,6 +401,7 @@ impl Sub for Float4 {
impl SubAssign for Float4 { impl SubAssign for Float4 {
#[inline(always)]
fn sub_assign(&mut self, rhs: Float4) { fn sub_assign(&mut self, rhs: Float4) {
*self = *self - rhs; *self = *self - rhs;
} }
@ -384,10 +412,12 @@ impl Mul for Float4 {
type Output = Float4; type Output = Float4;
#[cfg(feature = "simd_perf")] #[cfg(feature = "simd_perf")]
#[inline(always)]
fn mul(self, other: Float4) -> Float4 { fn mul(self, other: Float4) -> Float4 {
Float4 { data: self.data * other.data } Float4 { data: self.data * other.data }
} }
#[cfg(not(feature = "simd_perf"))] #[cfg(not(feature = "simd_perf"))]
#[inline(always)]
fn mul(self, other: Float4) -> Float4 { fn mul(self, other: Float4) -> Float4 {
Float4 { Float4 {
data: [self.get_0() * other.get_0(), data: [self.get_0() * other.get_0(),
@ -402,10 +432,12 @@ impl Mul<f32> for Float4 {
type Output = Float4; type Output = Float4;
#[cfg(feature = "simd_perf")] #[cfg(feature = "simd_perf")]
#[inline(always)]
fn mul(self, other: f32) -> Float4 { fn mul(self, other: f32) -> Float4 {
Float4 { data: self.data * f32x4::splat(other) } Float4 { data: self.data * f32x4::splat(other) }
} }
#[cfg(not(feature = "simd_perf"))] #[cfg(not(feature = "simd_perf"))]
#[inline(always)]
fn mul(self, other: f32) -> Float4 { fn mul(self, other: f32) -> Float4 {
Float4 { Float4 {
data: [self.get_0() * other, data: [self.get_0() * other,
@ -418,12 +450,14 @@ impl Mul<f32> for Float4 {
impl MulAssign for Float4 { impl MulAssign for Float4 {
#[inline(always)]
fn mul_assign(&mut self, rhs: Float4) { fn mul_assign(&mut self, rhs: Float4) {
*self = *self * rhs; *self = *self * rhs;
} }
} }
impl MulAssign<f32> for Float4 { impl MulAssign<f32> for Float4 {
#[inline(always)]
fn mul_assign(&mut self, rhs: f32) { fn mul_assign(&mut self, rhs: f32) {
*self = *self * rhs; *self = *self * rhs;
} }
@ -434,10 +468,12 @@ impl Div for Float4 {
type Output = Float4; type Output = Float4;
#[cfg(feature = "simd_perf")] #[cfg(feature = "simd_perf")]
#[inline(always)]
fn div(self, other: Float4) -> Float4 { fn div(self, other: Float4) -> Float4 {
Float4 { data: self.data / other.data } Float4 { data: self.data / other.data }
} }
#[cfg(not(feature = "simd_perf"))] #[cfg(not(feature = "simd_perf"))]
#[inline(always)]
fn div(self, other: Float4) -> Float4 { fn div(self, other: Float4) -> Float4 {
Float4 { Float4 {
data: [self.get_0() / other.get_0(), data: [self.get_0() / other.get_0(),
@ -452,10 +488,12 @@ impl Div<f32> for Float4 {
type Output = Float4; type Output = Float4;
#[cfg(feature = "simd_perf")] #[cfg(feature = "simd_perf")]
#[inline(always)]
fn div(self, other: f32) -> Float4 { fn div(self, other: f32) -> Float4 {
Float4 { data: self.data / f32x4::splat(other) } Float4 { data: self.data / f32x4::splat(other) }
} }
#[cfg(not(feature = "simd_perf"))] #[cfg(not(feature = "simd_perf"))]
#[inline(always)]
fn div(self, other: f32) -> Float4 { fn div(self, other: f32) -> Float4 {
Float4 { Float4 {
data: [self.get_0() / other, data: [self.get_0() / other,
@ -468,24 +506,19 @@ impl Div<f32> for Float4 {
impl DivAssign for Float4 { impl DivAssign for Float4 {
#[inline(always)]
fn div_assign(&mut self, rhs: Float4) { fn div_assign(&mut self, rhs: Float4) {
*self = *self / rhs; *self = *self / rhs;
} }
} }
impl DivAssign<f32> for Float4 { impl DivAssign<f32> for Float4 {
#[inline(always)]
fn div_assign(&mut self, rhs: f32) { fn div_assign(&mut self, rhs: f32) {
*self = *self / rhs; *self = *self / rhs;
} }
} }
impl Lerp for Float4 {
fn lerp(self, other: Float4, alpha: f32) -> Float4 {
(self * (1.0 - alpha)) + (other * alpha)
}
}
#[inline(always)] #[inline(always)]
pub fn v_min(a: Float4, b: Float4) -> Float4 { pub fn v_min(a: Float4, b: Float4) -> Float4 {
a.v_min(b) a.v_min(b)
@ -560,6 +593,7 @@ impl Bool4 {
unsafe { *self.data.get_unchecked(3) } unsafe { *self.data.get_unchecked(3) }
} }
#[inline]
pub fn to_bitmask(&self) -> u8 { pub fn to_bitmask(&self) -> u8 {
(self.get_0() as u8) | ((self.get_1() as u8) << 1) | ((self.get_2() as u8) << 2) | (self.get_0() as u8) | ((self.get_1() as u8) << 1) | ((self.get_2() as u8) << 2) |
((self.get_3() as u8) << 3) ((self.get_3() as u8) << 3)
@ -570,10 +604,12 @@ impl BitAnd for Bool4 {
type Output = Bool4; type Output = Bool4;
#[cfg(feature = "simd_perf")] #[cfg(feature = "simd_perf")]
#[inline(always)]
fn bitand(self, rhs: Bool4) -> Bool4 { fn bitand(self, rhs: Bool4) -> Bool4 {
Bool4 { data: self.data & rhs.data } Bool4 { data: self.data & rhs.data }
} }
#[cfg(not(feature = "simd_perf"))] #[cfg(not(feature = "simd_perf"))]
#[inline]
fn bitand(self, rhs: Bool4) -> Bool4 { fn bitand(self, rhs: Bool4) -> Bool4 {
Bool4 { Bool4 {
data: [self.data[0] && rhs.data[0], data: [self.data[0] && rhs.data[0],

View File

@ -0,0 +1,16 @@
[package]
name = "math3d"
version = "0.1.0"
authors = ["Nathan Vegdahl <cessen@cessen.com>"]
license = "MIT"
[lib]
name = "math3d"
path = "src/lib.rs"
[features]
simd_perf = ["float4/simd_perf"]
# Local crate dependencies
[dependencies.float4]
path = "../float4"

View File

@ -0,0 +1,36 @@
#![allow(dead_code)]
extern crate float4;
mod matrix;
mod normal;
mod point;
mod vector;
pub use self::matrix::Matrix4x4;
pub use self::normal::Normal;
pub use self::point::Point;
pub use self::vector::Vector;
/// Trait for calculating dot products.
pub trait DotProduct {
#[inline]
fn dot(self, other: Self) -> f32;
}
#[inline]
pub fn dot<T: DotProduct>(a: T, b: T) -> f32 {
a.dot(b)
}
/// Trait for calculating cross products.
pub trait CrossProduct {
#[inline]
fn cross(self, other: Self) -> Self;
}
#[inline]
pub fn cross<T: CrossProduct>(a: T, b: T) -> T {
a.cross(b)
}

View File

@ -4,7 +4,6 @@ use std;
use std::ops::{Index, IndexMut, Mul}; use std::ops::{Index, IndexMut, Mul};
use float4::Float4; use float4::Float4;
use lerp::Lerp;
use super::Point; use super::Point;
@ -12,12 +11,13 @@ use super::Point;
/// A 4x4 matrix, used for transforms /// A 4x4 matrix, used for transforms
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct Matrix4x4 { pub struct Matrix4x4 {
values: [Float4; 4], pub values: [Float4; 4],
} }
impl Matrix4x4 { impl Matrix4x4 {
/// Creates a new identity matrix /// Creates a new identity matrix
#[inline]
pub fn new() -> Matrix4x4 { pub fn new() -> Matrix4x4 {
Matrix4x4 { Matrix4x4 {
values: [Float4::new(1.0, 0.0, 0.0, 0.0), values: [Float4::new(1.0, 0.0, 0.0, 0.0),
@ -32,6 +32,7 @@ impl Matrix4x4 {
/// e f g h /// e f g h
/// i j k l /// i j k l
/// m n o p /// m n o p
#[inline]
pub fn new_from_values(a: f32, pub fn new_from_values(a: f32,
b: f32, b: f32,
c: f32, c: f32,
@ -57,6 +58,7 @@ impl Matrix4x4 {
} }
} }
#[inline]
pub fn from_location(loc: Point) -> Matrix4x4 { pub fn from_location(loc: Point) -> Matrix4x4 {
Matrix4x4 { Matrix4x4 {
values: [Float4::new(1.0, 0.0, 0.0, loc.x()), values: [Float4::new(1.0, 0.0, 0.0, loc.x()),
@ -69,6 +71,7 @@ impl Matrix4x4 {
/// Returns whether the matrices are approximately equal to each other. /// Returns whether the matrices are approximately equal to each other.
/// Each corresponding element in the matrices cannot have a relative error /// Each corresponding element in the matrices cannot have a relative error
/// exceeding `epsilon`. /// exceeding `epsilon`.
#[inline]
pub fn aprx_eq(&self, other: Matrix4x4, epsilon: f32) -> bool { pub fn aprx_eq(&self, other: Matrix4x4, epsilon: f32) -> bool {
let mut result = true; let mut result = true;
@ -99,6 +102,7 @@ impl Matrix4x4 {
} }
/// Returns the transpose of the matrix /// Returns the transpose of the matrix
#[inline]
pub fn transposed(&self) -> Matrix4x4 { pub fn transposed(&self) -> Matrix4x4 {
Matrix4x4 { Matrix4x4 {
values: { values: {
@ -124,6 +128,7 @@ impl Matrix4x4 {
/// Returns the inverse of the Matrix /// Returns the inverse of the Matrix
#[inline]
pub fn inverse(&self) -> Matrix4x4 { pub fn inverse(&self) -> Matrix4x4 {
let s0 = (self[0].get_0() * self[1].get_1()) - (self[1].get_0() * self[0].get_1()); let s0 = (self[0].get_0() * self[1].get_1()) - (self[1].get_0() * self[0].get_1());
let s1 = (self[0].get_0() * self[1].get_2()) - (self[1].get_0() * self[0].get_2()); let s1 = (self[0].get_0() * self[1].get_2()) - (self[1].get_0() * self[0].get_2());
@ -189,6 +194,7 @@ impl Matrix4x4 {
impl Index<usize> for Matrix4x4 { impl Index<usize> for Matrix4x4 {
type Output = Float4; type Output = Float4;
#[inline(always)]
fn index<'a>(&'a self, _index: usize) -> &'a Float4 { fn index<'a>(&'a self, _index: usize) -> &'a Float4 {
&self.values[_index] &self.values[_index]
} }
@ -196,6 +202,7 @@ impl Index<usize> for Matrix4x4 {
impl IndexMut<usize> for Matrix4x4 { impl IndexMut<usize> for Matrix4x4 {
#[inline(always)]
fn index_mut<'a>(&'a mut self, _index: usize) -> &'a mut Float4 { fn index_mut<'a>(&'a mut self, _index: usize) -> &'a mut Float4 {
&mut self.values[_index] &mut self.values[_index]
} }
@ -203,6 +210,7 @@ impl IndexMut<usize> for Matrix4x4 {
impl PartialEq for Matrix4x4 { impl PartialEq for Matrix4x4 {
#[inline]
fn eq(&self, other: &Matrix4x4) -> bool { fn eq(&self, other: &Matrix4x4) -> bool {
let mut result = true; let mut result = true;
@ -221,6 +229,7 @@ impl PartialEq for Matrix4x4 {
impl Mul<Matrix4x4> for Matrix4x4 { impl Mul<Matrix4x4> for Matrix4x4 {
type Output = Matrix4x4; type Output = Matrix4x4;
#[inline]
fn mul(self, other: Matrix4x4) -> Matrix4x4 { fn mul(self, other: Matrix4x4) -> Matrix4x4 {
let m = self.transposed(); let m = self.transposed();
Matrix4x4 { Matrix4x4 {
@ -248,23 +257,12 @@ impl Mul<Matrix4x4> for Matrix4x4 {
} }
impl Lerp for Matrix4x4 {
fn lerp(self, other: Matrix4x4, alpha: f32) -> Matrix4x4 {
let alpha_minus = 1.0 - alpha;
Matrix4x4 {
values: [(self[0] * alpha_minus) + (other[0] * alpha),
(self[1] * alpha_minus) + (other[1] * alpha),
(self[2] * alpha_minus) + (other[2] * alpha),
(self[3] * alpha_minus) + (other[3] * alpha)],
}
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use lerp::Lerp;
#[test] #[test]
fn equality_test() { fn equality_test() {
@ -464,95 +462,4 @@ mod tests {
assert_eq!(b, c); assert_eq!(b, c);
} }
#[test]
fn lerp_test() {
let a = Matrix4x4::new_from_values(0.0,
2.0,
2.0,
3.0,
4.0,
5.0,
6.0,
7.0,
8.0,
9.0,
10.0,
11.0,
12.0,
13.0,
14.0,
15.0);
let b = Matrix4x4::new_from_values(-1.0,
1.0,
3.0,
4.0,
5.0,
6.0,
7.0,
8.0,
9.0,
10.0,
11.0,
12.0,
13.0,
14.0,
15.0,
16.0);
let c1 = Matrix4x4::new_from_values(-0.25,
1.75,
2.25,
3.25,
4.25,
5.25,
6.25,
7.25,
8.25,
9.25,
10.25,
11.25,
12.25,
13.25,
14.25,
15.25);
let c2 = Matrix4x4::new_from_values(-0.5,
1.5,
2.5,
3.5,
4.5,
5.5,
6.5,
7.5,
8.5,
9.5,
10.5,
11.5,
12.5,
13.5,
14.5,
15.5);
let c3 = Matrix4x4::new_from_values(-0.75,
1.25,
2.75,
3.75,
4.75,
5.75,
6.75,
7.75,
8.75,
9.75,
10.75,
11.75,
12.75,
13.75,
14.75,
15.75);
assert_eq!(a.lerp(b, 0.0), a);
assert_eq!(a.lerp(b, 0.25), c1);
assert_eq!(a.lerp(b, 0.5), c2);
assert_eq!(a.lerp(b, 0.75), c3);
assert_eq!(a.lerp(b, 1.0), b);
}
} }

View File

@ -4,7 +4,6 @@ use std::cmp::PartialEq;
use std::ops::{Add, Sub, Mul, Div, Neg}; use std::ops::{Add, Sub, Mul, Div, Neg};
use float4::Float4; use float4::Float4;
use lerp::Lerp;
use super::{DotProduct, CrossProduct}; use super::{DotProduct, CrossProduct};
use super::{Matrix4x4, Vector}; use super::{Matrix4x4, Vector};
@ -17,26 +16,32 @@ pub struct Normal {
} }
impl Normal { impl Normal {
#[inline(always)]
pub fn new(x: f32, y: f32, z: f32) -> Normal { pub fn new(x: f32, y: f32, z: f32) -> Normal {
Normal { co: Float4::new(x, y, z, 0.0) } Normal { co: Float4::new(x, y, z, 0.0) }
} }
#[inline(always)]
pub fn length(&self) -> f32 { pub fn length(&self) -> f32 {
(self.co * self.co).h_sum().sqrt() (self.co * self.co).h_sum().sqrt()
} }
#[inline(always)]
pub fn length2(&self) -> f32 { pub fn length2(&self) -> f32 {
(self.co * self.co).h_sum() (self.co * self.co).h_sum()
} }
#[inline(always)]
pub fn normalized(&self) -> Normal { pub fn normalized(&self) -> Normal {
*self / self.length() *self / self.length()
} }
#[inline(always)]
pub fn into_vector(self) -> Vector { pub fn into_vector(self) -> Vector {
Vector::new(self.co.get_0(), self.co.get_1(), self.co.get_2()) Vector::new(self.co.get_0(), self.co.get_1(), self.co.get_2())
} }
#[inline(always)]
pub fn get_n(&self, n: usize) -> f32 { pub fn get_n(&self, n: usize) -> f32 {
match n { match n {
0 => self.x(), 0 => self.x(),
@ -46,26 +51,32 @@ impl Normal {
} }
} }
#[inline(always)]
pub fn x(&self) -> f32 { pub fn x(&self) -> f32 {
self.co.get_0() self.co.get_0()
} }
#[inline(always)]
pub fn y(&self) -> f32 { pub fn y(&self) -> f32 {
self.co.get_1() self.co.get_1()
} }
#[inline(always)]
pub fn z(&self) -> f32 { pub fn z(&self) -> f32 {
self.co.get_2() self.co.get_2()
} }
#[inline(always)]
pub fn set_x(&mut self, x: f32) { pub fn set_x(&mut self, x: f32) {
self.co.set_0(x); self.co.set_0(x);
} }
#[inline(always)]
pub fn set_y(&mut self, y: f32) { pub fn set_y(&mut self, y: f32) {
self.co.set_1(y); self.co.set_1(y);
} }
#[inline(always)]
pub fn set_z(&mut self, z: f32) { pub fn set_z(&mut self, z: f32) {
self.co.set_2(z); self.co.set_2(z);
} }
@ -73,6 +84,7 @@ impl Normal {
impl PartialEq for Normal { impl PartialEq for Normal {
#[inline(always)]
fn eq(&self, other: &Normal) -> bool { fn eq(&self, other: &Normal) -> bool {
self.co == other.co self.co == other.co
} }
@ -82,6 +94,7 @@ impl PartialEq for Normal {
impl Add for Normal { impl Add for Normal {
type Output = Normal; type Output = Normal;
#[inline(always)]
fn add(self, other: Normal) -> Normal { fn add(self, other: Normal) -> Normal {
Normal { co: self.co + other.co } Normal { co: self.co + other.co }
} }
@ -91,6 +104,7 @@ impl Add for Normal {
impl Sub for Normal { impl Sub for Normal {
type Output = Normal; type Output = Normal;
#[inline(always)]
fn sub(self, other: Normal) -> Normal { fn sub(self, other: Normal) -> Normal {
Normal { co: self.co - other.co } Normal { co: self.co - other.co }
} }
@ -100,6 +114,7 @@ impl Sub for Normal {
impl Mul<f32> for Normal { impl Mul<f32> for Normal {
type Output = Normal; type Output = Normal;
#[inline(always)]
fn mul(self, other: f32) -> Normal { fn mul(self, other: f32) -> Normal {
Normal { co: self.co * other } Normal { co: self.co * other }
} }
@ -108,12 +123,13 @@ impl Mul<f32> for Normal {
impl Mul<Matrix4x4> for Normal { impl Mul<Matrix4x4> for Normal {
type Output = Normal; type Output = Normal;
#[inline]
fn mul(self, other: Matrix4x4) -> Normal { fn mul(self, other: Matrix4x4) -> Normal {
let mat = other.inverse().transposed(); let mat = other.inverse().transposed();
Normal { Normal {
co: Float4::new((self.co * mat[0]).h_sum(), co: Float4::new((self.co * mat.values[0]).h_sum(),
(self.co * mat[1]).h_sum(), (self.co * mat.values[1]).h_sum(),
(self.co * mat[2]).h_sum(), (self.co * mat.values[2]).h_sum(),
0.0), 0.0),
} }
} }
@ -123,6 +139,7 @@ impl Mul<Matrix4x4> for Normal {
impl Div<f32> for Normal { impl Div<f32> for Normal {
type Output = Normal; type Output = Normal;
#[inline(always)]
fn div(self, other: f32) -> Normal { fn div(self, other: f32) -> Normal {
Normal { co: self.co / other } Normal { co: self.co / other }
} }
@ -132,20 +149,15 @@ impl Div<f32> for Normal {
impl Neg for Normal { impl Neg for Normal {
type Output = Normal; type Output = Normal;
#[inline(always)]
fn neg(self) -> Normal { fn neg(self) -> Normal {
Normal { co: self.co * -1.0 } Normal { co: self.co * -1.0 }
} }
} }
impl Lerp for Normal {
fn lerp(self, other: Normal, alpha: f32) -> Normal {
(self * (1.0 - alpha)) + (other * alpha)
}
}
impl DotProduct for Normal { impl DotProduct for Normal {
#[inline(always)]
fn dot(self, other: Normal) -> f32 { fn dot(self, other: Normal) -> f32 {
(self.co * other.co).h_sum() (self.co * other.co).h_sum()
} }
@ -153,6 +165,7 @@ impl DotProduct for Normal {
impl CrossProduct for Normal { impl CrossProduct for Normal {
#[inline]
fn cross(self, other: Normal) -> Normal { fn cross(self, other: Normal) -> Normal {
Normal { Normal {
co: Float4::new((self.co.get_1() * other.co.get_2()) - co: Float4::new((self.co.get_1() * other.co.get_2()) -
@ -171,7 +184,6 @@ impl CrossProduct for Normal {
mod tests { mod tests {
use super::*; use super::*;
use super::super::{Matrix4x4, CrossProduct, DotProduct}; use super::super::{Matrix4x4, CrossProduct, DotProduct};
use lerp::Lerp;
#[test] #[test]
fn add() { fn add() {
@ -271,31 +283,4 @@ mod tests {
assert_eq!(v3, v1.cross(v2)); assert_eq!(v3, v1.cross(v2));
} }
#[test]
fn lerp1() {
let n1 = Normal::new(1.0, 2.0, 1.0);
let n2 = Normal::new(-2.0, 1.0, -1.0);
let n3 = Normal::new(1.0, 2.0, 1.0);
assert_eq!(n3, n1.lerp(n2, 0.0));
}
#[test]
fn lerp2() {
let n1 = Normal::new(1.0, 2.0, 1.0);
let n2 = Normal::new(-2.0, 1.0, -1.0);
let n3 = Normal::new(-2.0, 1.0, -1.0);
assert_eq!(n3, n1.lerp(n2, 1.0));
}
#[test]
fn lerp3() {
let n1 = Normal::new(1.0, 2.0, 1.0);
let n2 = Normal::new(-2.0, 1.0, -1.0);
let n3 = Normal::new(-0.5, 1.5, 0.0);
assert_eq!(n3, n1.lerp(n2, 0.5));
}
} }

View File

@ -4,7 +4,6 @@ use std::cmp::PartialEq;
use std::ops::{Add, Sub, Mul}; use std::ops::{Add, Sub, Mul};
use float4::Float4; use float4::Float4;
use lerp::Lerp;
use super::Matrix4x4; use super::Matrix4x4;
use super::Vector; use super::Vector;
@ -17,16 +16,19 @@ pub struct Point {
} }
impl Point { impl Point {
#[inline(always)]
pub fn new(x: f32, y: f32, z: f32) -> Point { pub fn new(x: f32, y: f32, z: f32) -> Point {
Point { co: Float4::new(x, y, z, 1.0) } Point { co: Float4::new(x, y, z, 1.0) }
} }
/// Returns the point in standardized coordinates, where the /// Returns the point in standardized coordinates, where the
/// fourth homogeneous component has been normalized to 1.0. /// fourth homogeneous component has been normalized to 1.0.
#[inline(always)]
pub fn norm(&self) -> Point { pub fn norm(&self) -> Point {
Point { co: self.co / self.co.get_3() } Point { co: self.co / self.co.get_3() }
} }
#[inline(always)]
pub fn min(&self, other: Point) -> Point { pub fn min(&self, other: Point) -> Point {
let n1 = self.norm(); let n1 = self.norm();
let n2 = other.norm(); let n2 = other.norm();
@ -34,6 +36,7 @@ impl Point {
Point { co: n1.co.v_min(n2.co) } Point { co: n1.co.v_min(n2.co) }
} }
#[inline(always)]
pub fn max(&self, other: Point) -> Point { pub fn max(&self, other: Point) -> Point {
let n1 = self.norm(); let n1 = self.norm();
let n2 = other.norm(); let n2 = other.norm();
@ -41,10 +44,12 @@ impl Point {
Point { co: n1.co.v_max(n2.co) } Point { co: n1.co.v_max(n2.co) }
} }
#[inline(always)]
pub fn into_vector(self) -> Vector { pub fn into_vector(self) -> Vector {
Vector::new(self.co.get_0(), self.co.get_1(), self.co.get_2()) Vector::new(self.co.get_0(), self.co.get_1(), self.co.get_2())
} }
#[inline(always)]
pub fn get_n(&self, n: usize) -> f32 { pub fn get_n(&self, n: usize) -> f32 {
match n { match n {
0 => self.x(), 0 => self.x(),
@ -54,26 +59,32 @@ impl Point {
} }
} }
#[inline(always)]
pub fn x(&self) -> f32 { pub fn x(&self) -> f32 {
self.co.get_0() self.co.get_0()
} }
#[inline(always)]
pub fn y(&self) -> f32 { pub fn y(&self) -> f32 {
self.co.get_1() self.co.get_1()
} }
#[inline(always)]
pub fn z(&self) -> f32 { pub fn z(&self) -> f32 {
self.co.get_2() self.co.get_2()
} }
#[inline(always)]
pub fn set_x(&mut self, x: f32) { pub fn set_x(&mut self, x: f32) {
self.co.set_0(x); self.co.set_0(x);
} }
#[inline(always)]
pub fn set_y(&mut self, y: f32) { pub fn set_y(&mut self, y: f32) {
self.co.set_1(y); self.co.set_1(y);
} }
#[inline(always)]
pub fn set_z(&mut self, z: f32) { pub fn set_z(&mut self, z: f32) {
self.co.set_2(z); self.co.set_2(z);
} }
@ -81,6 +92,7 @@ impl Point {
impl PartialEq for Point { impl PartialEq for Point {
#[inline(always)]
fn eq(&self, other: &Point) -> bool { fn eq(&self, other: &Point) -> bool {
self.co == other.co self.co == other.co
} }
@ -90,6 +102,7 @@ impl PartialEq for Point {
impl Add<Vector> for Point { impl Add<Vector> for Point {
type Output = Point; type Output = Point;
#[inline(always)]
fn add(self, other: Vector) -> Point { fn add(self, other: Vector) -> Point {
Point { co: self.co + other.co } Point { co: self.co + other.co }
} }
@ -99,6 +112,7 @@ impl Add<Vector> for Point {
impl Sub for Point { impl Sub for Point {
type Output = Vector; type Output = Vector;
#[inline(always)]
fn sub(self, other: Point) -> Vector { fn sub(self, other: Point) -> Vector {
Vector { co: self.norm().co - other.norm().co } Vector { co: self.norm().co - other.norm().co }
} }
@ -107,6 +121,7 @@ impl Sub for Point {
impl Sub<Vector> for Point { impl Sub<Vector> for Point {
type Output = Point; type Output = Point;
#[inline(always)]
fn sub(self, other: Vector) -> Point { fn sub(self, other: Vector) -> Point {
Point { co: self.co - other.co } Point { co: self.co - other.co }
} }
@ -115,31 +130,22 @@ impl Sub<Vector> for Point {
impl Mul<Matrix4x4> for Point { impl Mul<Matrix4x4> for Point {
type Output = Point; type Output = Point;
#[inline]
fn mul(self, other: Matrix4x4) -> Point { fn mul(self, other: Matrix4x4) -> Point {
Point { Point {
co: Float4::new((self.co * other[0]).h_sum(), co: Float4::new((self.co * other.values[0]).h_sum(),
(self.co * other[1]).h_sum(), (self.co * other.values[1]).h_sum(),
(self.co * other[2]).h_sum(), (self.co * other.values[2]).h_sum(),
(self.co * other[3]).h_sum()), (self.co * other.values[3]).h_sum()),
} }
} }
} }
impl Lerp for Point {
fn lerp(self, other: Point, alpha: f32) -> Point {
let s = self.norm();
let o = other.norm();
Point { co: (s.co * (1.0 - alpha)) + (o.co * alpha) }
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use super::super::{Vector, Matrix4x4}; use super::super::{Vector, Matrix4x4};
use lerp::Lerp;
#[test] #[test]
fn norm() { fn norm() {
@ -258,31 +264,4 @@ mod tests {
assert!((pmm1 - pmm2).length2() <= 0.00001); // Assert pmm1 and pmm2 are roughly equal assert!((pmm1 - pmm2).length2() <= 0.00001); // Assert pmm1 and pmm2 are roughly equal
} }
#[test]
fn lerp1() {
let p1 = Point::new(1.0, 2.0, 1.0);
let p2 = Point::new(-2.0, 1.0, -1.0);
let p3 = Point::new(1.0, 2.0, 1.0);
assert_eq!(p3, p1.lerp(p2, 0.0));
}
#[test]
fn lerp2() {
let p1 = Point::new(1.0, 2.0, 1.0);
let p2 = Point::new(-2.0, 1.0, -1.0);
let p3 = Point::new(-2.0, 1.0, -1.0);
assert_eq!(p3, p1.lerp(p2, 1.0));
}
#[test]
fn lerp3() {
let p1 = Point::new(1.0, 2.0, 1.0);
let p2 = Point::new(-2.0, 1.0, -1.0);
let p3 = Point::new(-0.5, 1.5, 0.0);
assert_eq!(p3, p1.lerp(p2, 0.5));
}
} }

View File

@ -4,7 +4,6 @@ use std::cmp::PartialEq;
use std::ops::{Add, Sub, Mul, Div, Neg}; use std::ops::{Add, Sub, Mul, Div, Neg};
use float4::Float4; use float4::Float4;
use lerp::Lerp;
use super::{DotProduct, CrossProduct}; use super::{DotProduct, CrossProduct};
use super::{Matrix4x4, Normal}; use super::{Matrix4x4, Normal};
@ -17,26 +16,32 @@ pub struct Vector {
} }
impl Vector { impl Vector {
#[inline(always)]
pub fn new(x: f32, y: f32, z: f32) -> Vector { pub fn new(x: f32, y: f32, z: f32) -> Vector {
Vector { co: Float4::new(x, y, z, 0.0) } Vector { co: Float4::new(x, y, z, 0.0) }
} }
#[inline(always)]
pub fn length(&self) -> f32 { pub fn length(&self) -> f32 {
(self.co * self.co).h_sum().sqrt() (self.co * self.co).h_sum().sqrt()
} }
#[inline(always)]
pub fn length2(&self) -> f32 { pub fn length2(&self) -> f32 {
(self.co * self.co).h_sum() (self.co * self.co).h_sum()
} }
#[inline(always)]
pub fn normalized(&self) -> Vector { pub fn normalized(&self) -> Vector {
*self / self.length() *self / self.length()
} }
#[inline(always)]
pub fn into_normal(self) -> Normal { pub fn into_normal(self) -> Normal {
Normal::new(self.x(), self.y(), self.z()) Normal::new(self.x(), self.y(), self.z())
} }
#[inline(always)]
pub fn get_n(&self, n: usize) -> f32 { pub fn get_n(&self, n: usize) -> f32 {
match n { match n {
0 => self.x(), 0 => self.x(),
@ -46,26 +51,32 @@ impl Vector {
} }
} }
#[inline(always)]
pub fn x(&self) -> f32 { pub fn x(&self) -> f32 {
self.co.get_0() self.co.get_0()
} }
#[inline(always)]
pub fn y(&self) -> f32 { pub fn y(&self) -> f32 {
self.co.get_1() self.co.get_1()
} }
#[inline(always)]
pub fn z(&self) -> f32 { pub fn z(&self) -> f32 {
self.co.get_2() self.co.get_2()
} }
#[inline(always)]
pub fn set_x(&mut self, x: f32) { pub fn set_x(&mut self, x: f32) {
self.co.set_0(x); self.co.set_0(x);
} }
#[inline(always)]
pub fn set_y(&mut self, y: f32) { pub fn set_y(&mut self, y: f32) {
self.co.set_1(y); self.co.set_1(y);
} }
#[inline(always)]
pub fn set_z(&mut self, z: f32) { pub fn set_z(&mut self, z: f32) {
self.co.set_2(z); self.co.set_2(z);
} }
@ -73,6 +84,7 @@ impl Vector {
impl PartialEq for Vector { impl PartialEq for Vector {
#[inline(always)]
fn eq(&self, other: &Vector) -> bool { fn eq(&self, other: &Vector) -> bool {
self.co == other.co self.co == other.co
} }
@ -82,6 +94,7 @@ impl PartialEq for Vector {
impl Add for Vector { impl Add for Vector {
type Output = Vector; type Output = Vector;
#[inline(always)]
fn add(self, other: Vector) -> Vector { fn add(self, other: Vector) -> Vector {
Vector { co: self.co + other.co } Vector { co: self.co + other.co }
} }
@ -91,6 +104,7 @@ impl Add for Vector {
impl Sub for Vector { impl Sub for Vector {
type Output = Vector; type Output = Vector;
#[inline(always)]
fn sub(self, other: Vector) -> Vector { fn sub(self, other: Vector) -> Vector {
Vector { co: self.co - other.co } Vector { co: self.co - other.co }
} }
@ -100,6 +114,7 @@ impl Sub for Vector {
impl Mul<f32> for Vector { impl Mul<f32> for Vector {
type Output = Vector; type Output = Vector;
#[inline(always)]
fn mul(self, other: f32) -> Vector { fn mul(self, other: f32) -> Vector {
Vector { co: self.co * other } Vector { co: self.co * other }
} }
@ -109,12 +124,13 @@ impl Mul<f32> for Vector {
impl Mul<Matrix4x4> for Vector { impl Mul<Matrix4x4> for Vector {
type Output = Vector; type Output = Vector;
#[inline]
fn mul(self, other: Matrix4x4) -> Vector { fn mul(self, other: Matrix4x4) -> Vector {
Vector { Vector {
co: Float4::new((self.co * other[0]).h_sum(), co: Float4::new((self.co * other.values[0]).h_sum(),
(self.co * other[1]).h_sum(), (self.co * other.values[1]).h_sum(),
(self.co * other[2]).h_sum(), (self.co * other.values[2]).h_sum(),
(self.co * other[3]).h_sum()), (self.co * other.values[3]).h_sum()),
} }
} }
} }
@ -123,6 +139,7 @@ impl Mul<Matrix4x4> for Vector {
impl Div<f32> for Vector { impl Div<f32> for Vector {
type Output = Vector; type Output = Vector;
#[inline(always)]
fn div(self, other: f32) -> Vector { fn div(self, other: f32) -> Vector {
Vector { co: self.co / other } Vector { co: self.co / other }
} }
@ -132,20 +149,15 @@ impl Div<f32> for Vector {
impl Neg for Vector { impl Neg for Vector {
type Output = Vector; type Output = Vector;
#[inline(always)]
fn neg(self) -> Vector { fn neg(self) -> Vector {
Vector { co: self.co * -1.0 } Vector { co: self.co * -1.0 }
} }
} }
impl Lerp for Vector {
fn lerp(self, other: Vector, alpha: f32) -> Vector {
(self * (1.0 - alpha)) + (other * alpha)
}
}
impl DotProduct for Vector { impl DotProduct for Vector {
#[inline(always)]
fn dot(self, other: Vector) -> f32 { fn dot(self, other: Vector) -> f32 {
(self.co * other.co).h_sum() (self.co * other.co).h_sum()
} }
@ -153,6 +165,7 @@ impl DotProduct for Vector {
impl CrossProduct for Vector { impl CrossProduct for Vector {
#[inline]
fn cross(self, other: Vector) -> Vector { fn cross(self, other: Vector) -> Vector {
Vector { Vector {
co: Float4::new((self.co.get_1() * other.co.get_2()) - co: Float4::new((self.co.get_1() * other.co.get_2()) -
@ -171,7 +184,6 @@ impl CrossProduct for Vector {
mod tests { mod tests {
use super::*; use super::*;
use super::super::{Matrix4x4, CrossProduct, DotProduct}; use super::super::{Matrix4x4, CrossProduct, DotProduct};
use lerp::Lerp;
#[test] #[test]
fn add() { fn add() {
@ -295,31 +307,4 @@ mod tests {
assert_eq!(v3, v1.cross(v2)); assert_eq!(v3, v1.cross(v2));
} }
#[test]
fn lerp1() {
let v1 = Vector::new(1.0, 2.0, 1.0);
let v2 = Vector::new(-2.0, 1.0, -1.0);
let v3 = Vector::new(1.0, 2.0, 1.0);
assert_eq!(v3, v1.lerp(v2, 0.0));
}
#[test]
fn lerp2() {
let v1 = Vector::new(1.0, 2.0, 1.0);
let v2 = Vector::new(-2.0, 1.0, -1.0);
let v3 = Vector::new(-2.0, 1.0, -1.0);
assert_eq!(v3, v1.lerp(v2, 1.0));
}
#[test]
fn lerp3() {
let v1 = Vector::new(1.0, 2.0, 1.0);
let v2 = Vector::new(-2.0, 1.0, -1.0);
let v3 = Vector::new(-0.5, 1.5, 0.0);
assert_eq!(v3, v1.lerp(v2, 0.5));
}
} }