2 releases
0.1.1 | Feb 19, 2021 |
---|---|
0.1.0 | Feb 19, 2021 |
0.0.0 |
|
#1731 in Math
28KB
470 lines
gfxmath-vec4
A simple 3D math library to compute 3 dimensional vectors.
Usage
Vec4
Vec4 uses the { x, y, z }
coordinate system, with the trailing w
. We can obtain the coefficients
for each axis by calling its member.
The structure of Vec4 is as follows:
pub struct Vec4<T> {
pub x: T,
pub y: T,
pub z: T,
pub w: T
}
Depending on the context, Vec4 could be used to represent different types of data.
In graphics computing, it is common to use Vec4 to represent both point space and
vectors, using the w
to distinguish the two.
For example, a w
that equals to 0.0
would be considered as a vector while a
non-zero value would be considered a point in 3D space. Other times, the w
could
be used to represent the scaling factor of the vector or point.
In the case for colors, we could use { x, y, z, w }
to represent
(red, green, blue, alpha).
The creation of a Vec4 objection can be done via multiple ways.
use gfxmath_vec4::Vec4;
// Standard construction
let v = Vec4 { x: 3.0, y: 1.0, z: 0.5, w: 4.2 };
// Using `new` function
let v = Vec4::new(3.0, 1.0, 0.5, 4.2);
// Using tuples
let v: Vec4<f32> = (3.0, 4.0, 9.0, 4.2).into();
// Using macros
use gfxmath_vec4::vec4;
let v = vec4!(3.0, 4.0, 9.0, 4.2);
assert_eq!(3.0, v.x);
assert_eq!(1.0, v.y);
assert_eq!(0.5, v.z);
assert_eq!(4.2, v.w);
Operators
Common mathematical operators are implemented for Vec3.
+
,+=
-
,-=
*
,*=
/
,/=
// Reminder: Rust automatically infers floats to `f64` and integers to `i64`.
let v1 = Vec4::new(3.0, 9.0, 2.5, 1.0);
let v2 = Vec4::new(4.0, 5.0, 3.0, 0.0);
let res = v1 + v2;
assert_eq!( 7.0, res.x);
assert_eq!(14.0, res.y);
assert_eq!( 5.5, res.z);
assert_eq!( 1.0, res.w);
Cross Product
The cross product returns a 3D vector with a zero w
value.
use gfxmath_vec4::ops::Cross;
use gfxmath_vec4::Vec4;
let a = Vec4::new(1.0, 3.0, 2.5, 9.0);
let b = Vec4::all(2.0);
let res = a.cross(b);
assert_eq!( 1.0, res.x);
assert_eq!( 3.0, res.y);
assert_eq!(-4.0, res.z);
assert_eq!( 0.0, res.w);
Dot Product
The dot product of Vec4 only computes the dot product of the (x, y, z) component of the vector.
use gfxmath_vec4::{Vec4, ops::Dot};
let a = Vec4::new(3.0, 4.0, 5.0, 3.0);
let b = Vec4::new(2.0, 1.0, 3.0, 9.0);
let res = a.dot(b);
assert_eq!(25.0, res);
Normalize
We can use norm
from gfxmath_vec4::ops::Norm
to normalize the vector.
This may be subject to change in the future due to norm
being a word used
to represent the length of the vector. Norm
was selected for compactness so it
may be confusing for some people.
use gfxmath_vec4::ops::Norm;
use gfxmath_vec4::Vec4;
let a = Vec4::<f32>::new(3.0, 4.0, 0.0, 0.0);
let an = a.norm().unwrap();
assert_eq!(3.0/5.0, an.x);
assert_eq!(4.0/5.0, an.y);
assert_eq!(0.0, an.z);
assert_eq!(0.0, an.w); // this should always be zero so that this object is represented as a vector
Known Limitations
Left-Hand Primitives
One caveat is that operators where the Left-Hand side is a primitive has limited support. This is due to restrictions for trait implementations. impl <T> Add<Vec3<T>> for T
is illegal within Rust syntax (due to the trailing T
) because the implementation must be for a known type for non-local traits and types. Since Add
is from the core
package and T
(the type to be implemented for) is not derived from a local trait, this is not possible.
At the time of this writing, primitives that work on the Left-Hand Side for common operators are f32
, f64
, i32
, and i64
.
// Works
let lhs: f32 = 4.0;
let rhs = Vec4::<f32>::new(3.0, 4.0, 2.5, 3.0);
let res = lhs + rhs;
// NOT SUPPORTED!!
let lhs: u32 = 4;
let rhs = Vec4::<u32>::new(3, 4, 2, 3);
let res = lhs + rhs;
Hash Implementation
Currently, Hash implementations are limited for the following types:
f32
f64
i32
i64
u32
u64
Dependencies
~1.5MB
~35K SLoC