nova-math 0.5.0

Vector and matrix math utilities for nova-engine
Documentation
/*
 *
 * This file is a part of NovaEngine
 * https://gitlab.com/MindSpunk/NovaEngine
 *
 *
 * MIT License
 *
 * Copyright (c) 2018 Nathan Voglsam
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

use crate::traits::{IntoSTD140, Pack, Real};
use crate::vector::{TVec2, TVec3, TVec4};

///
/// A wrapper struct that is used to implement std140 packing for the underlying vector
///
#[repr(transparent)]
#[derive(Copy, Clone, Debug)]
pub struct TVec2P<T: Real>([T; 2]);

///
/// Const fn for constructing a TVec2 in a const context
///
pub const fn vector_2_packed_f32(x: f32, y: f32) -> TVec2P<f32> {
    TVec2P::<f32> { 0: [x, y] }
}

///
/// Const fn for constructing a TVec2 in a const context
///
pub const fn vector_2_packed_f64(x: f64, y: f64) -> TVec2P<f64> {
    TVec2P::<f64> { 0: [x, y] }
}

impl<T: Real> TVec2P<T> {
    pub fn new(x: T, y: T) -> Self {
        Self([x, y])
    }
}

impl<T: Real> From<TVec2<T>> for TVec2P<T> {
    fn from(other: TVec2<T>) -> Self {
        Self([other[0], other[1]])
    }
}

impl<T: Real> From<[T; 2]> for TVec2P<T> {
    fn from(other: [T; 2]) -> Self {
        Self(other)
    }
}

impl<T: Real> From<(T, T)> for TVec2P<T> {
    fn from(other: (T, T)) -> Self {
        Self([other.0, other.1])
    }
}

impl<T: Real> Pack for TVec2P<T> {
    type GLSLOutput = [T; 2];
    type HLSLOutput = [T; 2];
    type GLSLOutputArray = Self::GLSLOutput;
    type HLSLOutputArray = Self::HLSLOutput;
    type CPUOutput = [T; 2];

    #[inline]
    fn into_packed_glsl(self) -> Self::GLSLOutput {
        self.0
    }

    #[inline]
    fn into_packed_hlsl(self) -> Self::HLSLOutput {
        self.0
    }

    #[inline]
    fn into_packed_glsl_array(self) -> Self::GLSLOutputArray {
        self.0
    }

    #[inline]
    fn into_packed_hlsl_array(self) -> Self::HLSLOutputArray {
        self.0
    }

    #[inline]
    fn into_packed_cpu(self) -> Self::CPUOutput {
        self.0
    }
}

///
/// A wrapper struct that is used to implement std140 packing for the underlying vector
///
#[repr(transparent)]
#[derive(Copy, Clone, Debug)]
pub struct TVec3P<T: Real>([T; 3]);

///
/// Const fn for constructing a TVec3P in a const context
///
pub const fn vector_3_packed_f32(x: f32, y: f32, z: f32) -> TVec3P<f32> {
    TVec3P::<f32> { 0: [x, y, z] }
}

///
/// Const fn for constructing a TVec3P in a const context
///
pub const fn vector_3_packed_f64(x: f64, y: f64, z: f64) -> TVec3P<f64> {
    TVec3P::<f64> { 0: [x, y, z] }
}

impl<T: Real> TVec3P<T> {
    pub fn new(x: T, y: T, z: T) -> Self {
        Self([x, y, z])
    }
}

impl<T: Real> From<TVec3<T>> for TVec3P<T> {
    fn from(other: TVec3<T>) -> Self {
        Self([other[0], other[1], other[2]])
    }
}

impl<T: Real> From<[T; 3]> for TVec3P<T> {
    fn from(other: [T; 3]) -> Self {
        Self(other)
    }
}

impl<T: Real> From<(T, T, T)> for TVec3P<T> {
    fn from(other: (T, T, T)) -> Self {
        Self([other.0, other.1, other.2])
    }
}

impl<T: Real> Pack for TVec3P<T> {
    type GLSLOutput = [T; 4];
    type HLSLOutput = [T; 4];
    type GLSLOutputArray = Self::GLSLOutput;
    type HLSLOutputArray = Self::HLSLOutput;
    type CPUOutput = [T; 3];

    #[inline]
    fn into_packed_glsl(self) -> Self::GLSLOutput {
        [self.0[0], self.0[1], self.0[2], T::zero()]
    }

    #[inline]
    fn into_packed_hlsl(self) -> Self::HLSLOutput {
        [self.0[0], self.0[1], self.0[2], T::zero()]
    }

    #[inline]
    fn into_packed_glsl_array(self) -> Self::GLSLOutputArray {
        self.into_packed_glsl()
    }

    #[inline]
    fn into_packed_hlsl_array(self) -> Self::HLSLOutputArray {
        self.into_packed_hlsl()
    }

    #[inline]
    fn into_packed_cpu(self) -> Self::CPUOutput {
        [self.0[0], self.0[1], self.0[2]]
    }
}

///
/// A wrapper struct that is used to implement std140 packing for the underlying vector
///
#[repr(transparent)]
#[derive(Copy, Clone, Debug)]
pub struct TVec4P<T: Real>([T; 4]);

///
/// Const fn for constructing a TVec4P in a const context
///
pub const fn vector_4_packed_f32(x: f32, y: f32, z: f32, w: f32) -> TVec4P<f32> {
    TVec4P::<f32> { 0: [x, y, z, w] }
}

///
/// Const fn for constructing a TVec4P in a const context
///
pub const fn vector_4_packed_f64(x: f64, y: f64, z: f64, w: f64) -> TVec4P<f64> {
    TVec4P::<f64> { 0: [x, y, z, w] }
}

impl<T: Real> TVec4P<T> {
    pub fn new(x: T, y: T, z: T, w: T) -> Self {
        Self([x, y, z, w])
    }
}

impl<T: Real> From<TVec4<T>> for TVec4P<T> {
    fn from(other: TVec4<T>) -> Self {
        Self([other[0], other[1], other[2], other[3]])
    }
}

impl<T: Real> From<[T; 4]> for TVec4P<T> {
    fn from(other: [T; 4]) -> Self {
        Self(other)
    }
}

impl<T: Real> From<(T, T, T, T)> for TVec4P<T> {
    fn from(other: (T, T, T, T)) -> Self {
        Self([other.0, other.1, other.2, other.3])
    }
}

impl<T: Real> Pack for TVec4P<T> {
    type GLSLOutput = [T; 4];
    type HLSLOutput = [T; 4];
    type GLSLOutputArray = Self::GLSLOutput;
    type HLSLOutputArray = Self::HLSLOutput;
    type CPUOutput = [T; 4];

    #[inline]
    fn into_packed_glsl(self) -> Self::GLSLOutput {
        self.0
    }

    #[inline]
    fn into_packed_hlsl(self) -> Self::HLSLOutput {
        self.0
    }

    #[inline]
    fn into_packed_glsl_array(self) -> Self::GLSLOutputArray {
        self.into_packed_glsl()
    }

    #[inline]
    fn into_packed_hlsl_array(self) -> Self::HLSLOutputArray {
        self.into_packed_hlsl()
    }

    #[inline]
    fn into_packed_cpu(self) -> Self::CPUOutput {
        self.0
    }
}

impl<T: Real> IntoSTD140 for TVec2<T> {
    type Output = TVec2P<T>;

    fn into_std140(self) -> Self::Output {
        TVec2P::from(self)
    }
}

impl<T: Real> IntoSTD140 for TVec3<T> {
    type Output = TVec3P<T>;

    fn into_std140(self) -> Self::Output {
        TVec3P::from(self)
    }
}

impl<T: Real> IntoSTD140 for TVec4<T> {
    type Output = TVec4P<T>;

    fn into_std140(self) -> Self::Output {
        TVec4P::from(self)
    }
}