Browse Source

Implemented vector types

raster
Bergmann89 4 years ago
parent
commit
4795cbd14f
2 changed files with 721 additions and 0 deletions
  1. +1
    -0
      glc/src/lib.rs
  2. +720
    -0
      glc/src/vector.rs

+ 1
- 0
glc/src/lib.rs View File

@@ -2,4 +2,5 @@ pub mod array_buffer;
pub mod error;
pub mod misc;
pub mod shader;
pub mod vector;
pub mod vertex_array;

+ 720
- 0
glc/src/vector.rs View File

@@ -0,0 +1,720 @@
#![allow(dead_code)]

use std::convert::{AsMut, AsRef};
use std::fmt::{Debug, Formatter, Result as FmtResult};
use std::ops::{Add, Deref, DerefMut, Div, Mul, Sub};

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,)+ }
}
}

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);

type Vector2f = Vector2<gl::GLfloat>;
type Vector3f = Vector3<gl::GLfloat>;
type Vector4f = Vector4<gl::GLfloat>;

type Vector2d = Vector2<gl::GLdouble>;
type Vector3d = Vector3<gl::GLdouble>;
type Vector4d = Vector4<gl::GLdouble>;

type Vector2i = Vector2<gl::GLint>;
type Vector3i = Vector3<gl::GLint>;
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
+ 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 sqrt(self) -> Self;
fn acos(self) -> Self::AsFloat;
fn atan(self) -> Self::AsFloat;
fn atan2(a: Self, b: Self) -> Self::AsFloat;
fn is_zero(&self) -> bool;
}

impl Element for gl::GLfloat {
type AsFloat = f32;

#[inline]
fn one() -> Self {
1.0
}

#[inline]
fn zero() -> Self {
0.0
}

#[inline]
fn sqrt(self) -> Self {
f32::sqrt(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)
}
}

impl Element for gl::GLdouble {
type AsFloat = f64;

#[inline]
fn one() -> Self {
1.0
}

#[inline]
fn zero() -> Self {
0.0
}

#[inline]
fn sqrt(self) -> Self {
f64::sqrt(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)
}
}

impl Element for gl::GLint {
type AsFloat = f32;

#[inline]
fn one() -> Self {
1
}

#[inline]
fn zero() -> Self {
0
}

#[inline]
fn sqrt(self) -> Self {
f64::sqrt(self as f64) as i32
}

#[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)
}
}

#[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));
}
}

Loading…
Cancel
Save