#![allow(dead_code)] use std::convert::{AsMut, AsRef}; use std::fmt::{Debug, Formatter, Result as FmtResult}; use std::ops::{Add, Deref, DerefMut, Div, Mul, Neg, Sub}; macro_rules! first_ptr { ($this:ident, $first:ident $(,$other:ident)*) => { unsafe { &$this.$first } }; } macro_rules! define_vec { ($Name:ident, $size:tt, $($T:ident => $i:tt => $f:ident),*) => { #[repr(C, packed)] pub struct $Name { $(pub $f: T,)+ } impl $Name { #[inline] pub fn new($($f: T,)+) -> Self { Self { $($f,)+ } } #[inline] pub fn as_ptr(&self) -> * const T { first_ptr!(self $(, $f)+) } } impl Default for $Name where T: Default { #[inline] fn default() -> Self { Self { $($f: T::default(),)+ } } } impl Debug for $Name where T: Debug { fn fmt(&self, fmt: &mut Formatter<'_>) -> FmtResult { fmt.debug_list().entries(self.as_ref().iter()).finish() } } impl PartialEq<$Name> for $Name where S: PartialEq, { fn eq(&self, other: &$Name) -> bool { unsafe { true $(&& other.$f.eq(&self.$f))+ } } } impl Eq for $Name where T: Eq { } impl Deref for $Name { type Target = [T; $size]; #[inline] fn deref(&self) -> &Self::Target { self.as_ref() } } impl DerefMut for $Name { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { self.as_mut() } } impl AsRef<[T; $size]> for $Name { #[inline] fn as_ref(&self) -> &[T; $size] { unsafe { let raw: * const _ = self; let raw = raw as * const [T; $size]; &*raw } } } impl AsMut<[T; $size]> for $Name { #[inline] fn as_mut(&mut self) -> &mut [T; $size] { unsafe { let raw: * mut _ = self; let raw = raw as * mut [T; $size]; &mut *raw } } } impl Clone for $Name where T: Clone { #[inline] fn clone(&self) -> Self { unsafe { Self { $($f: self.$f.clone(),)+ } } } } impl Copy for $Name where T: Copy { } impl From<[T; $size]> for $Name where T: Copy, { #[inline] fn from(arr: [T; $size]) -> Self { Self { $($f: arr[$i],)+ } } } impl From<($($T,)+)> for $Name { #[inline] fn from(($($f,)+): ($($T,)+)) -> Self { Self { $($f,)+ } } } }; } define_vec!(Vector2, 2, T => 0 => x, T => 1 => y); define_vec!(Vector3, 3, T => 0 => x, T => 1 => y, T => 2 => z); define_vec!(Vector4, 4, T => 0 => x, T => 1 => y, T => 2 => z, T => 3 => w); pub type Vector2f = Vector2; pub type Vector3f = Vector3; pub type Vector4f = Vector4; pub type Vector2d = Vector2; pub type Vector3d = Vector3; pub type Vector4d = Vector4; pub type Vector2i = Vector2; pub type Vector3i = Vector3; pub type Vector4i = Vector4; /* Vector2 */ impl Vector2 where T: Element, { #[inline] pub fn multiply(mut self, v: T) -> Self { self.x = self.x * v; self.y = self.y * v; self } #[inline] pub fn length(&self) -> T { Element::sqrt(self.x * self.x + self.y * self.y) } #[inline] pub fn normalize(mut self) -> Self { let len = self.length(); self.x = self.x / len; self.y = self.y / len; self } #[inline] pub fn scalar(&self, other: &Self) -> T { self.x * other.x + self.y * other.y } #[inline] pub fn angle(&self, other: &Self) -> T::AsFloat { let s = self.scalar(other); let l1 = self.length(); let l2 = self.length(); Element::acos(s / (l1 + l2)) } #[inline] pub fn angle2(&self, other: &Self) -> T::AsFloat { T::atan2( other.x * self.y - other.y * self.x, other.x * self.x + other.y * self.y, ) } } impl Add for Vector2 where T: Element, { type Output = Self; #[inline] fn add(mut self, other: Self) -> Self::Output { self.x = self.x + other.x; self.y = self.y + other.y; self } } impl Sub for Vector2 where T: Element, { type Output = Self; #[inline] fn sub(mut self, other: Self) -> Self::Output { self.x = self.x - other.x; self.y = self.y - other.y; self } } impl Mul for Vector2 where T: Element, { type Output = T; #[inline] fn mul(self, rhs: Self) -> Self::Output { self.scalar(&rhs) } } /* Vector3 */ impl Vector3 where T: Element, { #[inline] pub fn multiply(mut self, v: T) -> Self { self.x = self.x * v; self.y = self.y * v; self.z = self.z * v; self } #[inline] pub fn length(&self) -> T { Element::sqrt(self.x * self.x + self.y * self.y + self.z * self.z) } #[inline] pub fn normalize(mut self) -> Self { let len = self.length(); self.x = self.x / len; self.y = self.y / len; self.z = self.z / len; self } #[inline] pub fn scalar(&self, other: &Self) -> T { self.x * other.x + self.y * other.y + self.z * other.z } #[inline] pub fn cross(&self, other: &Self) -> Self { Self { x: self.y * other.z - self.z * other.y, y: self.z * other.x - self.x * other.z, z: self.x * other.y - self.y * other.x, } } #[inline] pub fn angle(&self, other: &Self) -> T::AsFloat { let s = self.scalar(other); let l1 = self.length(); let l2 = self.length(); Element::acos(s / (l1 + l2)) } } impl Add for Vector3 where T: Element, { type Output = Self; #[inline] fn add(mut self, other: Self) -> Self::Output { self.x = self.x + other.x; self.y = self.y + other.y; self.z = self.z + other.z; self } } impl Sub for Vector3 where T: Element, { type Output = Self; #[inline] fn sub(mut self, other: Self) -> Self::Output { self.x = self.x - other.x; self.y = self.y - other.y; self.z = self.z - other.z; self } } impl Mul for Vector3 where T: Element, { type Output = T; #[inline] fn mul(self, rhs: Self) -> Self::Output { self.scalar(&rhs) } } /* Vector4 */ impl Vector4 where T: Element, { #[inline] pub fn multiply(mut self, v: T) -> Self { self.x = self.x * v; self.y = self.y * v; self.z = self.z * v; self } #[inline] pub fn length(self) -> T { self.xyz().length() } #[inline] pub fn normalize(mut self) -> Self { let len = self.length(); if unsafe { !Element::is_zero(&self.w) } { self.x = self.x / self.w; self.y = self.y / self.w; self.z = self.z / self.w; } else { self.x = Element::zero(); self.y = Element::zero(); self.z = Element::zero(); } self.x = self.x / len; self.y = self.y / len; self.z = self.z / len; self.w = Element::one(); self } #[inline] pub fn scalar(&self, other: &Self) -> T { self.xyz().scalar(&other.xyz()) } #[inline] pub fn cross(&self, other: &Self) -> Self { (self.xyz().cross(&other.xyz()), Element::one()).into() } #[inline] pub fn angle(&self, other: &Self) -> T::AsFloat { self.xyz().angle(&other.xyz()) } #[inline] pub fn xyz(self) -> Vector3 { if unsafe { Element::is_zero(&self.w) } { Vector3 { x: Element::zero(), y: Element::zero(), z: Element::zero(), } } else { Vector3 { x: self.x / self.w, y: self.y / self.w, z: self.z / self.w, } } } } impl Add for Vector4 where T: Element, { type Output = Self; #[inline] fn add(self, other: Self) -> Self::Output { (self.xyz() + other.xyz(), T::one()).into() } } impl Sub for Vector4 where T: Element, { type Output = Self; #[inline] fn sub(self, other: Self) -> Self::Output { (self.xyz() - other.xyz(), T::one()).into() } } impl Mul for Vector4 where T: Element, { type Output = T; fn mul(self, rhs: Self) -> Self::Output { self.scalar(&rhs) } } impl From<(Vector3, T)> for Vector4 { fn from((vec3, w): (Vector3, T)) -> Self { Self { x: vec3.x, y: vec3.y, z: vec3.z, w, } } } /* Element */ pub trait Element: Sized + Neg + Add + Sub + Mul + Div + Copy { type AsFloat: Element; fn one() -> Self; fn zero() -> Self; fn sin(self) -> Self; fn cos(self) -> Self; fn sqrt(self) -> Self; fn tan(self) -> Self::AsFloat; fn acos(self) -> Self::AsFloat; fn atan(self) -> Self::AsFloat; fn atan2(a: Self, b: Self) -> Self::AsFloat; fn is_zero(&self) -> bool; fn to_degrees(self) -> Self; fn to_radians(self) -> Self; } impl Element for gl::GLfloat { type AsFloat = f32; #[inline] fn one() -> Self { 1.0 } #[inline] fn zero() -> Self { 0.0 } #[inline] fn sin(self) -> Self { f32::sin(self) } #[inline] fn cos(self) -> Self { f32::cos(self) } #[inline] fn sqrt(self) -> Self { f32::sqrt(self) } #[inline] fn tan(self) -> Self::AsFloat { f32::tan(self) } #[inline] fn acos(self) -> Self::AsFloat { f32::acos(self) } #[inline] fn atan(self) -> Self::AsFloat { f32::atan(self) } #[inline] fn atan2(a: Self, b: Self) -> Self::AsFloat { f32::atan2(a, b) } #[inline] fn is_zero(&self) -> bool { PartialEq::::eq(self, &0.0) } #[inline] fn to_degrees(self) -> Self { f32::to_degrees(self) } #[inline] fn to_radians(self) -> Self { f32::to_radians(self) } } impl Element for gl::GLdouble { type AsFloat = f64; #[inline] fn one() -> Self { 1.0 } #[inline] fn zero() -> Self { 0.0 } #[inline] fn sin(self) -> Self { f64::sin(self) } #[inline] fn cos(self) -> Self { f64::cos(self) } #[inline] fn sqrt(self) -> Self { f64::sqrt(self) } #[inline] fn tan(self) -> Self::AsFloat { f64::tan(self) } #[inline] fn acos(self) -> Self::AsFloat { f64::acos(self) } #[inline] fn atan(self) -> Self::AsFloat { f64::atan(self) } #[inline] fn atan2(a: Self, b: Self) -> Self::AsFloat { f64::atan2(a, b) } #[inline] fn is_zero(&self) -> bool { PartialEq::::eq(self, &0.0) } #[inline] fn to_degrees(self) -> Self { f64::to_degrees(self) } #[inline] fn to_radians(self) -> Self { f64::to_radians(self) } } impl Element for gl::GLint { type AsFloat = f32; #[inline] fn one() -> Self { 1 } #[inline] fn zero() -> Self { 0 } #[inline] fn sin(self) -> Self { f32::sin(self as f32) as i32 } #[inline] fn cos(self) -> Self { f32::cos(self as f32) as i32 } #[inline] fn sqrt(self) -> Self { f64::sqrt(self as f64) as i32 } #[inline] fn tan(self) -> Self::AsFloat { f32::tan(self as f32) } #[inline] fn acos(self) -> Self::AsFloat { f32::acos(self as f32) } #[inline] fn atan(self) -> Self::AsFloat { f32::atan(self as f32) } #[inline] fn atan2(a: Self, b: Self) -> Self::AsFloat { f32::atan2(a as f32, b as f32) } #[inline] fn is_zero(&self) -> bool { PartialEq::::eq(self, &0) } #[inline] fn to_degrees(self) -> Self { f32::to_degrees(self as f32) as i32 } #[inline] fn to_radians(self) -> Self { f32::to_radians(self as f32) as i32 } } #[cfg(test)] mod tests { use super::*; #[test] fn add() { let v1 = Vector2f::from((1.0, 0.0)); let v2 = Vector2f::from((0.0, 1.0)); let ex = Vector2f::from((1.0, 1.0)); assert_eq!(ex, v1 + v2); let v1 = Vector3f::from((1.0, 0.0, 1.8)); let v2 = Vector3f::from((0.0, 2.0, 1.2)); let ex = Vector3f::from((1.0, 2.0, 3.0)); assert_eq!(ex, v1 + v2); let v1 = Vector4f::from((1.0, 0.0, 1.8, 0.5)); let v2 = Vector4f::from((0.0, 2.0, 1.2, 1.0)); let ex = Vector4f::from((2.0, 2.0, 4.8, 1.0)); assert_eq!(ex, v1 + v2); } #[test] fn sub() { let v1 = Vector2f::from((1.0, 0.0)); let v2 = Vector2f::from((0.0, 1.0)); let ex = Vector2f::from((1.0, -1.0)); assert_eq!(ex, v1 - v2); let v1 = Vector3d::from((1.0, 0.0, 1.75)); let v2 = Vector3d::from((0.0, 2.0, 1.0)); let ex = Vector3d::from((1.0, -2.0, 0.75)); assert_eq!(ex, v1 - v2); let v1 = Vector4d::from((1.0, 0.0, 1.0, 0.5)); let v2 = Vector4d::from((0.0, 2.0, -2.0, 1.0)); let ex = Vector4d::from((2.0, -2.0, 4.0, 1.0)); assert_eq!(ex, v1 - v2); } #[test] fn multiply() { let v1 = Vector2f::from((1.0, 0.0)).multiply(2.0); let ex = Vector2f::from((2.0, 0.0)); assert_eq!(ex, v1); let v1 = Vector3d::from((1.0, 0.0, 1.75)).multiply(2.0); let ex = Vector3d::from((2.0, 0.0, 3.5)); assert_eq!(ex, v1); let v1 = Vector4d::from((1.0, 0.0, 0.5, 0.5)).multiply(3.0); let ex = Vector4d::from((3.0, 0.0, 1.5, 0.5)); assert_eq!(ex, v1); } #[test] fn scalar() { let v1 = Vector2f::from((1.0, 0.0)); let v2 = Vector2f::from((0.0, 1.0)); assert_eq!(0.0, v1.scalar(&v2)); let v1 = Vector3f::from((1.0, 0.0, 0.0)); let v2 = Vector3f::from((0.0, 1.0, 0.0)); assert_eq!(0.0, v1.scalar(&v2)); let v1 = Vector4f::from((3.0, 0.0, 0.0, 1.0)); let v2 = Vector4f::from((0.0, 2.0, 0.0, 0.8)); assert_eq!(0.0, v1.scalar(&v2)); } #[test] fn normalize() { let v1 = Vector2f::from((1.0, 0.0)).normalize(); let ex = Vector2f::from((1.0, 0.0)); assert_eq!(ex, v1); let v1 = Vector3d::from((1.0, 0.0, 1.75)).normalize(); let ex = Vector3d::from((0.49613893835683387, 0.0, 0.8682431421244593)); assert_eq!(ex, v1); let v1 = Vector4d::from((1.0, 0.0, 0.5, 0.5)).normalize(); let ex = Vector4d::from((0.8944271909999159, 0.0, 0.4472135954999579, 1.0)); assert_eq!(ex, v1); } #[test] fn cross() { let v1 = Vector3d::from((1.0, 0.0, 0.0)); let v2 = Vector3d::from((0.0, 1.0, 0.0)); let ex = Vector3d::from((0.0, 0.0, 1.0)); assert_eq!(ex, v1.cross(&v2)); let v1 = Vector4d::from((1.0, 0.0, 0.0, 0.5)); let v2 = Vector4d::from((0.0, 3.0, 0.0, 1.0)); let ex = Vector4d::from((0.0, 0.0, 6.0, 1.0)); assert_eq!(ex, v1.cross(&v2)); } }