use crate::common;
use crate::vector3::Vector3;
use std::cmp;
use std::convert::From;
use std::f32::EPSILON;
use std::fmt;
use std::fmt::{Display, Formatter};
use std::ops::{
Index,
IndexMut,
Neg,
Add,
AddAssign,
Sub,
SubAssign,
Mul,
MulAssign,
Div,
DivAssign,
};
#[repr(C, packed)]
#[derive(Copy, Clone, Debug)]
pub struct Vector4 {
pub x: f32,
pub y: f32,
pub z: f32,
pub w: f32,
}
impl Vector4 {
#[inline]
pub fn new() -> Vector4 {
Vector4 {
x: 0.0,
y: 0.0,
z: 0.0,
w: 0.0,
}
}
#[inline]
pub fn one() -> Vector4 {
Vector4 {
x: 1.0,
y: 1.0,
z: 1.0,
w: 1.0,
}
}
#[inline]
pub fn make(x: f32, y: f32, z: f32, w: f32) -> Vector4 {
Vector4 { x, y, z, w }
}
#[inline]
pub fn dot(a: &Vector4, b: &Vector4) -> f32 {
a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w
}
#[inline]
pub fn min(a: &Vector4, b: &Vector4) -> Vector4 {
Vector4::make(a.x.min(b.x), a.y.min(b.y), a.z.min(b.z), a.w.min(b.w))
}
#[inline]
pub fn max(a: &Vector4, b: &Vector4) -> Vector4 {
Vector4::make(a.x.max(b.x), a.y.max(b.y), a.z.max(b.z), a.w.max(b.w))
}
#[inline]
pub fn clamp(&mut self, a: &Vector4, b: &Vector4) {
let low = Self::min(a, b);
let high = Self::max(a, b);
let result = Self::max(&low, &Self::min(self, &high));
self.set(result.x, result.y, result.z, result.w);
}
#[inline]
pub fn set(&mut self, x: f32, y: f32, z: f32, w: f32) {
self.x = x;
self.y = y;
self.z = z;
self.w = w;
}
#[inline]
pub fn mag(&self) -> f32 {
self.mag_sq().sqrt()
}
#[inline]
pub fn mag_sq(&self) -> f32 {
self.x * self.x + self.y * self.y + self.z * self.z + self.w * self.w
}
#[inline]
pub fn norm(&mut self) -> f32 {
let length = self.mag();
if length > EPSILON {
self.x /= length;
self.y /= length;
self.z /= length;
self.w /= length;
length
} else {
0.0
}
}
#[inline]
pub fn abs(&mut self) {
self.x = self.x.abs();
self.y = self.y.abs();
self.z = self.z.abs();
self.w = self.w.abs();
}
#[inline]
pub fn is_valid(&self) -> bool {
for i in 0..4 {
if !common::is_valid(self[i]) {
return false;
}
}
true
}
}
impl From<Vector3> for Vector4 {
#[inline]
fn from(item: Vector3) -> Vector4 {
Vector4 {
x: item.x,
y: item.y,
z: item.z,
w: 0.0,
}
}
}
impl Index<u32> for Vector4 {
type Output = f32;
#[inline]
fn index(&self, index: u32) -> &f32 {
unsafe {
match index {
0 => &self.x,
1 => &self.y,
2 => &self.z,
3 => &self.w,
_ => panic!("Invalid index for Vector4: {}", index),
}
}
}
}
impl IndexMut<u32> for Vector4 {
#[inline]
fn index_mut<'a>(&'a mut self, index: u32) -> &'a mut f32 {
unsafe {
match index {
0 => &mut self.x,
1 => &mut self.y,
2 => &mut self.z,
3 => &mut self.w,
_ => panic!("Invalid index for Vector4: {}", index),
}
}
}
}
impl Neg for Vector4 {
type Output = Vector4;
#[inline]
fn neg(self) -> Vector4 {
Vector4::make(-self.x, -self.y, -self.z, -self.w)
}
}
impl Add<f32> for Vector4 {
type Output = Vector4;
#[inline]
fn add(self, _rhs: f32) -> Vector4 {
Vector4::make(self.x + _rhs, self.y + _rhs, self.z + _rhs, self.w + _rhs)
}
}
impl Add<Vector4> for Vector4 {
type Output = Vector4;
#[inline]
fn add(self, _rhs: Vector4) -> Vector4 {
Vector4::make(
self.x + _rhs.x,
self.y + _rhs.y,
self.z + _rhs.z,
self.w + _rhs.w,
)
}
}
impl AddAssign<f32> for Vector4 {
#[inline]
fn add_assign(&mut self, _rhs: f32) {
self.x += _rhs;
self.y += _rhs;
self.z += _rhs;
self.w += _rhs;
}
}
impl AddAssign<Vector4> for Vector4 {
#[inline]
fn add_assign(&mut self, _rhs: Vector4) {
self.x += _rhs.x;
self.y += _rhs.y;
self.z += _rhs.z;
self.w += _rhs.w;
}
}
impl Sub<f32> for Vector4 {
type Output = Vector4;
#[inline]
fn sub(self, _rhs: f32) -> Vector4 {
Vector4::make(self.x - _rhs, self.y - _rhs, self.z - _rhs, self.w - _rhs)
}
}
impl Sub<Vector4> for Vector4 {
type Output = Vector4;
#[inline]
fn sub(self, _rhs: Vector4) -> Vector4 {
Vector4::make(
self.x - _rhs.x,
self.y - _rhs.y,
self.z - _rhs.z,
self.w - _rhs.w,
)
}
}
impl SubAssign<f32> for Vector4 {
#[inline]
fn sub_assign(&mut self, _rhs: f32) {
self.x -= _rhs;
self.y -= _rhs;
self.z -= _rhs;
self.w -= _rhs;
}
}
impl SubAssign<Vector4> for Vector4 {
#[inline]
fn sub_assign(&mut self, _rhs: Vector4) {
self.x -= _rhs.x;
self.y -= _rhs.y;
self.z -= _rhs.z;
self.w -= _rhs.w;
}
}
impl Mul<f32> for Vector4 {
type Output = Vector4;
#[inline]
fn mul(self, _rhs: f32) -> Vector4 {
Vector4::make(self.x * _rhs, self.y * _rhs, self.z * _rhs, self.w * _rhs)
}
}
impl Mul<Vector4> for Vector4 {
type Output = Vector4;
#[inline]
fn mul(self, _rhs: Vector4) -> Vector4 {
Vector4::make(
self.x * _rhs.x,
self.y * _rhs.y,
self.z * _rhs.z,
self.w * _rhs.w,
)
}
}
impl MulAssign<f32> for Vector4 {
#[inline]
fn mul_assign(&mut self, _rhs: f32) {
self.x *= _rhs;
self.y *= _rhs;
self.z *= _rhs;
self.w *= _rhs;
}
}
impl MulAssign<Vector4> for Vector4 {
#[inline]
fn mul_assign(&mut self, _rhs: Vector4) {
self.x *= _rhs.x;
self.y *= _rhs.y;
self.z *= _rhs.z;
self.w *= _rhs.w;
}
}
impl Div<f32> for Vector4 {
type Output = Vector4;
#[inline]
fn div(self, _rhs: f32) -> Vector4 {
Vector4::make(self.x / _rhs, self.y / _rhs, self.z / _rhs, self.w / _rhs)
}
}
impl Div<Vector4> for Vector4 {
type Output = Vector4;
#[inline]
fn div(self, _rhs: Vector4) -> Vector4 {
Vector4::make(
self.x / _rhs.x,
self.y / _rhs.y,
self.z / _rhs.z,
self.w / _rhs.w,
)
}
}
impl DivAssign<f32> for Vector4 {
#[inline]
fn div_assign(&mut self, _rhs: f32) {
self.x /= _rhs;
self.y /= _rhs;
self.z /= _rhs;
self.w /= _rhs;
}
}
impl DivAssign<Vector4> for Vector4 {
#[inline]
fn div_assign(&mut self, _rhs: Vector4) {
self.x /= _rhs.x;
self.y /= _rhs.y;
self.z /= _rhs.z;
self.w /= _rhs.w;
}
}
impl cmp::PartialEq for Vector4 {
#[inline]
fn eq(&self, _rhs: &Vector4) -> bool {
for i in 0..4 {
if self[i] != _rhs[i] {
return false;
}
}
true
}
}
impl Display for Vector4 {
#[inline]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
unsafe { write!(f, "<{} {} {} {}>", self.x, self.y, self.z, self.w) }
}
}