#vec4 #vector-math #3d #graphics

gfxmath-vec4

A simple 3D math library

2 releases

0.1.1 Feb 19, 2021
0.1.0 Feb 19, 2021
0.0.0 Feb 14, 2021

#1984 in Math

Custom license

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
~37K SLoC