// 4D vector: homogeneous / clip-space coordinates.
///|
#valtype
pub(all) struct Vec4 {
x : Double
y : Double
z : Double
w : Double
} derive(Eq, Debug)
///|
pub fn Vec4::new(x : Double, y : Double, z : Double, w : Double) -> Vec4 {
{ x, y, z, w, }
}
///|
pub fn Vec4::zero() -> Vec4 {
{ x: 0.0, y: 0.0, z: 0.0, w: 0.0, }
}
///|
pub impl Add for Vec4 with fn add(a, b) {
{ x: a.x + b.x, y: a.y + b.y, z: a.z + b.z, w: a.w + b.w, }
}
///|
pub impl Sub for Vec4 with fn sub(a, b) {
{ x: a.x - b.x, y: a.y - b.y, z: a.z - b.z, w: a.w - b.w, }
}
///|
pub impl Neg for Vec4 with fn neg(a) {
{ x: -a.x, y: -a.y, z: -a.z, w: -a.w, }
}
///|
pub fn Vec4::scale(self : Vec4, s : Double) -> Vec4 {
{ x: self.x * s, y: self.y * s, z: self.z * s, w: self.w * s, }
}
///|
pub fn Vec4::dot(self : Vec4, o : Vec4) -> Double {
self.x * o.x + self.y * o.y + self.z * o.z + self.w * o.w
}
///|
pub fn Vec4::xyz(self : Vec4) -> Vec3 {
{ x: self.x, y: self.y, z: self.z, }
}
///|
pub fn Vec4::lerp(self : Vec4, o : Vec4, t : Double) -> Vec4 {
{
x: self.x + (o.x - self.x) * t,
y: self.y + (o.y - self.y) * t,
z: self.z + (o.z - self.z) * t,
w: self.w + (o.w - self.w) * t,
}
}
///|
/// Perspective divide: (x/w, y/w, z/w). `None` when w == 0 / non-finite result.
pub fn Vec4::perspective_divide(self : Vec4) -> Vec3? {
if self.w == 0.0 {
return None
}
let iw = 1.0 / self.w
Some({ x: self.x * iw, y: self.y * iw, z: self.z * iw, })
}
///|
pub fn Vec4::get(self : Vec4, i : Int) -> Double {
match i {
0 => self.x
1 => self.y
2 => self.z
3 => self.w
_ => abort("Vec4::get: index out of range")
}
}
///|
pub fn Vec4::approx_eq(self : Vec4, o : Vec4, eps : Double) -> Bool {
approx(self.x, o.x, eps) &&
approx(self.y, o.y, eps) &&
approx(self.z, o.z, eps) &&
approx(self.w, o.w, eps)
}