|
- #![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<T> {
- $(pub $f: T,)+
- }
-
- impl<T> $Name<T> {
- #[inline]
- pub fn new($($f: T,)+) -> Self {
- Self { $($f,)+ }
- }
-
- #[inline]
- pub fn as_ptr(&self) -> * const T {
- first_ptr!(self $(, $f)+)
- }
- }
-
- impl<T> Default for $Name<T>
- where
- T: Default
- {
- #[inline]
- fn default() -> Self {
- Self {
- $($f: T::default(),)+
- }
- }
- }
-
- impl<T> Debug for $Name<T>
- where
- T: Debug
- {
- fn fmt(&self, fmt: &mut Formatter<'_>) -> FmtResult {
- fmt.debug_list().entries(self.as_ref().iter()).finish()
- }
- }
-
- impl<T, S> PartialEq<$Name<S>> for $Name<T>
- where
- S: PartialEq<T>,
- {
- fn eq(&self, other: &$Name<S>) -> bool {
- unsafe { true $(&& other.$f.eq(&self.$f))+ }
- }
- }
-
- impl<T> Eq for $Name<T>
- where
- T: Eq
- { }
-
- impl<T> Deref for $Name<T> {
- type Target = [T; $size];
-
- #[inline]
- fn deref(&self) -> &Self::Target {
- self.as_ref()
- }
- }
-
- impl<T> DerefMut for $Name<T> {
- #[inline]
- fn deref_mut(&mut self) -> &mut Self::Target {
- self.as_mut()
- }
- }
-
- impl<T> AsRef<[T; $size]> for $Name<T> {
- #[inline]
- fn as_ref(&self) -> &[T; $size] {
- unsafe {
- let raw: * const _ = self;
- let raw = raw as * const [T; $size];
-
- &*raw
- }
- }
- }
-
- impl<T> AsMut<[T; $size]> for $Name<T> {
- #[inline]
- fn as_mut(&mut self) -> &mut [T; $size] {
- unsafe {
- let raw: * mut _ = self;
- let raw = raw as * mut [T; $size];
-
- &mut *raw
- }
- }
- }
-
- impl<T> Clone for $Name<T>
- where
- T: Clone
- {
- #[inline]
- fn clone(&self) -> Self {
- unsafe {
- Self {
- $($f: self.$f.clone(),)+
- }
- }
- }
- }
-
- impl<T> Copy for $Name<T>
- where
- T: Copy
- { }
-
- impl<T> From<[T; $size]> for $Name<T>
- where
- T: Copy,
- {
- #[inline]
- fn from(arr: [T; $size]) -> Self {
- Self {
- $($f: arr[$i],)+
- }
- }
- }
-
- impl<T> From<($($T,)+)> for $Name<T> {
- #[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<gl::GLfloat>;
- pub type Vector3f = Vector3<gl::GLfloat>;
- pub type Vector4f = Vector4<gl::GLfloat>;
-
- pub type Vector2d = Vector2<gl::GLdouble>;
- pub type Vector3d = Vector3<gl::GLdouble>;
- pub type Vector4d = Vector4<gl::GLdouble>;
-
- pub type Vector2i = Vector2<gl::GLint>;
- pub type Vector3i = Vector3<gl::GLint>;
- pub type Vector4i = Vector4<gl::GLint>;
-
- /* Vector2 */
-
- impl<T> Vector2<T>
- 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<T> Add for Vector2<T>
- 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<T> Sub for Vector2<T>
- 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<T> Mul for Vector2<T>
- where
- T: Element,
- {
- type Output = T;
-
- #[inline]
- fn mul(self, rhs: Self) -> Self::Output {
- self.scalar(&rhs)
- }
- }
-
- /* Vector3 */
-
- impl<T> Vector3<T>
- 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<T> Add for Vector3<T>
- 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<T> Sub for Vector3<T>
- 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<T> Mul for Vector3<T>
- where
- T: Element,
- {
- type Output = T;
-
- #[inline]
- fn mul(self, rhs: Self) -> Self::Output {
- self.scalar(&rhs)
- }
- }
-
- /* Vector4 */
-
- impl<T> Vector4<T>
- 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<T> {
- 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<T> Add for Vector4<T>
- where
- T: Element,
- {
- type Output = Self;
-
- #[inline]
- fn add(self, other: Self) -> Self::Output {
- (self.xyz() + other.xyz(), T::one()).into()
- }
- }
-
- impl<T> Sub for Vector4<T>
- where
- T: Element,
- {
- type Output = Self;
-
- #[inline]
- fn sub(self, other: Self) -> Self::Output {
- (self.xyz() - other.xyz(), T::one()).into()
- }
- }
-
- impl<T> Mul for Vector4<T>
- where
- T: Element,
- {
- type Output = T;
-
- fn mul(self, rhs: Self) -> Self::Output {
- self.scalar(&rhs)
- }
- }
-
- impl<T> From<(Vector3<T>, T)> for Vector4<T> {
- fn from((vec3, w): (Vector3<T>, T)) -> Self {
- Self {
- x: vec3.x,
- y: vec3.y,
- z: vec3.z,
- w,
- }
- }
- }
-
- /* Element */
-
- pub trait Element:
- Sized
- + Neg<Output = Self>
- + Add<Self, Output = Self>
- + Sub<Self, Output = Self>
- + Mul<Self, Output = Self>
- + Div<Self, Output = Self>
- + 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::<f32>::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::<f64>::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::<i32>::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));
- }
- }
|