@ -0,0 +1,31 @@ | |||
/* | |||
* Copyright (C) 2020 Christopher J. Howard | |||
* | |||
* This file is part of Antkeeper source code. | |||
* | |||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* Antkeeper source code is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef ANTKEEPER_PROJECTION_HPP | |||
#define ANTKEEPER_PROJECTION_HPP | |||
#include "math/math.hpp" | |||
template <class T> | |||
math::vector<T, 3> project_on_plane(const math::vector<T, 3>& v, const math::vector<T, 3>& p, const math::vector<T, 3>& n) | |||
{ | |||
return v - n * math::dot(v - p, n); | |||
} | |||
#endif // ANTKEEPER_PROJECTION_HPP |
@ -1,75 +0,0 @@ | |||
/* | |||
* Copyright (C) 2020 Christopher J. Howard | |||
* | |||
* This file is part of Antkeeper source code. | |||
* | |||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* Antkeeper source code is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef ANTKEEPER_MATH_HPP | |||
#define ANTKEEPER_MATH_HPP | |||
#include <cstdlib> | |||
#include <type_traits> | |||
#include <vmq/vmq.hpp> | |||
using namespace vmq::operators; | |||
inline float frand(float start, float end) | |||
{ | |||
float f = (float)std::rand() / RAND_MAX; | |||
return start + f * (end - start); | |||
} | |||
namespace math { | |||
/** | |||
* Reinterprets data as an `N`-dimensional vector of type `T`. | |||
* | |||
* @tparam N Number of vector dimensions. | |||
* @tparam T Scalar type. | |||
* @param data Data to reinterpret. | |||
*/ | |||
template <std::size_t N, typename T> | |||
inline vmq::vector<T, N>& as_vector(T& data) | |||
{ | |||
static_assert(std::is_pod<vmq::vector<T, N>>::value); | |||
return reinterpret_cast<vmq::vector<T, N>&>(data); | |||
} | |||
/** | |||
* Reinterprets data as an `NxM` matrix of type `T`. | |||
* | |||
* @tparam N Number of columns. | |||
* @tparam M Number of rows. | |||
* @tparam T Element type. | |||
* @param data Data to reinterpret. | |||
*/ | |||
template <std::size_t N, std::size_t M, typename T> | |||
inline vmq::matrix<T, N, M>& as_matrix(T& data) | |||
{ | |||
static_assert(std::is_pod<vmq::matrix<T, N, M>>::value); | |||
return reinterpret_cast<vmq::matrix<T, N, M>&>(data); | |||
} | |||
template <class T> | |||
vmq::vector<T, 3> project_on_plane(const vmq::vector<T, 3>& v, const vmq::vector<T, 3>& p, const vmq::vector<T, 3>& n) | |||
{ | |||
return v - n * vmq::dot(v - p, n); | |||
} | |||
} // namespace math | |||
#endif // ANTKEEPER_MATH_HPP | |||
@ -0,0 +1,64 @@ | |||
/* | |||
* Copyright (C) 2020 Christopher J. Howard | |||
* | |||
* This file is part of Antkeeper source code. | |||
* | |||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* Antkeeper source code is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef ANTKEEPER_MATH_ANGLES_HPP | |||
#define ANTKEEPER_MATH_ANGLES_HPP | |||
#include "math/constants.hpp" | |||
namespace math { | |||
/// @addtogroup utility | |||
/// @{ | |||
/** | |||
* Converts an angle given in radians to degrees. | |||
* | |||
* @param radians Angle in radians. | |||
* @return Angle in degrees. | |||
*/ | |||
template <class T> | |||
T degrees(T radians); | |||
/** | |||
* Converts an angle given in degrees to radians. | |||
* | |||
* @param radians Angle in radians. | |||
* @return Angle in degrees. | |||
*/ | |||
template <class T> | |||
T radians(T degrees); | |||
template <class T> | |||
inline T degrees(T radians) | |||
{ | |||
return radians * T(180) / pi<T>; | |||
} | |||
template <class T> | |||
inline T radians(T degrees) | |||
{ | |||
return degrees * pi<T> / T(180); | |||
} | |||
/// @} | |||
} // namespace math | |||
#endif // ANTKEEPER_MATH_ANGLES_HPP |
@ -0,0 +1,104 @@ | |||
/* | |||
* Copyright (C) 2020 Christopher J. Howard | |||
* | |||
* This file is part of Antkeeper source code. | |||
* | |||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* Antkeeper source code is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef ANTKEEPER_MATH_CONSTANTS_HPP | |||
#define ANTKEEPER_MATH_CONSTANTS_HPP | |||
#include "math/matrix-type.hpp" | |||
#include "math/quaternion-type.hpp" | |||
#include "math/transform-type.hpp" | |||
namespace math { | |||
/// @addtogroup utility | |||
/// @{ | |||
/** | |||
* Pi. | |||
*/ | |||
template <class T> | |||
constexpr T pi = T(3.14159265358979323846); | |||
/** | |||
* Pi / 2. | |||
*/ | |||
template <class T> | |||
constexpr T half_pi = pi<T> * T(0.5); | |||
/** | |||
* Pi * 2. | |||
*/ | |||
template <class T> | |||
constexpr T two_pi = pi<T> * T(2); | |||
/** | |||
* 2x2 identity matrix. | |||
*/ | |||
template <class T> | |||
constexpr matrix<T, 2, 2> identity2x2 = | |||
{{ | |||
{1, 0}, | |||
{0, 1} | |||
}}; | |||
/** | |||
* 3x3 identity matrix. | |||
*/ | |||
template <class T> | |||
constexpr matrix<T, 3, 3> identity3x3 = | |||
{{ | |||
{1, 0, 0}, | |||
{0, 1, 0}, | |||
{0, 0, 1} | |||
}}; | |||
/** | |||
* 4x4 identity matrix. | |||
*/ | |||
template <class T> | |||
constexpr matrix<T, 4, 4> identity4x4 = | |||
{{ | |||
{1, 0, 0, 0}, | |||
{0, 1, 0, 0}, | |||
{0, 0, 1, 0}, | |||
{0, 0, 0, 1} | |||
}}; | |||
/** | |||
* Unit quaternion. | |||
*/ | |||
template <class T> | |||
constexpr quaternion<T> identity_quaternion = {T(1), T(0), T(0), T(0)}; | |||
/** | |||
* Identity transform. | |||
*/ | |||
template <class T> | |||
constexpr transform<T> identity_transform = | |||
{ | |||
{T(0), T(0), T(0)}, | |||
{T(1), T(0), T(0), T(0)}, | |||
{T(1), T(1), T(1)} | |||
}; | |||
/// @} | |||
} // namespace math | |||
#endif // ANTKEEPER_MATH_CONSTANTS_HPP |
@ -0,0 +1,77 @@ | |||
/* | |||
* Copyright (C) 2020 Christopher J. Howard | |||
* | |||
* This file is part of Antkeeper source code. | |||
* | |||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* Antkeeper source code is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef ANTKEEPER_MATH_INTERPOLATION_HPP | |||
#define ANTKEEPER_MATH_INTERPOLATION_HPP | |||
#include "math/matrix-type.hpp" | |||
#include "math/quaternion-type.hpp" | |||
#include "math/transform-type.hpp" | |||
#include <cmath> | |||
#include <type_traits> | |||
namespace math { | |||
/// @addtogroup utility | |||
/// @{ | |||
/** | |||
* Linearly interpolates between @p x and @p y. | |||
* | |||
* Requires the following operators to be defined: | |||
* | |||
* T operator+(const T&, const T&); | |||
* T operator-(const T&, const T&); | |||
* T operator*(const T&, S); | |||
* | |||
* @tparam T Value type. | |||
* @tparam S Scalar type. | |||
*/ | |||
template <typename T, typename S = float> | |||
T lerp(const T& x, const T& y, S a); | |||
/** | |||
* Logarithmically interpolates between @p x and @p y. | |||
* | |||
* @warning Undefined behavior when @p x is zero. | |||
* | |||
* @tparam T Value type. | |||
* @tparam S Scalar type. | |||
*/ | |||
template <typename T, typename S = float> | |||
T log_lerp(const T& x, const T& y, S a); | |||
template <typename T, typename S> | |||
inline T lerp(const T& x, const T& y, S a) | |||
{ | |||
return (y - x) * a + x; | |||
} | |||
template <typename T, typename S> | |||
inline T log_lerp(const T& x, const T& y, S a) | |||
{ | |||
//return std::exp(linear(std::log(x), std::log(y), a)); | |||
return x * std::pow(y / x, a); | |||
} | |||
/// @} | |||
} // namespace math | |||
#endif // ANTKEEPER_MATH_INTERPOLATION_HPP |
@ -0,0 +1,79 @@ | |||
/* | |||
* Copyright (C) 2020 Christopher J. Howard | |||
* | |||
* This file is part of Antkeeper source code. | |||
* | |||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* Antkeeper source code is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef ANTKEEPER_MATH_HPP | |||
#define ANTKEEPER_MATH_HPP | |||
/// Contains mathematical functions and data types. | |||
namespace math {} | |||
/** | |||
* @defgroup vector Vector | |||
* | |||
* Vector type, functions, and operators. | |||
*/ | |||
#include "math/vector-type.hpp" | |||
#include "math/vector-functions.hpp" | |||
#include "math/vector-operators.hpp" | |||
/** | |||
* @defgroup matrix Matrix | |||
* | |||
* Matrix type, functions, and operators. | |||
*/ | |||
#include "math/matrix-type.hpp" | |||
#include "math/matrix-functions.hpp" | |||
#include "math/matrix-operators.hpp" | |||
/** | |||
* @defgroup quaternion Quaternion | |||
* | |||
* Quaternion type, functions, and operators. | |||
*/ | |||
#include "math/quaternion-type.hpp" | |||
#include "math/quaternion-functions.hpp" | |||
#include "math/quaternion-operators.hpp" | |||
/** | |||
* @defgroup transform Transform | |||
* | |||
* TRS transform type, functions, and operators. | |||
*/ | |||
#include "math/transform-type.hpp" | |||
#include "math/transform-functions.hpp" | |||
#include "math/transform-operators.hpp" | |||
/** | |||
* @defgroup io I/O | |||
* | |||
* Functions and operators that read/write vectors, matrices, or quaternions from/to streams. | |||
*/ | |||
#include "math/stream-operators.hpp" | |||
/** | |||
* @defgroup utility Utility constants and functions | |||
* | |||
* Commonly used utilities. | |||
*/ | |||
#include "math/angles.hpp" | |||
#include "math/constants.hpp" | |||
#include "math/interpolation.hpp" | |||
#include "math/random.hpp" | |||
#endif // ANTKEEPER_MATH_HPP |
@ -0,0 +1,795 @@ | |||
/* | |||
* Copyright (C) 2020 Christopher J. Howard | |||
* | |||
* This file is part of Antkeeper source code. | |||
* | |||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* Antkeeper source code is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef ANTKEEPER_MATH_MATRIX_FUNCTIONS_HPP | |||
#define ANTKEEPER_MATH_MATRIX_FUNCTIONS_HPP | |||
#include "math/matrix-type.hpp" | |||
#include "math/vector-type.hpp" | |||
#include "math/vector-functions.hpp" | |||
#include <type_traits> | |||
namespace math { | |||
/// @addtogroup matrix | |||
/// @{ | |||
/** | |||
* Adds two matrices. | |||
* | |||
* @param x First matrix. | |||
* @param y Second matrix. | |||
* @return Sum of the two matrices. | |||
*/ | |||
template <class T> | |||
matrix<T, 2, 2> add(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y); | |||
/// @copydoc add(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&) | |||
template <class T> | |||
matrix<T, 3, 3> add(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y); | |||
/// @copydoc add(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&) | |||
template <class T> | |||
matrix<T, 4, 4> add(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& y); | |||
/** | |||
* Reinterprets data as an `NxM` matrix of type `T`. | |||
* | |||
* @tparam N Number of columns. | |||
* @tparam M Number of rows. | |||
* @tparam T Element type. | |||
* @param data Data to reinterpret. | |||
*/ | |||
template <std::size_t N, std::size_t M, typename T> | |||
matrix<T, N, M>& as_matrix(T& data); | |||
/** | |||
* Calculates the determinant of a matrix. | |||
* | |||
* @param m Matrix of which to take the determinant. | |||
*/ | |||
template <class T> | |||
T determinant(const matrix<T, 2, 2>& m); | |||
/// @copydoc determinant(const matrix<T, 2, 2>&) | |||
template <class T> | |||
T determinant(const matrix<T, 3, 3>& m); | |||
/// @copydoc determinant(const matrix<T, 2, 2>&) | |||
template <class T> | |||
T determinant(const matrix<T, 4, 4>& m); | |||
/** | |||
* Calculates the inverse of a matrix. | |||
* | |||
* @param m Matrix of which to take the inverse. | |||
*/ | |||
template <class T> | |||
matrix<T, 2, 2> inverse(const matrix<T, 2, 2>& m); | |||
/// @copydoc inverse(const matrix<T, 2, 2>&) | |||
template <class T> | |||
matrix<T, 3, 3> inverse(const matrix<T, 3, 3>& m); | |||
/// @copydoc inverse(const matrix<T, 2, 2>&) | |||
template <class T> | |||
matrix<T, 4, 4> inverse(const matrix<T, 4, 4>& m); | |||
/** | |||
* Performs a component-wise multiplication of two matrices. | |||
* | |||
* @param x First matrix multiplicand. | |||
* @param y Second matrix multiplicand. | |||
*/ | |||
template <class T> | |||
matrix<T, 2, 2> componentwise_mul(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y); | |||
/// @copydoc componentwise_mul(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&) | |||
template <class T> | |||
matrix<T, 3, 3> componentwise_mul(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y); | |||
/// @copydoc componentwise_mul(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&) | |||
template <class T> | |||
matrix<T, 4, 4> componentwise_mul(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& y); | |||
/** | |||
* Creates a viewing transformation matrix. | |||
* | |||
* @param position Position of the view point. | |||
* @param target Position of the target. | |||
* @param up Normalized direction of the up vector. | |||
* @return Viewing transformation matrix. | |||
*/ | |||
template <class T> | |||
matrix<T, 4, 4> look_at(const vector<T, 3>& position, const vector<T, 3>& target, vector<T, 3> up); | |||
/** | |||
* Multiplies two matrices. | |||
* | |||
* @param x First matrix. | |||
* @param y Second matrix. | |||
* @return Product of the two matrices. | |||
*/ | |||
template <class T> | |||
matrix<T, 2, 2> mul(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y); | |||
/// @copydoc mul(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&); | |||
template <class T> | |||
matrix<T, 3, 3> mul(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y); | |||
/// @copydoc mul(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&); | |||
template <class T> | |||
matrix<T, 4, 4> mul(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& y); | |||
/** | |||
* Multiplies a matrix by a scalar. | |||
* | |||
* @param m Matrix. | |||
* @param s Scalar. | |||
* @return Product of the matrix and the scalar.. | |||
*/ | |||
template <class T, std::size_t N, std::size_t M> | |||
matrix<T, N, M> mul(const matrix<T, N, M>& m, T s); | |||
/** | |||
* Transforms a vector by a matrix. | |||
* | |||
* @param m Matrix. | |||
* @param v Vector. | |||
* @return Transformed vector. | |||
*/ | |||
template <class T> | |||
vector<T, 2> mul(const matrix<T, 2, 2>& m, const vector<T, 2>& v); | |||
/// @copydoc mul(const matrix<T, 2, 2>&, const vector<T, 2>&) | |||
template <class T> | |||
vector<T, 3> mul(const matrix<T, 3, 3>& m, const vector<T, 3>& v); | |||
/// @copydoc mul(const matrix<T, 2, 2>&, const vector<T, 2>&) | |||
template <class T> | |||
vector<T, 4> mul(const matrix<T, 4, 4>& m, const vector<T, 4>& v); | |||
/** | |||
* Creates an orthographic projection matrix. | |||
* | |||
* @param left Signed distance to the left clipping plane. | |||
* @param right Signed distance to the right clipping plane. | |||
* @param bottom Signed distance to the bottom clipping plane. | |||
* @param top Signed distance to the top clipping plane. | |||
* @param z_near Signed distance to the near clipping plane. | |||
* @param z_far Signed distance to the far clipping plane. | |||
* @return Orthographic projection matrix. | |||
*/ | |||
template <class T> | |||
matrix<T, 4, 4> ortho(T left, T right, T bottom, T top, T z_near, T z_far); | |||
/** | |||
* Calculates the outer product of a pair of vectors. | |||
* | |||
* @param c Parameter to be treated as a column vector. | |||
* @param r Parameter to be treated as a row vector. | |||
*/ | |||
template <class T> | |||
matrix<T, 2, 2> outer_product(const vector<T, 2>& c, const vector<T, 2>& r); | |||
/// @copydoc outer_product(const vector<T, 2>&, const vector<T, 2>&) | |||
template <class T> | |||
matrix<T, 3, 3> outer_product(const vector<T, 3>& c, const vector<T, 3>& r); | |||
/// @copydoc outer_product(const vector<T, 2>&, const vector<T, 2>&) | |||
template <class T> | |||
matrix<T, 4, 4> outer_product(const vector<T, 4>& c, const vector<T, 4> r); | |||
/** | |||
* Creates a perspective projection matrix. | |||
* | |||
* @param vertical_fov Vertical field of view angle, in radians. | |||
* @param aspect_ratio Aspect ratio which determines the horizontal field of view. | |||
* @param z_near Distance to the near clipping plane. | |||
* @param z_far Distance to the far clipping plane. | |||
* @return Perspective projection matrix. | |||
*/ | |||
template <class T> | |||
matrix<T, 4, 4> perspective(T vertical_fov, T aspect_ratio, T z_near, T z_far); | |||
/** | |||
* Resizes a matrix. Any new elements will be set to `1` if in the diagonal, and `0` otherwise. | |||
* | |||
* @param m Matrix to resize. | |||
* @return Resized matrix. | |||
*/ | |||
template <std::size_t N1, std::size_t M1, class T, std::size_t N0, std::size_t M0> | |||
matrix<T, N1, M1> resize(const matrix<T, N0, M0>& m); | |||
/** | |||
* Rotates a matrix. | |||
* | |||
* @param m Matrix to rotate. | |||
* @param angle Angle of rotation (in radians). | |||
* @param axis Axis of rotation | |||
* @return Rotated matrix. | |||
*/ | |||
template <class T> | |||
matrix<T, 4, 4> rotate(const matrix<T, 4, 4>& m, T angle, const vector<T, 3>& axis); | |||
/** | |||
* Scales a matrix. | |||
* | |||
* @param m Matrix to scale. | |||
* @param v Scale vector. | |||
* @return Scaled matrix. | |||
*/ | |||
template <class T> | |||
matrix<T, 4, 4> scale(const matrix<T, 4, 4>& m, const vector<T, 3>& v); | |||
/** | |||
* Subtracts a matrix from another matrix. | |||
* | |||
* @param x First matrix. | |||
* @param y Second matrix. | |||
* @return Difference between the two matrices. | |||
*/ | |||
template <class T> | |||
matrix<T, 2, 2> sub(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y); | |||
/// @copydoc sub(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&) | |||
template <class T> | |||
matrix<T, 3, 3> sub(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y); | |||
/// @copydoc sub(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&) | |||
template <class T> | |||
matrix<T, 4, 4> sub(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& y); | |||
/** | |||
* Translates a matrix. | |||
* | |||
* @param m Matrix to translate. | |||
* @param v Translation vector. | |||
* @return Translated matrix. | |||
*/ | |||
template <class T> | |||
matrix<T, 4, 4> translate(const matrix<T, 4, 4>& m, const vector<T, 3>& v); | |||
/** | |||
* Calculates the transpose of a matrix. | |||
* | |||
* @param m Matrix of which to take the transpose. | |||
*/ | |||
template <class T> | |||
matrix<T, 2, 2> transpose(const matrix<T, 2, 2>& m); | |||
/// @copydoc transpose(const matrix<T, 2, 2>&) | |||
template <class T> | |||
matrix<T, 3, 3> transpose(const matrix<T, 3, 3>& m); | |||
/// @copydoc transpose(const matrix<T, 2, 2>&) | |||
template <class T> | |||
matrix<T, 4, 4> transpose(const matrix<T, 4, 4>& m); | |||
template <class T> | |||
matrix<T, 2, 2> add(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y) | |||
{ | |||
return | |||
{{ | |||
x[0] + y[0], | |||
x[1] + y[1] | |||
}}; | |||
} | |||
template <class T> | |||
matrix<T, 3, 3> add(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y) | |||
{ | |||
return | |||
{{ | |||
x[0] + y[0], | |||
x[1] + y[1], | |||
x[2] + y[2] | |||
}}; | |||
} | |||
template <class T> | |||
matrix<T, 4, 4> add(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& y) | |||
{ | |||
return | |||
{{ | |||
x[0] + y[0], | |||
x[1] + y[1], | |||
x[2] + y[2], | |||
x[3] + y[3] | |||
}}; | |||
} | |||
template <std::size_t N, std::size_t M, typename T> | |||
inline matrix<T, N, M>& as_matrix(T& data) | |||
{ | |||
static_assert(std::is_pod<matrix<T, N, M>>::value); | |||
return reinterpret_cast<matrix<T, N, M>&>(data); | |||
} | |||
template <class T> | |||
T determinant(const matrix<T, 2, 2>& m) | |||
{ | |||
return m[0][0] * m[1][1] - m[0][1] * m[1][0]; | |||
} | |||
template <class T> | |||
T determinant(const matrix<T, 3, 3>& m) | |||
{ | |||
return m[0][0] * m [1][1] * m[2][2] + | |||
m[0][1] * m[1][2] * m[2][0] + | |||
m[0][2] * m[1][0] * m[2][1] - | |||
m[0][0] * m[1][2] * m[2][1] - | |||
m[0][1] * m[1][0] * m[2][2] - | |||
m[0][2] * m[1][1] * m[2][0]; | |||
} | |||
template <class T> | |||
T determinant(const matrix<T, 4, 4>& m) | |||
{ | |||
return m[0][3] * m[1][2] * m[2][1] * m[3][0] - m[0][2] * m[1][3] * m[2][1] * m[3][0] - | |||
m[0][3] * m[1][1] * m[2][2] * m[3][0] + m[0][1] * m[1][3] * m[2][2] * m[3][0] + | |||
m[0][2] * m[1][1] * m[2][3] * m[3][0] - m[0][1] * m[1][2] * m[2][3] * m[3][0] - | |||
m[0][3] * m[1][2] * m[2][0] * m[3][1] + m[0][2] * m[1][3] * m[2][0] * m[3][1] + | |||
m[0][3] * m[1][0] * m[2][2] * m[3][1] - m[0][0] * m[1][3] * m[2][2] * m[3][1] - | |||
m[0][2] * m[1][0] * m[2][3] * m[3][1] + m[0][0] * m[1][2] * m[2][3] * m[3][1] + | |||
m[0][3] * m[1][1] * m[2][0] * m[3][2] - m[0][1] * m[1][3] * m[2][0] * m[3][2] - | |||
m[0][3] * m[1][0] * m[2][1] * m[3][2] + m[0][0] * m[1][3] * m[2][1] * m[3][2] + | |||
m[0][1] * m[1][0] * m[2][3] * m[3][2] - m[0][0] * m[1][1] * m[2][3] * m[3][2] - | |||
m[0][2] * m[1][1] * m[2][0] * m[3][3] + m[0][1] * m[1][2] * m[2][0] * m[3][3] + | |||
m[0][2] * m[1][0] * m[2][1] * m[3][3] - m[0][0] * m[1][2] * m[2][1] * m[3][3] - | |||
m[0][1] * m[1][0] * m[2][2] * m[3][3] + m[0][0] * m[1][1] * m[2][2] * m[3][3]; | |||
} | |||
template <class T> | |||
matrix<T, 2, 2> inverse(const matrix<T, 2, 2>& m) | |||
{ | |||
static_assert(std::is_floating_point<T>::value); | |||
const T rd(T(1) / determinant(m)); | |||
return | |||
{{ | |||
{ m[1][1] * rd, -m[0][1] * rd}, | |||
{-m[1][0] * rd, m[0][0] * rd} | |||
}}; | |||
} | |||
template <class T> | |||
matrix<T, 3, 3> inverse(const matrix<T, 3, 3>& m) | |||
{ | |||
static_assert(std::is_floating_point<T>::value); | |||
const T rd(T(1) / determinant(m)); | |||
return | |||
{{ | |||
{ | |||
(m[1][1] * m[2][2] - m[1][2] * m[2][1]) * rd, | |||
(m[0][2] * m[2][1] - m[0][1] * m[2][2]) * rd, | |||
(m[0][1] * m[1][2] - m[0][2] * m[1][1]) * rd | |||
}, | |||
{ | |||
(m[1][2] * m[2][0] - m[1][0] * m[2][2]) * rd, | |||
(m[0][0] * m[2][2] - m[0][2] * m[2][0]) * rd, | |||
(m[0][2] * m[1][0] - m[0][0] * m[1][2]) * rd | |||
}, | |||
{ | |||
(m[1][0] * m[2][1] - m[1][1] * m[2][0]) * rd, | |||
(m[0][1] * m[2][0] - m[0][0] * m[2][1]) * rd, | |||
(m[0][0] * m[1][1] - m[0][1] * m[1][0]) * rd | |||
} | |||
}}; | |||
} | |||
template <class T> | |||
matrix<T, 4, 4> inverse(const matrix<T, 4, 4>& m) | |||
{ | |||
static_assert(std::is_floating_point<T>::value); | |||
const T rd(T(1) / determinant(m)); | |||
return | |||
{{ | |||
{ | |||
(m[1][2] * m[2][3] * m[3][1] - m[1][3] * m[2][2] * m[3][1] + m[1][3] * m[2][1] * m[3][2] - m[1][1] * m[2][3] * m[3][2] - m[1][2] * m[2][1] * m[3][3] + m[1][1] * m[2][2] * m[3][3]) * rd, | |||
(m[0][3] * m[2][2] * m[3][1] - m[0][2] * m[2][3] * m[3][1] - m[0][3] * m[2][1] * m[3][2] + m[0][1] * m[2][3] * m[3][2] + m[0][2] * m[2][1] * m[3][3] - m[0][1] * m[2][2] * m[3][3]) * rd, | |||
(m[0][2] * m[1][3] * m[3][1] - m[0][3] * m[1][2] * m[3][1] + m[0][3] * m[1][1] * m[3][2] - m[0][1] * m[1][3] * m[3][2] - m[0][2] * m[1][1] * m[3][3] + m[0][1] * m[1][2] * m[3][3]) * rd, | |||
(m[0][3] * m[1][2] * m[2][1] - m[0][2] * m[1][3] * m[2][1] - m[0][3] * m[1][1] * m[2][2] + m[0][1] * m[1][3] * m[2][2] + m[0][2] * m[1][1] * m[2][3] - m[0][1] * m[1][2] * m[2][3]) * rd | |||
}, | |||
{ | |||
(m[1][3] * m[2][2] * m[3][0] - m[1][2] * m[2][3] * m[3][0] - m[1][3] * m[2][0] * m[3][2] + m[1][0] * m[2][3] * m[3][2] + m[1][2] * m[2][0] * m[3][3] - m[1][0] * m[2][2] * m[3][3]) * rd, | |||
(m[0][2] * m[2][3] * m[3][0] - m[0][3] * m[2][2] * m[3][0] + m[0][3] * m[2][0] * m[3][2] - m[0][0] * m[2][3] * m[3][2] - m[0][2] * m[2][0] * m[3][3] + m[0][0] * m[2][2] * m[3][3]) * rd, | |||
(m[0][3] * m[1][2] * m[3][0] - m[0][2] * m[1][3] * m[3][0] - m[0][3] * m[1][0] * m[3][2] + m[0][0] * m[1][3] * m[3][2] + m[0][2] * m[1][0] * m[3][3] - m[0][0] * m[1][2] * m[3][3]) * rd, | |||
(m[0][2] * m[1][3] * m[2][0] - m[0][3] * m[1][2] * m[2][0] + m[0][3] * m[1][0] * m[2][2] - m[0][0] * m[1][3] * m[2][2] - m[0][2] * m[1][0] * m[2][3] + m[0][0] * m[1][2] * m[2][3]) * rd | |||
}, | |||
{ | |||
(m[1][1] * m[2][3] * m[3][0] - m[1][3] * m[2][1] * m[3][0] + m[1][3] * m[2][0] * m[3][1] - m[1][0] * m[2][3] * m[3][1] - m[1][1] * m[2][0] * m[3][3] + m[1][0] * m[2][1] * m[3][3]) * rd, | |||
(m[0][3] * m[2][1] * m[3][0] - m[0][1] * m[2][3] * m[3][0] - m[0][3] * m[2][0] * m[3][1] + m[0][0] * m[2][3] * m[3][1] + m[0][1] * m[2][0] * m[3][3] - m[0][0] * m[2][1] * m[3][3]) * rd, | |||
(m[0][1] * m[1][3] * m[3][0] - m[0][3] * m[1][1] * m[3][0] + m[0][3] * m[1][0] * m[3][1] - m[0][0] * m[1][3] * m[3][1] - m[0][1] * m[1][0] * m[3][3] + m[0][0] * m[1][1] * m[3][3]) * rd, | |||
(m[0][3] * m[1][1] * m[2][0] - m[0][1] * m[1][3] * m[2][0] - m[0][3] * m[1][0] * m[2][1] + m[0][0] * m[1][3] * m[2][1] + m[0][1] * m[1][0] * m[2][3] - m[0][0] * m[1][1] * m[2][3]) * rd | |||
}, | |||
{ | |||
(m[1][2] * m[2][1] * m[3][0] - m[1][1] * m[2][2] * m[3][0] - m[1][2] * m[2][0] * m[3][1] + m[1][0] * m[2][2] * m[3][1] + m[1][1] * m[2][0] * m[3][2] - m[1][0] * m[2][1] * m[3][2]) * rd, | |||
(m[0][1] * m[2][2] * m[3][0] - m[0][2] * m[2][1] * m[3][0] + m[0][2] * m[2][0] * m[3][1] - m[0][0] * m[2][2] * m[3][1] - m[0][1] * m[2][0] * m[3][2] + m[0][0] * m[2][1] * m[3][2]) * rd, | |||
(m[0][2] * m[1][1] * m[3][0] - m[0][1] * m[1][2] * m[3][0] - m[0][2] * m[1][0] * m[3][1] + m[0][0] * m[1][2] * m[3][1] + m[0][1] * m[1][0] * m[3][2] - m[0][0] * m[1][1] * m[3][2]) * rd, | |||
(m[0][1] * m[1][2] * m[2][0] - m[0][2] * m[1][1] * m[2][0] + m[0][2] * m[1][0] * m[2][1] - m[0][0] * m[1][2] * m[2][1] - m[0][1] * m[1][0] * m[2][2] + m[0][0] * m[1][1] * m[2][2]) * rd | |||
} | |||
}}; | |||
} | |||
template <class T> | |||
matrix<T, 2, 2> componentwise_mul(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y) | |||
{ | |||
return | |||
{{ | |||
{x[0][0] * y[0][0], x[0][1] * y[0][1]}, | |||
{x[1][0] * y[1][0], x[1][1] * y[1][1]} | |||
}}; | |||
} | |||
template <class T> | |||
matrix<T, 3, 3> componentwise_mul(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y) | |||
{ | |||
return | |||
{{ | |||
{x[0][0] * y[0][0], x[0][1] * y[0][1], x[0][2] * y[0][2]}, | |||
{x[1][0] * y[1][0], x[1][1] * y[1][1], x[1][2] * y[1][2]}, | |||
{x[2][0] * y[2][0], x[2][1] * y[2][1], x[2][2] * y[2][2]} | |||
}}; | |||
} | |||
template <class T> | |||
matrix<T, 4, 4> componentwise_mul(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& y) | |||
{ | |||
return | |||
{{ | |||
{x[0][0] * y[0][0], x[0][1] * y[0][1], x[0][2] * y[0][2], x[0][3] * y[0][3]}, | |||
{x[1][0] * y[1][0], x[1][1] * y[1][1], x[1][2] * y[1][2], x[1][3] * y[1][3]}, | |||
{x[2][0] * y[2][0], x[2][1] * y[2][1], x[2][2] * y[2][2], x[2][3] * y[2][3]}, | |||
{x[3][0] * y[3][0], x[3][1] * y[3][1], x[3][2] * y[3][2], x[3][3] * y[3][3]} | |||
}}; | |||
} | |||
template <class T> | |||
matrix<T, 4, 4> look_at(const vector<T, 3>& position, const vector<T, 3>& target, vector<T, 3> up) | |||
{ | |||
vector<T, 3> forward = normalize(sub(target, position)); | |||
vector<T, 3> right = normalize(cross(forward, up)); | |||
up = cross(right, forward); | |||
matrix<T, 4, 4> m = | |||
{{ | |||
{right[0], up[0], -forward[0], T(0)}, | |||
{right[1], up[1], -forward[1], T(0)}, | |||
{right[2], up[2], -forward[2], T(0)}, | |||
{T(0), T(0), T(0), T(1)} | |||
}}; | |||
return translate(m, negate(position)); | |||
} | |||
template <class T> | |||
matrix<T, 2, 2> mul(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y) | |||
{ | |||
return | |||
{{ | |||
x[0] * y[0][0] + x[1] * y[0][1], | |||
x[0] * y[1][0] + x[1] * y[1][1] | |||
}}; | |||
} | |||
template <class T> | |||
matrix<T, 3, 3> mul(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y) | |||
{ | |||
return | |||
{{ | |||
x[0] * y[0][0] + x[1] * y[0][1] + x[2] * y[0][2], | |||
x[0] * y[1][0] + x[1] * y[1][1] + x[2] * y[1][2], | |||
x[0] * y[2][0] + x[1] * y[2][1] + x[2] * y[2][2] | |||
}}; | |||
} | |||
template <class T> | |||
matrix<T, 4, 4> mul(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& y) | |||
{ | |||
return | |||
{{ | |||
x[0] * y[0][0] + x[1] * y[0][1] + x[2] * y[0][2] + x[3] * y[0][3], | |||
x[0] * y[1][0] + x[1] * y[1][1] + x[2] * y[1][2] + x[3] * y[1][3], | |||
x[0] * y[2][0] + x[1] * y[2][1] + x[2] * y[2][2] + x[3] * y[2][3], | |||
x[0] * y[3][0] + x[1] * y[3][1] + x[2] * y[3][2] + x[3] * y[3][3] | |||
}}; | |||
} | |||
/// @private | |||
template <class T, std::size_t N, std::size_t M, std::size_t... I> | |||
inline matrix<T, N, M> mul(const matrix<T, N, M>& m, T s, std::index_sequence<I...>) | |||
{ | |||
return {{(m[I] * s)...}}; | |||
} | |||
template <class T, std::size_t N, std::size_t M> | |||
inline matrix<T, N, M> mul(const matrix<T, N, M>& m, T s) | |||
{ | |||
return mul(m, s, std::make_index_sequence<N>{}); | |||
} | |||
template <class T> | |||
vector<T, 2> mul(const matrix<T, 2, 2>& m, const vector<T, 2>& v) | |||
{ | |||
return | |||
{ | |||
m[0][0] * v[0] + m[1][0] * v[1], | |||
m[0][1] * v[0] + m[1][1] * v[1] | |||
}; | |||
} | |||
template <class T> | |||
vector<T, 3> mul(const matrix<T, 3, 3>& m, const vector<T, 3>& v) | |||
{ | |||
return | |||
{ | |||
m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2], | |||
m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2], | |||
m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2] | |||
}; | |||
} | |||
template <class T> | |||
vector<T, 4> mul(const matrix<T, 4, 4>& m, const vector<T, 4>& v) | |||
{ | |||
return | |||
{ | |||
m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2] + m[3][0] * v[3], | |||
m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2] + m[3][1] * v[3], | |||
m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2] + m[3][2] * v[3], | |||
m[0][3] * v[0] + m[1][3] * v[1] + m[2][3] * v[2] + m[3][3] * v[3] | |||
}; | |||
} | |||
template <class T> | |||
matrix<T, 4, 4> ortho(T left, T right, T bottom, T top, T z_near, T z_far) | |||
{ | |||
return | |||
{{ | |||
{T(2) / (right - left), T(0), T(0), T(0)}, | |||
{T(0), T(2) / (top - bottom), T(0), T(0)}, | |||
{T(0), T(0), T(-2) / (z_far - z_near), T(0)}, | |||
{-((right + left) / (right - left)), -((top + bottom) / (top - bottom)), -((z_far + z_near) / (z_far - z_near)), T(1)} | |||
}}; | |||
} | |||
template <class T> | |||
matrix<T, 2, 2> outer_product(const vector<T, 2>& c, const vector<T, 2>& r) | |||
{ | |||
return | |||
{{ | |||
{c[0] * r[0], c[1] * r[0]}, | |||
{c[0] * r[1], c[1] * r[1]} | |||
}}; | |||
} | |||
template <class T> | |||
matrix<T, 3, 3> outer_product(const vector<T, 3>& c, const vector<T, 3>& r) | |||
{ | |||
return | |||
{{ | |||
{c[0] * r[0], c[1] * r[0], c[2] * r[0]}, | |||
{c[0] * r[1], c[1] * r[1], c[2] * r[1]}, | |||
{c[0] * r[2], c[1] * r[2], c[2] * r[2]} | |||
}}; | |||
} | |||
template <class T> | |||
matrix<T, 4, 4> outer_product(const vector<T, 4>& c, const vector<T, 4> r) | |||
{ | |||
return | |||
{{ | |||
{c[0] * r[0], c[1] * r[0], c[2] * r[0], c[3] * r[0]}, | |||
{c[0] * r[1], c[1] * r[1], c[2] * r[1], c[3] * r[1]}, | |||
{c[0] * r[2], c[1] * r[2], c[2] * r[2], c[3] * r[2]}, | |||
{c[0] * r[3], c[1] * r[3], c[2] * r[3], c[3] * r[3]} | |||
}}; | |||
} | |||
template <class T> | |||
matrix<T, 4, 4> perspective(T vertical_fov, T aspect_ratio, T z_near, T z_far) | |||
{ | |||
T half_fov = vertical_fov * T(0.5); | |||
T f = std::cos(half_fov) / std::sin(half_fov); | |||
return | |||
{{ | |||
{f / aspect_ratio, T(0), T(0), T(0)}, | |||
{T(0), f, T(0), T(0)}, | |||
{T(0), T(0), (z_far + z_near) / (z_near - z_far), T(-1)}, | |||
{T(0), T(0), (T(2) * z_near * z_far) / (z_near - z_far), T(0)} | |||
}}; | |||
} | |||
template <std::size_t N1, std::size_t M1, class T, std::size_t N0, std::size_t M0> | |||
matrix<T, N1, M1> resize(const matrix<T, N0, M0>& m) | |||
{ | |||
matrix<T, N1, M1> resized; | |||
for (std::size_t i = 0; i < N1; ++i) | |||
{ | |||
for (std::size_t j = 0; j < M1; ++j) | |||
{ | |||
resized[i][j] = (i < N0 && j < M0) ? m[i][j] : ((i == j) ? T(1) : T(0)); | |||
} | |||
} | |||
return resized; | |||
} | |||
template <class T> | |||
matrix<T, 4, 4> rotate(const matrix<T, 4, 4>& m, T angle, const vector<T, 3>& axis) | |||
{ | |||
const T c = std::cos(angle); | |||
const T s = std::sin(angle); | |||
const vector<T, 3> temp = mul(axis, T(1) - c); | |||
matrix<T, 4, 4> rotation; | |||
rotation[0][0] = axis[0] * temp[0] + c | |||
rotation[0][1] = axis[1] * temp[0] + axis[2] * s; | |||
rotation[0][2] = axis[2] * temp[0] - axis[1] * s; | |||
rotation[0][3] = T(0); | |||
rotation[1][0] = axis[0] * temp[1] - axis[2] * s | |||
rotation[1][1] = axis[1] * temp[1] + c; | |||
rotation[1][2] = axis[2] * temp[1] + axis[0] * s; | |||
rotation[1][3] = T(0); | |||
rotation[2][0] = axis[0] * temp[2] + axis[1] * s; | |||
rotation[2][1] = axis[1] * temp[2] - axis[0] * s; | |||
rotation[2][2] = axis[2] * temp[2] + c | |||
rotation[2][3] = T(0); | |||
rotation[3][0] = T(0); | |||
rotation[3][1] = T(0); | |||
rotation[3][2] = T(0); | |||
rotation[3][3] = T(1); | |||
return mul(m, rotation); | |||
} | |||
template <class T> | |||
matrix<T, 4, 4> scale(const matrix<T, 4, 4>& m, const vector<T, 3>& v) | |||
{ | |||
return mul(m, matrix<T, 4, 4> | |||
{{ | |||
{v[0], T(0), T(0), T(0)}, | |||
{T(0), v[1], T(0), T(0)}, | |||
{T(0), T(0), v[2], T(0)}, | |||
{T(0), T(0), T(0), T(1)} | |||
}}); | |||
} | |||
template <class T> | |||
matrix<T, 2, 2> sub(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y) | |||
{ | |||
return | |||
{{ | |||
x[0] - y[0], | |||
x[1] - y[1] | |||
}}; | |||
} | |||
template <class T> | |||
matrix<T, 3, 3> sub(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y) | |||
{ | |||
return | |||
{{ | |||
x[0] - y[0], | |||
x[1] - y[1], | |||
x[2] - y[2] | |||
}}; | |||
} | |||
template <class T> | |||
matrix<T, 4, 4> sub(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& y) | |||
{ | |||
return | |||
{{ | |||
x[0] - y[0], | |||
x[1] - y[1], | |||
x[2] - y[2], | |||
x[3] - y[3] | |||
}}; | |||
} | |||
template <class T> | |||
matrix<T, 4, 4> translate(const matrix<T, 4, 4>& m, const vector<T, 3>& v) | |||
{ | |||
return mul(m, matrix<T, 4, 4> | |||
{{ | |||
{T(1), T(0), T(0), T(0)}, | |||
{T(0), T(1), T(0), T(0)}, | |||
{T(0), T(0), T(1), T(0)}, | |||
{v[0], v[1], v[2], T(1)} | |||
}}); | |||
} | |||
template <class T> | |||
matrix<T, 2, 2> transpose(const matrix<T, 2, 2>& m) | |||
{ | |||
return | |||
{{ | |||
{ | |||
m[0][0], m[1][0] | |||
}, | |||
{ | |||
m[0][1], m[1][1] | |||
} | |||
}}; | |||
} | |||
template <class T> | |||
matrix<T, 3, 3> transpose(const matrix<T, 3, 3>& m) | |||
{ | |||
return | |||
{{ | |||
{ | |||
m[0][0], m[1][0], m[2][0] | |||
}, | |||
{ | |||
m[0][1], m[1][1], m[2][1] | |||
}, | |||
{ | |||
m[0][2], m[1][2], m[2][2] | |||
} | |||
}}; | |||
} | |||
template <class T> | |||
matrix<T, 4, 4> transpose(const matrix<T, 4, 4>& m) | |||
{ | |||
return | |||
{{ | |||
{ | |||
m[0][0], m[1][0], m[2][0], m[3][0] | |||
}, | |||
{ | |||
m[0][1], m[1][1], m[2][1], m[3][1] | |||
}, | |||
{ | |||
m[0][2], m[1][2], m[2][2], m[3][2] | |||
}, | |||
{ | |||
m[0][3], m[1][3], m[2][3], m[3][3] | |||
} | |||
}}; | |||
} | |||
/// @} | |||
} // namespace math | |||
#endif // ANTKEEPER_MATH_MATRIX_FUNCTIONS_HPP |
@ -0,0 +1,100 @@ | |||
/* | |||
* Copyright (C) 2020 Christopher J. Howard | |||
* | |||
* This file is part of Antkeeper source code. | |||
* | |||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* Antkeeper source code is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef ANTKEEPER_MATH_MATRIX_OPERATORS_HPP | |||
#define ANTKEEPER_MATH_MATRIX_OPERATORS_HPP | |||
#include "math/matrix-type.hpp" | |||
#include "math/matrix-functions.hpp" | |||
namespace math { | |||
namespace matrix_operators { | |||
/// @addtogroup matrix | |||
/// @{ | |||
/// @copydoc add(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&) | |||
template <class T, std::size_t N, std::size_t M> | |||
matrix<T, N, M> operator+(const matrix<T, N, M>& x, const matrix<T, N, M>& y); | |||
/// @copydoc mul(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&) | |||
template <class T, std::size_t N, std::size_t M> | |||
matrix<T, N, M> operator*(const matrix<T, N, M>& x, const matrix<T, N, M>& y); | |||
/// @copydoc mul(const matrix<T, N, M>&, T) | |||
template <class T, std::size_t N, std::size_t M> | |||
matrix<T, N, M> operator*(const matrix<T, N, M>& m, T s); | |||
/// @copydoc mul(const matrix<T, N, M>&, T) | |||
template <class T, std::size_t N, std::size_t M> | |||
matrix<T, N, M> operator*(T s, const matrix<T, N, M>& m); | |||
/// @copydoc mul(const matrix<T, 2, 2>&, const vector<T, 2>&) | |||
template <class T, std::size_t N> | |||
vector<T, N> operator*(const matrix<T, N, N>& m, const vector<T, N>& v); | |||
/// @copydoc sub(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&) | |||
template <class T, std::size_t N, std::size_t M> | |||
matrix<T, N, M> operator-(const matrix<T, N, M>& x, const matrix<T, N, M>& y); | |||
template <class T, std::size_t N, std::size_t M> | |||
inline matrix<T, N, M> operator+(const matrix<T, N, M>& x, const matrix<T, N, M>& y) | |||
{ | |||
return add(x, y); | |||
} | |||
template <class T, std::size_t N, std::size_t M> | |||
inline matrix<T, N, M> operator*(const matrix<T, N, M>& x, const matrix<T, N, M>& y) | |||
{ | |||
return mul(x, y); | |||
} | |||
template <class T, std::size_t N, std::size_t M> | |||
inline matrix<T, N, M> operator*(const matrix<T, N, M>& m, T s) | |||
{ | |||
return mul(m, s); | |||
} | |||
template <class T, std::size_t N, std::size_t M> | |||
inline matrix<T, N, M> operator*(T s, const matrix<T, N, M>& m) | |||
{ | |||
return mul(m, s); | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<T, N> operator*(const matrix<T, N, N>& m, const vector<T, N>& v) | |||
{ | |||
return mul(m, v); | |||
} | |||
template <class T, std::size_t N, std::size_t M> | |||
inline matrix<T, N, M> operator-(const matrix<T, N, M>& x, const matrix<T, N, M>& y) | |||
{ | |||
return sub(x, y); | |||
} | |||
/// @} | |||
} // namespace matrix_operators | |||
} // namespace math | |||
// Bring matrix operators into global namespace | |||
using namespace math::matrix_operators; | |||
#endif // ANTKEEPER_MATH_MATRIX_OPERATORS_HPP |
@ -0,0 +1,54 @@ | |||
/* | |||
* Copyright (C) 2020 Christopher J. Howard | |||
* | |||
* This file is part of Antkeeper source code. | |||
* | |||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* Antkeeper source code is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef ANTKEEPER_MATH_MATRIX_TYPE_HPP | |||
#define ANTKEEPER_MATH_MATRIX_TYPE_HPP | |||
#include "math/vector-type.hpp" | |||
#include <cstddef> | |||
namespace math { | |||
/// @addtogroup matrix | |||
/// @{ | |||
/** | |||
* An NxM matrix. | |||
* | |||
* @tparam T Matrix element type. | |||
* @tparam N Number of columns. | |||
* @tparam M Number of rows. | |||
*/ | |||
template <typename T, std::size_t N, std::size_t M> | |||
struct matrix | |||
{ | |||
typedef T element_type; | |||
typedef vector<element_type, M> row_type; | |||
row_type columns[N]; | |||
inline constexpr row_type& operator[](std::size_t i) noexcept { return columns[i]; } | |||
inline constexpr const row_type& operator[](std::size_t i) const noexcept { return columns[i]; } | |||
}; | |||
/// @} | |||
} // namespace math | |||
#endif // ANTKEEPER_MATH_MATRIX_TYPE_HPP | |||
@ -0,0 +1,29 @@ | |||
/* | |||
* Copyright (C) 2020 Christopher J. Howard | |||
* | |||
* This file is part of Antkeeper source code. | |||
* | |||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* Antkeeper source code is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef ANTKEEPER_MATH_OPERATORS_HPP | |||
#define ANTKEEPER_MATH_OPERATORS_HPP | |||
#include "math/vector-operators.hpp" | |||
#include "math/matrix-operators.hpp" | |||
#include "math/quaternion-operators.hpp" | |||
#include "math/transform-operators.hpp" | |||
#include "math/stream-operators.hpp" | |||
#endif // ANTKEEPER_MATH_OPERATORS_HPP |
@ -0,0 +1,443 @@ | |||
/* | |||
* Copyright (C) 2020 Christopher J. Howard | |||
* | |||
* This file is part of Antkeeper source code. | |||
* | |||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* Antkeeper source code is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef ANTKEEPER_MATH_QUATERNION_FUNCTIONS_HPP | |||
#define ANTKEEPER_MATH_QUATERNION_FUNCTIONS_HPP | |||
#include "math/matrix-type.hpp" | |||
#include "math/quaternion-type.hpp" | |||
#include "math/vector-type.hpp" | |||
#include "math/vector-functions.hpp" | |||
#include <cmath> | |||
namespace math { | |||
/// @addtogroup quaternion | |||
/// @{ | |||
/** | |||
* Adds two quaternions. | |||
* | |||
* @param x First quaternion. | |||
* @param y Second quaternion. | |||
* @return Sum of the two quaternions. | |||
*/ | |||
template <class T> | |||
quaternion<T> add(const quaternion<T>& x, const quaternion<T>& y); | |||
/** | |||
* Calculates the conjugate of a quaternion. | |||
* | |||
* @param x Quaternion from which the conjugate will be calculated. | |||
* @return Conjugate of the quaternion. | |||
*/ | |||
template <class T> | |||
quaternion<T> conjugate(const quaternion<T>& x); | |||
/** | |||
* Calculates the dot product of two quaternions. | |||
* | |||
* @param x First quaternion. | |||
* @param y Second quaternion. | |||
* @return Dot product of the two quaternions. | |||
*/ | |||
template <class T> | |||
T dot(const quaternion<T>& x, const quaternion<T>& y); | |||
/** | |||
* Divides a quaternion by a scalar. | |||
* | |||
* @param q Quaternion. | |||
* @param s Scalar. | |||
* @return Result of the division. | |||
*/ | |||
template <class T> | |||
quaternion<T> div(const quaternion<T>& q, T s); | |||
/** | |||
* Calculates the length of a quaternion. | |||
* | |||
* @param x Quaternion to calculate the length of. | |||
* @return Length of the quaternion. | |||
*/ | |||
template <class T> | |||
T length(const quaternion<T>& x); | |||
/** | |||
* Calculates the squared length of a quaternion. The squared length can be calculated faster than the length because a call to `std::sqrt` is saved. | |||
* | |||
* @param x Quaternion to calculate the squared length of. | |||
* @return Squared length of the quaternion. | |||
*/ | |||
template <class T> | |||
T length_squared(const quaternion<T>& x); | |||
/** | |||
* Performs linear interpolation between two quaternions. | |||
* | |||
* @param x First quaternion. | |||
* @param y Second quaternion. | |||
* @param a Interpolation factor. | |||
* @return Interpolated quaternion. | |||
*/ | |||
template <class T> | |||
quaternion<T> lerp(const quaternion<T>& x, const quaternion<T>& y, T a); | |||
/** | |||
* Creates a unit quaternion rotation using forward and up vectors. | |||
* | |||
* @param forward Unit forward vector. | |||
* @param up Unit up vector. | |||
* @return Unit rotation quaternion. | |||
*/ | |||
template <class T> | |||
quaternion<T> look_rotation(const vector<T, 3>& forward, vector<T, 3> up); | |||
/** | |||
* Converts a quaternion to a rotation matrix. | |||
* | |||
* @param q Unit quaternion. | |||
* @return Matrix representing the rotation described by `q`. | |||
*/ | |||
template <class T> | |||
matrix<T, 3, 3> matrix_cast(const quaternion<T>& q); | |||
/** | |||
* Multiplies two quaternions. | |||
* | |||
* @param x First quaternion. | |||
* @param y Second quaternion. | |||
* @return Product of the two quaternions. | |||
*/ | |||
template <class T> | |||
quaternion<T> mul(const quaternion<T>& x, const quaternion<T>& y); | |||
/** | |||
* Multiplies a quaternion by a scalar. | |||
* | |||
* @param q Quaternion. | |||
* @param s Scalar. | |||
* @return Product of the quaternion and scalar. | |||
*/ | |||
template <class T> | |||
quaternion<T> mul(const quaternion<T>& q, T s); | |||
/** | |||
* Rotates a 3-dimensional vector by a quaternion. | |||
* | |||
* @param q Unit quaternion. | |||
* @param v Vector. | |||
* @return Rotated vector. | |||
*/ | |||
template <class T> | |||
vector<T, 3> mul(const quaternion<T>& q, const vector<T, 3>& v); | |||
/** | |||
* Negates a quaternion. | |||
*/ | |||
template <class T> | |||
quaternion<T> negate(const quaternion<T>& x); | |||
/** | |||
* Normalizes a quaternion. | |||
*/ | |||
template <class T> | |||
quaternion<T> normalize(const quaternion<T>& x); | |||
/** | |||
* Creates a rotation from an angle and axis. | |||
* | |||
* @param angle Angle of rotation (in radians). | |||
* @param axis Axis of rotation | |||
* @return Quaternion representing the rotation. | |||
*/ | |||
template <class T> | |||
quaternion<T> angle_axis(T angle, const vector<T, 3>& axis); | |||
/** | |||
* Calculates the minimum rotation between two normalized direction vectors. | |||
* | |||
* @param source Normalized source direction. | |||
* @param destination Normalized destination direction. | |||
* @return Quaternion representing the minimum rotation between the source and destination vectors. | |||
*/ | |||
template <class T> | |||
quaternion<T> rotation(const vector<T, 3>& source, const vector<T, 3>& destination); | |||
/** | |||
* Performs spherical linear interpolation between two quaternions. | |||
* | |||
* @param x First quaternion. | |||
* @param y Second quaternion. | |||
* @param a Interpolation factor. | |||
* @return Interpolated quaternion. | |||
*/ | |||
template <class T> | |||
quaternion<T> slerp(const quaternion<T>& x, const quaternion<T>& y, T a); | |||
/** | |||
* Subtracts a quaternion from another quaternion. | |||
* | |||
* @param x First quaternion. | |||
* @param y Second quaternion. | |||
* @return Difference between the quaternions. | |||
*/ | |||
template <class T> | |||
quaternion<T> sub(const quaternion<T>& x, const quaternion<T>& y); | |||
/** | |||
* Converts a 3x3 rotation matrix to a quaternion. | |||
* | |||
* @param m Rotation matrix. | |||
* @return Unit quaternion representing the rotation described by `m`. | |||
*/ | |||
template <class T> | |||
quaternion<T> quaternion_cast(const matrix<T, 3, 3>& m); | |||
template <class T> | |||
inline quaternion<T> add(const quaternion<T>& x, const quaternion<T>& y) | |||
{ | |||
return {x.w + y.w, x.x + y.x, x.y + y.y, x.z + y.z}; | |||
} | |||
template <class T> | |||
inline quaternion<T> conjugate(const quaternion<T>& x) | |||
{ | |||
return {x.w, -x.x, -x.y, -x.z}; | |||
} | |||
template <class T> | |||
inline T dot(const quaternion<T>& x, const quaternion<T>& y) | |||
{ | |||
return {x.w * y.w + x.x * y.x + x.y * y.y + x.z * y.z}; | |||
} | |||
template <class T> | |||
inline quaternion<T> div(const quaternion<T>& q, T s) | |||
{ | |||
return {q.w / s, q.x / s, q.y / s, q.z / s} | |||
} | |||
template <class T> | |||
inline T length(const quaternion<T>& x) | |||
{ | |||
return std::sqrt(x.w * x.w + x.x * x.x + x.y * x.y + x.z * x.z); | |||
} | |||
template <class T> | |||
inline T length_squared(const quaternion<T>& x) | |||
{ | |||
return x.w * x.w + x.x * x.x + x.y * x.y + x.z * x.z; | |||
} | |||
template <class T> | |||
inline quaternion<T> lerp(const quaternion<T>& x, const quaternion<T>& y, T a) | |||
{ | |||
return | |||
{ | |||
x.w * (T(1) - a) + y.w * a, | |||
x.x * (T(1) - a) + y.x * a, | |||
x.y * (T(1) - a) + y.y * a, | |||
x.z * (T(1) - a) + y.z * a | |||
}; | |||
} | |||
template <class T> | |||
quaternion<T> look_rotation(const vector<T, 3>& forward, vector<T, 3> up) | |||
{ | |||
vector<T, 3> right = normalize(cross(forward, up)); | |||
up = cross(right, forward); | |||
matrix<T, 3, 3> m = | |||
{{ | |||
{right[0], up[0], -forward[0]}, | |||
{right[1], up[1], -forward[1]}, | |||
{right[2], up[2], -forward[2]} | |||
}}; | |||
// Convert to quaternion | |||
return normalize(quaternion_cast(m)); | |||
} | |||
template <class T> | |||
matrix<T, 3, 3> matrix_cast(const quaternion<T>& q) | |||
{ | |||
T wx = q.w * q.x; | |||
T wy = q.w * q.y; | |||
T wz = q.w * q.z; | |||
T xx = q.x * q.x; | |||
T xy = q.x * q.y; | |||
T xz = q.x * q.z; | |||
T yy = q.y * q.y; | |||
T yz = q.y * q.z; | |||
T zz = q.z * q.z; | |||
return | |||
{{ | |||
{T(1) - (yy + zz) * T(2), (xy + wz) * T(2), (xz - wy) * T(2)}, | |||
{(xy - wz) * T(2), T(1) - (xx + zz) * T(2), (yz + wx) * T(2)}, | |||
{(xz + wy) * T(2), (yz - wx) * T(2), T(1) - (xx + yy) * T(2)} | |||
}}; | |||
} | |||
template <class T> | |||
quaternion<T> mul(const quaternion<T>& x, const quaternion<T>& y) | |||
{ | |||
return | |||
{ | |||
-x.x * y.x - x.y * y.y - x.z * y.z + x.w * y.w, | |||
x.x * y.w + x.y * y.z - x.z * y.y + x.w * y.x, | |||
-x.x * y.z + x.y * y.w + x.z * y.x + x.w * y.y, | |||
x.x * y.y - x.y * y.x + x.z * y.w + x.w * y.z | |||
}; | |||
} | |||
template <class T> | |||
inline quaternion<T> mul(const quaternion<T>& q, T s) | |||
{ | |||
return {q.w * s, q.x * s, q.y * s, q.z * s}; | |||
} | |||
template <class T> | |||
vector<T, 3> mul(const quaternion<T>& q, const vector<T, 3>& v) | |||
{ | |||
const T r = q.w; // Real part | |||
const vector<T, 3>& i = reinterpret_cast<const vector<T, 3>&>(q.x); // Imaginary part | |||
return i * dot(i, v) * T(2) + v * (r * r - dot(i, i)) + cross(i, v) * r * T(2); | |||
} | |||
template <class T> | |||
inline quaternion<T> negate(const quaternion<T>& x) | |||
{ | |||
return {-x.w, -x.x, -x.y, -x.z}; | |||
} | |||
template <class T> | |||
inline quaternion<T> normalize(const quaternion<T>& x) | |||
{ | |||
return mul(x, T(1) / length(x)); | |||
} | |||
template <class T> | |||
quaternion<T> angle_axis(T angle, const vector<T, 3>& axis) | |||
{ | |||
T s = std::sin(angle * T(0.5)); | |||
return {static_cast<T>(std::cos(angle * T(0.5))), axis.x * s, axis.y * s, axis.z * s}; | |||
} | |||
template <class T> | |||
quaternion<T> rotation(const vector<T, 3>& source, const vector<T, 3>& destination) | |||
{ | |||
quaternion<T> q; | |||
q.w = dot(source, destination); | |||
reinterpret_cast<vector<T, 3>&>(q.x) = cross(source, destination); | |||
q.w += length(q); | |||
return normalize(q); | |||
} | |||
template <class T> | |||
quaternion<T> slerp(const quaternion<T>& x, const quaternion<T>& y, T a) | |||
{ | |||
T cos_theta = dot(x, y); | |||
constexpr T epsilon = T(0.0005); | |||
if (cos_theta > T(1) - epsilon) | |||
{ | |||
return normalize(lerp(x, y, a)); | |||
} | |||
cos_theta = std::max<T>(T(-1), std::min<T>(T(1), cos_theta)); | |||
T theta = static_cast<T>(std::acos(cos_theta)) * a; | |||
quaternion<T> z = normalize(sub(y, mul(x, cos_theta))); | |||
return add(mul(x, static_cast<T>(std::cos(theta))), mul(z, static_cast<T>(std::sin(theta)))); | |||
} | |||
template <class T> | |||
inline quaternion<T> sub(const quaternion<T>& x, const quaternion<T>& y) | |||
{ | |||
return {x.w - y.w, x.x - y.x, x.y - y.y, x.z - y.z}; | |||
} | |||
template <class T> | |||
quaternion<T> quaternion_cast(const matrix<T, 3, 3>& m) | |||
{ | |||
T r; | |||
vector<T, 3> i; | |||
T trace = m[0][0] + m[1][1] + m[2][2]; | |||
if (trace > T(0)) | |||
{ | |||
T s = T(0.5) / std::sqrt(trace + T(1)); | |||
r = T(0.25) / s; | |||
i = | |||
{ | |||
(m[2][1] - m[1][2]) * s, | |||
(m[0][2] - m[2][0]) * s, | |||
(m[1][0] - m[0][1]) * s | |||
}; | |||
} | |||
else | |||
{ | |||
if (m[0][0] > m[1][1] && m[0][0] > m[2][2]) | |||
{ | |||
T s = T(2) * std::sqrt(T(1) + m[0][0] - m[1][1] - m[2][2]); | |||
r = (m[2][1] - m[1][2]) / s; | |||
i = | |||
{ | |||
T(0.25) * s, | |||
(m[0][1] + m[1][0]) / s, | |||
(m[0][2] + m[2][0]) / s | |||
}; | |||
} | |||
else if (m[1][1] > m[2][2]) | |||
{ | |||
T s = T(2) * std::sqrt(T(1) + m[1][1] - m[0][0] - m[2][2]); | |||
r = (m[0][2] - m[2][0]) / s; | |||
i = | |||
{ | |||
(m[0][1] + m[1][0]) / s, | |||
T(0.25) * s, | |||
(m[1][2] + m[2][1]) / s | |||
}; | |||
} | |||
else | |||
{ | |||
T s = T(2) * std::sqrt(T(1) + m[2][2] - m[0][0] - m[1][1]); | |||
r = (m[1][0] - m[0][1]) / s; | |||
i = | |||
{ | |||
(m[0][2] + m[2][0]) / s, | |||
(m[1][2] + m[2][1]) / s, | |||
T(0.25) * s | |||
}; | |||
} | |||
} | |||
return {r, i.x, i.y, i.z}; | |||
} | |||
/// @} | |||
} // namespace math | |||
#endif // ANTKEEPER_MATH_QUATERNION_FUNCTIONS_HPP | |||
@ -0,0 +1,111 @@ | |||
/* | |||
* Copyright (C) 2020 Christopher J. Howard | |||
* | |||
* This file is part of Antkeeper source code. | |||
* | |||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* Antkeeper source code is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef ANTKEEPER_MATH_QUATERNION_OPERATORS_HPP | |||
#define ANTKEEPER_MATH_QUATERNION_OPERATORS_HPP | |||
#include "math/quaternion-type.hpp" | |||
#include "math/quaternion-functions.hpp" | |||
namespace math { | |||
namespace quaternion_operators { | |||
/// @addtogroup quaternion | |||
/// @{ | |||
/// @copydoc add(const quaternion<T>&, const quaternion<T>&) | |||
template <class T> | |||
quaternion<T> operator+(const quaternion<T>& x, const quaternion<T>& y); | |||
/// @copydoc div(const quaternion<T>&, T) | |||
template <class T> | |||
quaternion<T> operator/(const quaternion<T>& q, T s); | |||
/// @copydoc mul(const quaternion<T>&, const quaternion<T>&) | |||
template <class T> | |||
quaternion<T> operator*(const quaternion<T>& x, const quaternion<T>& y); | |||
/// @copydoc mul(const quaternion<T>&, T) | |||
template <class T> | |||
quaternion<T> operator*(const quaternion<T>& q, T s); | |||
/// @copydoc mul(const quaternion<T>&, const vector<T, 3>&) | |||
template <class T> | |||
vector<T, 3> operator*(const quaternion<T>& q, const vector<T, 3>& v); | |||
/// @copydoc sub(const quaternion<T>&, const quaternion<T>&) | |||
template <class T> | |||
quaternion<T> operator-(const quaternion<T>& x, const quaternion<T>& y); | |||
/// @copydoc negate(const quaternion<T>&) | |||
template <class T, std::size_t N> | |||
quaternion<T> operator-(const quaternion<T>& x); | |||
template <class T> | |||
inline quaternion<T> operator+(const quaternion<T>& x, const quaternion<T>& y) | |||
{ | |||
return add(x, y); | |||
} | |||
template <class T> | |||
inline quaternion<T> operator/(const quaternion<T>& q, T s) | |||
{ | |||
return div(q, s); | |||
} | |||
template <class T> | |||
inline quaternion<T> operator*(const quaternion<T>& x, const quaternion<T>& y) | |||
{ | |||
return mul(x, y); | |||
} | |||
template <class T> | |||
inline quaternion<T> operator*(const quaternion<T>& q, T s) | |||
{ | |||
return mul(q, s); | |||
} | |||
template <class T> | |||
inline vector<T, 3> operator*(const quaternion<T>& q, const vector<T, 3>& v) | |||
{ | |||
return mul(q, v); | |||
} | |||
template <class T> | |||
inline quaternion<T> operator-(const quaternion<T>& x, const quaternion<T>& y) | |||
{ | |||
return sub(x, y); | |||
} | |||
template <class T, std::size_t N> | |||
inline quaternion<T> operator-(const quaternion<T>& x) | |||
{ | |||
return negate(x); | |||
} | |||
/// @} | |||
} // namespace quaternion_operators | |||
} // namespace math | |||
/// Bring quaternion operators into global namespace | |||
using namespace math::quaternion_operators; | |||
#endif // ANTKEEPER_MATH_QUATERNION_OPERATORS_HPP | |||
@ -0,0 +1,48 @@ | |||
/* | |||
* Copyright (C) 2020 Christopher J. Howard | |||
* | |||
* This file is part of Antkeeper source code. | |||
* | |||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* Antkeeper source code is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef ANTKEEPER_MATH_QUATERNION_TYPE_HPP | |||
#define ANTKEEPER_MATH_QUATERNION_TYPE_HPP | |||
namespace math { | |||
/// @addtogroup quaternion | |||
/// @{ | |||
/** | |||
* A quaternion type is a tuple made of a scalar (real) part and vector (imaginary) part. | |||
* | |||
* @tparam T Scalar type. | |||
*/ | |||
template <class T> | |||
struct quaternion | |||
{ | |||
typedef T scalar_type; | |||
scalar_type w; | |||
scalar_type x; | |||
scalar_type y; | |||
scalar_type z; | |||
}; | |||
/// @} | |||
} // namespace math | |||
#endif // ANTKEEPER_MATH_QUATERNION_TYPE_HPP | |||
@ -0,0 +1,55 @@ | |||
/* | |||
* Copyright (C) 2020 Christopher J. Howard | |||
* | |||
* This file is part of Antkeeper source code. | |||
* | |||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* Antkeeper source code is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef ANTKEEPER_MATH_RANDOM_HPP | |||
#define ANTKEEPER_MATH_RANDOM_HPP | |||
#include <cstdlib> | |||
#include <type_traits> | |||
namespace math { | |||
/// @addtogroup utility | |||
/// @{ | |||
/** | |||
* Generates a pseudo-random floating point number on `[start, end)` using std::rand(). | |||
* | |||
* @warning Don't forget to seed with std::srand() before using! | |||
* | |||
* @param start Start of the range (inclusive). | |||
* @param end End of the range (exclusive). | |||
* @return Pseudo-random floating point number. | |||
*/ | |||
template <typename T = float> | |||
T random(T start, T end); | |||
template <typename T> | |||
inline T random(T start, T end) | |||
{ | |||
static_assert(std::is_floating_point<T>::value); | |||
constexpr T rand_max_inverse = T(1) / static_cast<T>(RAND_MAX); | |||
return static_cast<T>(std::rand()) * rand_max_inverse * (end - start) + start; | |||
} | |||
/// @} | |||
} // namespace math | |||
#endif // ANTKEEPER_MATH_RANDOM_HPP |
@ -0,0 +1,114 @@ | |||
/* | |||
* Copyright (C) 2020 Christopher J. Howard | |||
* | |||
* This file is part of Antkeeper source code. | |||
* | |||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* Antkeeper source code is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef ANTKEEPER_MATH_STREAM_OPERATORS_HPP | |||
#define ANTKEEPER_MATH_STREAM_OPERATORS_HPP | |||
#include "math/vector-type.hpp" | |||
#include "math/matrix-type.hpp" | |||
#include "math/quaternion-type.hpp" | |||
#include <ostream> | |||
namespace math { | |||
namespace stream_operators { | |||
/// @addtogroup io | |||
/// @{ | |||
/** | |||
* Writes the elements of a vector to an output stream, with each element delimeted by a space. | |||
* | |||
* @param os Output stream. | |||
* @param v Vector. | |||
* @return Output stream. | |||
*/ | |||
template <class T, std::size_t N> | |||
std::ostream& operator<<(std::ostream& os, const vector<T, N>& v); | |||
/** | |||
* Writes the elements of a matrix to an output stream, with each element delimeted by a space. | |||
* | |||
* @param os Output stream. | |||
* @param m Matrix. | |||
* @return Output stream. | |||
*/ | |||
template <class T, std::size_t N, std::size_t M> | |||
std::ostream& operator<<(std::ostream& os, const matrix<T, N, M>& m); | |||
/** | |||
* Writes the real and imaginary parts of a quaternion to an output stream, with each number delimeted by a space. | |||
* | |||
* @param os Output stream. | |||
* @param q Quaternion. | |||
* @return Output stream. | |||
*/ | |||
template <class T> | |||
std::ostream& operator<<(std::ostream& os, const quaternion<T>& q); | |||
template <class T, std::size_t N> | |||
std::ostream& operator<<(std::ostream& os, const vector<T, N>& v) | |||
{ | |||
for (std::size_t i = 0; i < N; ++i) | |||
{ | |||
os << v[i]; | |||
if (i < N - 1) | |||
{ | |||
os << ' '; | |||
} | |||
} | |||
return os; | |||
} | |||
template <class T, std::size_t N, std::size_t M> | |||
std::ostream& operator<<(std::ostream& os, const matrix<T, N, M>& m) | |||
{ | |||
for (std::size_t i = 0; i < N; ++i) | |||
{ | |||
for (std::size_t j = 0; j < M; ++j) | |||
{ | |||
os << m[i][j]; | |||
if (i < N - 1 || j < M - 1) | |||
{ | |||
os << ' '; | |||
} | |||
} | |||
} | |||
return os; | |||
} | |||
template <class T> | |||
std::ostream& operator<<(std::ostream& os, const quaternion<T>& q) | |||
{ | |||
os << std::get<0>(q) << ' ' << std::get<1>(q)[0] << ' ' << std::get<1>(q)[1] << ' ' << std::get<1>(q)[2]; | |||
return os; | |||
} | |||
/// @} | |||
} // namespace stream_operators | |||
} // namespace math | |||
// Bring stream operators into global namespace | |||
using namespace math::stream_operators; | |||
#endif // ANTKEEPER_MATH_STREAM_OPERATORS_HPP |
@ -0,0 +1,110 @@ | |||
/* | |||
* Copyright (C) 2020 Christopher J. Howard | |||
* | |||
* This file is part of Antkeeper source code. | |||
* | |||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* Antkeeper source code is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef ANTKEEPER_MATH_TRANSFORM_FUNCTIONS_HPP | |||
#define ANTKEEPER_MATH_TRANSFORM_FUNCTIONS_HPP | |||
#include "math/transform-type.hpp" | |||
#include "math/vector-functions.hpp" | |||
#include "math/matrix-functions.hpp" | |||
#include "math/quaternion-functions.hpp" | |||
namespace math { | |||
/// @addtogroup transform | |||
/// @{ | |||
/** | |||
* Calculates the inverse of a transform. | |||
* | |||
* @param t Transform of which to take the inverse. | |||
*/ | |||
template <class T> | |||
transform<T> inverse(const transform<T>& t); | |||
/** | |||
* Converts a transform to a transformation matrix. | |||
* | |||
* @param t Transform. | |||
* @return Matrix representing the transformation described by `t`. | |||
*/ | |||
template <class T> | |||
matrix<T, 4, 4> matrix_cast(const transform<T>& t); | |||
/** | |||
* Multiplies two transforms. | |||
* | |||
* @param x First transform. | |||
* @param y Second transform. | |||
* @return Product of the two transforms. | |||
*/ | |||
template <class T> | |||
transform<T> mul(const transform<T>& x, const transform<T>& y); | |||
/** | |||
* Multiplies a vector by a transform. | |||
* | |||
* @param t Transform. | |||
* @param v Vector. | |||
* @return Product of the transform and vector. | |||
*/ | |||
template <class T> | |||
vector<T, 3> mul(const transform<T>& t, const vector<T, 3>& v); | |||
template <class T> | |||
transform<T> inverse(const transform<T>& t) | |||
{ | |||
transform<T> inverse_t; | |||
inverse_t.scale = {T(1) / t.scale.x, T(1) / t.scale.y, T(1) / t.scale.z}; | |||
inverse_t.rotation = conjugate(t.rotation); | |||
inverse_t.translation = negate(mul(inverse_t.rotation, t.translation)); | |||
return inverse_t; | |||
} | |||
template <class T> | |||
matrix<T, 4, 4> matrix_cast(const transform<T>& t) | |||
{ | |||
matrix<T, 4, 4> transformation = resize<4, 4>(matrix_cast(t.rotation)); | |||
transformation[3] = {t.translation[0], t.translation[1], t.translation[2], T(1)}; | |||
return scale(transformation, t.scale); | |||
} | |||
template <class T> | |||
transform<T> mul(const transform<T>& x, const transform<T>& y) | |||
{ | |||
return | |||
{ | |||
mul(x, y.translation), | |||
normalize(mul(x.rotation, y.rotation)), | |||
x.scale * y.scale | |||
}; | |||
} | |||
template <class T> | |||
vector<T, 3> mul(const transform<T>& t, const vector<T, 3>& v) | |||
{ | |||
return t.translation + (t.rotation * (v * t.scale)); | |||
} | |||
/// @} | |||
} // namespace math | |||
#endif // ANTKEEPER_MATH_TRANSFORM_FUNCTIONS_HPP | |||
@ -0,0 +1,77 @@ | |||
/* | |||
* Copyright (C) 2020 Christopher J. Howard | |||
* | |||
* This file is part of Antkeeper source code. | |||
* | |||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* Antkeeper source code is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef ANTKEEPER_MATH_TRANSFORM_OPERATORS_HPP | |||
#define ANTKEEPER_MATH_TRANSFORM_OPERATORS_HPP | |||
#include "math/transform-type.hpp" | |||
#include "math/transform-functions.hpp" | |||
namespace math { | |||
namespace transform_operators { | |||
/// @addtogroup transform | |||
/// @{ | |||
/// @copydoc mul(const transform<T>&, const transform<T>&) | |||
template <class T> | |||
transform<T> operator*(const transform<T>& x, const transform<T>& y); | |||
/// @copydoc mul(const transform<T>&, const vector<T, 3>&) | |||
template <class T> | |||
vector<T, 3> operator*(const transform<T>& t, const vector<T, 3>& v); | |||
/** | |||
* Multiplies two transforms and stores the result in the first transform. | |||
* | |||
* @param x First transform. | |||
* @param y Second transform. | |||
* @return Reference to the first transform. | |||
*/ | |||
template <class T> | |||
transform<T>& operator*=(transform<T>& x, const transform<T>& y); | |||
template <class T> | |||
inline transform<T> operator*(const transform<T>& x, const transform<T>& y) | |||
{ | |||
return mul(x, y); | |||
} | |||
template <class T> | |||
inline vector<T, 3> operator*(const transform<T>& t, const vector<T, 3>& v) | |||
{ | |||
return mul(t, v); | |||
} | |||
template <class T> | |||
inline transform<T>& operator*=(transform<T>& x, const vector<T, 3>& y) | |||
{ | |||
return (x = x * y); | |||
} | |||
/// @} | |||
} // namespace transform_operators | |||
} // namespace math | |||
// Bring transform operators into global namespace | |||
using namespace math::transform_operators; | |||
#endif // ANTKEEPER_MATH_TRANSFORM_OPERATORS_HPP | |||
@ -0,0 +1,54 @@ | |||
/* | |||
* Copyright (C) 2020 Christopher J. Howard | |||
* | |||
* This file is part of Antkeeper source code. | |||
* | |||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* Antkeeper source code is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef ANTKEEPER_MATH_TRANSFORM_TYPE_HPP | |||
#define ANTKEEPER_MATH_TRANSFORM_TYPE_HPP | |||
#include "math/vector-type.hpp" | |||
#include "math/quaternion-type.hpp" | |||
namespace math { | |||
/// @addtogroup transform | |||
/// @{ | |||
/** | |||
* Represents 3D TRS transformation. | |||
* | |||
* @tparam T Scalar type. | |||
*/ | |||
template <class T> | |||
struct transform | |||
{ | |||
/// Translation vector | |||
vector<T, 3> translation; | |||
/// Rotation quaternion | |||
quaternion<T> rotation; | |||
/// Scale vector | |||
vector<T, 3> scale; | |||
}; | |||
/// @} | |||
} // namespace math | |||
#endif // ANTKEEPER_MATH_TRANSFORM_TYPE_HPP | |||
@ -0,0 +1,627 @@ | |||
/* | |||
* Copyright (C) 2020 Christopher J. Howard | |||
* | |||
* This file is part of Antkeeper source code. | |||
* | |||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* Antkeeper source code is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef ANTKEEPER_MATH_VECTOR_FUNCTIONS_HPP | |||
#define ANTKEEPER_MATH_VECTOR_FUNCTIONS_HPP | |||
#include "math/vector-type.hpp" | |||
#include <algorithm> | |||
#include <cmath> | |||
#include <type_traits> | |||
#include <utility> | |||
namespace math { | |||
/// @addtogroup vector | |||
/// @{ | |||
/** | |||
* Adds two vectors. | |||
* | |||
* @param x First vector. | |||
* @param y Second vector. | |||
* @return Sum of the two vectors. | |||
*/ | |||
template <class T, std::size_t N> | |||
vector<T, N> add(const vector<T, N>& x, const vector<T, N>& y); | |||
/** | |||
* Checks if all elements of a boolean vector are `true`. | |||
* | |||
* @param x Vector to be tested for truth. | |||
* @return `true` if all elements are `true`, `false` otherwise. | |||
*/ | |||
template <std::size_t N> | |||
bool all(const vector<bool, N>& x); | |||
/** | |||
* Checks if any elements of a boolean vector are `true`. | |||
* | |||
* @param x Vector to be tested for truth. | |||
* @return `true` if any elements are `true`, `false` otherwise. | |||
*/ | |||
template <std::size_t N> | |||
bool any(const vector<bool, N>& x); | |||
/** | |||
* Reinterprets data as an `N`-dimensional vector of type `T`. | |||
* | |||
* @tparam N Number of vector dimensions. | |||
* @tparam T Scalar type. | |||
* @param data Data to reinterpret. | |||
*/ | |||
template <std::size_t N, typename T> | |||
vector<T, N>& as_vector(T& data); | |||
/** | |||
* Clamps the values of a vector's elements. | |||
* | |||
* @param x Vector to clamp. | |||
* @param min_value Minimum element value. | |||
* @param max_value Maximum element value. | |||
* @return Clamped vector. | |||
*/ | |||
template <class T, std::size_t N> | |||
vector<T, N> clamp(const vector<T, N>& x, T min_value, T max_value); | |||
/** | |||
* Clamps the length of a vector. | |||
* | |||
* @param x Vector to clamp. | |||
* @param max_length Maximum length. | |||
* @return Length-clamped vector. | |||
*/ | |||
template <class T, std::size_t N> | |||
vector<T, N> clamp_length(const vector<T, N>& x, T max_length); | |||
/** | |||
* Calculate the cross product of two vectors. | |||
* | |||
* @param x First vector. | |||
* @param y Second vector. | |||
* @return Cross product of the two vectors. | |||
*/ | |||
template <class T> | |||
vector<T, 3> cross(const vector<T, 3>& x, const vector<T, 3>& y); | |||
/** | |||
* Calculates the distance between two points. | |||
* | |||
* @param p0 First of two points. | |||
* @param p1 Second of two points. | |||
* @return Distance between the two points. | |||
*/ | |||
template <class T, std::size_t N> | |||
vector<T, N> distance(const vector<T, N>& p0, const vector<T, N>& p1); | |||
/** | |||
* Calculates the squared distance between two points. The squared distance can be calculated faster than the distance because a call to `std::sqrt` is saved. | |||
* | |||
* @param p0 First of two points. | |||
* @param p1 Second of two points. | |||
* @return Squared distance between the two points. | |||
*/ | |||
template <class T, std::size_t N> | |||
vector<T, N> distance_squared(const vector<T, N>& p0, const vector<T, N>& p1); | |||
/** | |||
* Divides a vector by another vector. | |||
* | |||
* @param x First vector. | |||
* @param y Second vector. | |||
* @return Result of the division. | |||
*/ | |||
template <class T, std::size_t N> | |||
vector<T, N> div(const vector<T, N>& x, const vector<T, N>& y); | |||
/** | |||
* Divides a vector by a scalar. | |||
* | |||
* @param v Vector. | |||
* @param s Scalar. | |||
* @return Result of the division. | |||
*/ | |||
template <class T, std::size_t N> | |||
vector<T, N> div(const vector<T, N>& v, T s); | |||
/** | |||
* Calculates the dot product of two vectors. | |||
* | |||
* @param x First vector. | |||
* @param y Second vector. | |||
* @return Dot product of the two vectors. | |||
*/ | |||
template <class T, std::size_t N> | |||
T dot(const vector<T, N>& x, const vector<T, N>& y); | |||
/** | |||
* Compares two vectors for equality | |||
* | |||
* @param x First vector. | |||
* @param y Second vector. | |||
* @return Boolean vector containing the result of the element comparisons. | |||
*/ | |||
template <class T, std::size_t N> | |||
vector<bool, N> equal(const vector<T, N>& x, const vector<T, N>& y); | |||
/** | |||
* Performs a component-wise greater-than comparison of two vectors. | |||
* | |||
* @param x First vector. | |||
* @param y Second vector. | |||
* @return Boolean vector containing the result of the element comparisons. | |||
*/ | |||
template <class T, std::size_t N> | |||
vector<bool, N> greater_than(const vector<T, N>& x, const vector<T, N>& y); | |||
/** | |||
* Performs a component-wise greater-than or equal-to comparison of two vectors. | |||
* | |||
* @param x First vector. | |||
* @param y Second vector. | |||
* @return Boolean vector containing the result of the element comparisons. | |||
*/ | |||
template <class T, std::size_t N> | |||
vector<bool, N> greater_than_equal(const vector<T, N>& x, const vector<T, N>& y); | |||
/** | |||
* Calculates the length of a vector. | |||
* | |||
* @param x Vector of which to calculate the length. | |||
* @return Length of the vector. | |||
*/ | |||
template <class T, std::size_t N> | |||
T length(const vector<T, N>& x); | |||
/** | |||
* Calculates the squared length of a vector. The squared length can be calculated faster than the length because a call to `std::sqrt` is saved. | |||
* | |||
* @param x Vector of which to calculate the squared length. | |||
* @return Squared length of the vector. | |||
*/ | |||
template <class T, std::size_t N> | |||
T length_squared(const vector<T, N>& x); | |||
/** | |||
* Performs a component-wise less-than comparison of two vectors. | |||
* | |||
* @param x First vector. | |||
* @param y Second vector. | |||
* @return Boolean vector containing the result of the element comparisons. | |||
*/ | |||
template <class T, std::size_t N> | |||
vector<bool, N> less_than(const vector<T, N>& x, const vector<T, N>& y); | |||
/** | |||
* Performs a component-wise less-than or equal-to comparison of two vectors. | |||
* | |||
* @param x First vector. | |||
* @param y Second vector. | |||
* @return Boolean vector containing the result of the element comparisons. | |||
*/ | |||
template <class T, std::size_t N> | |||
vector<bool, N> less_than_equal(const vector<T, N>& x, const vector<T, N>& y); | |||
/** | |||
* Multiplies two vectors. | |||
* | |||
* @param x First vector. | |||
* @param y Second vector. | |||
* @return Product of the two vectors. | |||
*/ | |||
template <class T, std::size_t N> | |||
vector<T, N> mul(const vector<T, N>& x, const vector<T, N>& y); | |||
/** | |||
* Multiplies a vector by a scalar. | |||
* | |||
* @param v Vector. | |||
* @param s Scalar. | |||
* @return Product of the vector and scalar. | |||
*/ | |||
template <class T, std::size_t N> | |||
vector<T, N> mul(const vector<T, N>& v, T s); | |||
/** | |||
* Negates a vector. | |||
* | |||
* @param x Vector to negate. | |||
* @return Negated vector. | |||
*/ | |||
template <class T, std::size_t N> | |||
vector<T, N> negate(const vector<T, N>& x); | |||
/** | |||
* Calculates the unit vector in the same direction as the original vector. | |||
* | |||
* @param x Vector to normalize. | |||
* @return Normalized vector. | |||
*/ | |||
template <class T, std::size_t N> | |||
vector<T, N> normalize(const vector<T, N>& x); | |||
/** | |||
* Logically inverts a boolean vector. | |||
* | |||
* @param x Vector to be inverted. | |||
* @return Logically inverted vector. | |||
*/ | |||
template <class T, std::size_t N> | |||
vector<bool, N> not(const vector<T, N>& x); | |||
/** | |||
* Compares two vectors for inequality | |||
* | |||
* @param x First vector. | |||
* @param y Second vector. | |||
* @return Boolean vector containing the result of the element comparisons. | |||
*/ | |||
template <class T, std::size_t N> | |||
vector<bool, N> not_equal(const vector<T, N>& x, const vector<T, N>& y); | |||
/** | |||
* Resizes a vector. Any new elements will be set to `0`. | |||
* | |||
* @param v Vector to resize. | |||
* @return Resized vector. | |||
*/ | |||
template <std::size_t N1, class T, std::size_t N0> | |||
vector<T, N1> resize(const vector<T, N0>& v); | |||
/** | |||
* Subtracts a vector from another vector. | |||
* | |||
* @param x First vector. | |||
* @param y Second vector. | |||
* @return Difference between the two vectors. | |||
*/ | |||
template <class T, std::size_t N> | |||
vector<T, N> sub(const vector<T, N>& x, const vector<T, N>& y); | |||
/** | |||
* Makes an m-dimensional vector by rearranging and/or duplicating elements of an n-dimensional vector. | |||
* | |||
* @tparam Indices List of indices of elements in the vector `v`. | |||
* @tparam T Vector component type. | |||
* @tparam N Number of dimensions in vector `v`. | |||
* @return Vector containing elements from vector `v` in the order specified by `Indices`. The size of the returned vector is equivalent to the number of indices in `Indices`. | |||
*/ | |||
template <std::size_t... Indices, class T, std::size_t N> | |||
vector<T, sizeof...(Indices)> swizzle(const vector<T, N>& v); | |||
/// @private | |||
template <class T, std::size_t N, std::size_t... I> | |||
inline vector<T, N> add(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) | |||
{ | |||
return {(x[I] + y[I])...}; | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<T, N> add(const vector<T, N>& x, const vector<T, N>& y) | |||
{ | |||
return add(x, y, std::make_index_sequence<N>{}); | |||
} | |||
/// @private | |||
template <std::size_t N, std::size_t... I> | |||
inline bool all(const vector<bool, N>& x, std::index_sequence<I...>) | |||
{ | |||
return (x[I] && ...); | |||
} | |||
template <std::size_t N> | |||
inline bool all(const vector<bool, N>& x) | |||
{ | |||
return all(x, std::make_index_sequence<N>{}); | |||
} | |||
/// @private | |||
template <std::size_t N, std::size_t... I> | |||
inline bool any(const vector<bool, N>& x, std::index_sequence<I...>) | |||
{ | |||
return (x[I] || ...); | |||
} | |||
template <std::size_t N> | |||
inline bool any(const vector<bool, N>& x) | |||
{ | |||
return any(x, std::make_index_sequence<N>{}); | |||
} | |||
template <std::size_t N, typename T> | |||
inline vector<T, N>& as_vector(T& data) | |||
{ | |||
static_assert(std::is_pod<vector<T, N>>::value); | |||
return reinterpret_cast<vector<T, N>&>(data); | |||
} | |||
/// @private | |||
template <class T, std::size_t N, std::size_t... I> | |||
inline vector<T, N> clamp(const vector<T, N>& x, T min_value, T max_value, std::index_sequence<I...>) | |||
{ | |||
return {std::min<T>(max_value, std::max<T>(min_value, x[I]))...}; | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<T, N> clamp(const vector<T, N>& x, T min_value, T max_value) | |||
{ | |||
return clamp(x, min_value, max_value, std::make_index_sequence<N>{}); | |||
} | |||
template <class T, std::size_t N> | |||
vector<T, N> clamp_length(const vector<T, N>& x, T max_length) | |||
{ | |||
T length2 = length_squared(x); | |||
return (length2 > max_length * max_length) ? (x * max_length / std::sqrt(length2)) : x; | |||
} | |||
template <class T> | |||
inline vector<T, 3> cross(const vector<T, 3>& x, const vector<T, 3>& y) | |||
{ | |||
return | |||
{ | |||
x[1] * y[2] - y[1] * x[2], | |||
x[2] * y[0] - y[2] * x[0], | |||
x[0] * y[1] - y[0] * x[1] | |||
}; | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<T, N> distance(const vector<T, N>& p0, const vector<T, N>& p1) | |||
{ | |||
static_assert(std::is_floating_point<T>::value); | |||
return length(sub(p0, p1)); | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<T, N> distance_squared(const vector<T, N>& p0, const vector<T, N>& p1) | |||
{ | |||
static_assert(std::is_floating_point<T>::value); | |||
return length_squared(sub(p0, p1)); | |||
} | |||
/// @private | |||
template <class T, std::size_t N, std::size_t... I> | |||
inline vector<T, N> div(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) | |||
{ | |||
return {(x[I] / y[I])...}; | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<T, N> div(const vector<T, N>& x, const vector<T, N>& y) | |||
{ | |||
return div(x, y, std::make_index_sequence<N>{}); | |||
} | |||
/// @private | |||
template <class T, std::size_t N, std::size_t... I> | |||
inline vector<T, N> div(const vector<T, N>& v, T s, std::index_sequence<I...>) | |||
{ | |||
return {(v[I] / s)...}; | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<T, N> div(const vector<T, N>& v, T s) | |||
{ | |||
return div(v, s, std::make_index_sequence<N>{}); | |||
} | |||
/// @private | |||
template <class T, std::size_t N, std::size_t... I> | |||
inline T dot(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) | |||
{ | |||
return ((x[I] * y[I]) + ...); | |||
} | |||
template <class T, std::size_t N> | |||
inline T dot(const vector<T, N>& x, const vector<T, N>& y) | |||
{ | |||
return dot(x, y, std::make_index_sequence<N>{}); | |||
} | |||
/// @private | |||
template <class T, std::size_t N, std::size_t... I> | |||
inline vector<bool, N> equal(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) | |||
{ | |||
return {(x[I] == y[I])...}; | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<bool, N> equal(const vector<T, N>& x, const vector<T, N>& y) | |||
{ | |||
return equal(x, y, std::make_index_sequence<N>{}); | |||
} | |||
/// @private | |||
template <class T, std::size_t N, std::size_t... I> | |||
inline vector<bool, N> greater_than(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) | |||
{ | |||
return {(x[I] > y[I])...}; | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<bool, N> greater_than(const vector<T, N>& x, const vector<T, N>& y) | |||
{ | |||
return greater_than(x, y, std::make_index_sequence<N>{}); | |||
} | |||
/// @private | |||
template <class T, std::size_t N, std::size_t... I> | |||
inline vector<bool, N> greater_than_equal(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) | |||
{ | |||
return {(x[I] >= y[I])...}; | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<bool, N> greater_than_equal(const vector<T, N>& x, const vector<T, N>& y) | |||
{ | |||
return greater_than_equal(x, y, std::make_index_sequence<N>{}); | |||
} | |||
template <class T, std::size_t N> | |||
inline T length(const vector<T, N>& x) | |||
{ | |||
static_assert(std::is_floating_point<T>::value); | |||
return std::sqrt(dot(x, x)); | |||
} | |||
template <class T, std::size_t N> | |||
inline T length_squared(const vector<T, N>& x) | |||
{ | |||
static_assert(std::is_floating_point<T>::value); | |||
return dot(x, x); | |||
} | |||
/// @private | |||
template <class T, std::size_t N, std::size_t... I> | |||
inline vector<bool, N> less_than(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) | |||
{ | |||
return {(x[I] < y[I])...}; | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<bool, N> less_than(const vector<T, N>& x, const vector<T, N>& y) | |||
{ | |||
return less_than(x, y, std::make_index_sequence<N>{}); | |||
} | |||
/// @private | |||
template <class T, std::size_t N, std::size_t... I> | |||
inline vector<bool, N> less_than_equal(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) | |||
{ | |||
return {(x[I] <= y[I])...}; | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<bool, N> less_than_equal(const vector<T, N>& x, const vector<T, N>& y) | |||
{ | |||
return less_than_equal(x, y, std::make_index_sequence<N>{}); | |||
} | |||
/// @private | |||
template <class T, std::size_t N, std::size_t... I> | |||
inline vector<T, N> mul(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) | |||
{ | |||
return {(x[I] * y[I])...}; | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<T, N> mul(const vector<T, N>& x, const vector<T, N>& y) | |||
{ | |||
return mul(x, y, std::make_index_sequence<N>{}); | |||
} | |||
/// @private | |||
template <class T, std::size_t N, std::size_t... I> | |||
inline vector<T, N> mul(const vector<T, N>& v, T s, std::index_sequence<I...>) | |||
{ | |||
return {(v[I] * s)...}; | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<T, N> mul(const vector<T, N>& v, T s) | |||
{ | |||
return mul(v, s, std::make_index_sequence<N>{}); | |||
} | |||
/// @private | |||
template <class T, std::size_t N, std::size_t... I> | |||
inline vector<T, N> negate(const vector<T, N>& x, std::index_sequence<I...>) | |||
{ | |||
return {(-x[I])...}; | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<T, N> negate(const vector<T, N>& x) | |||
{ | |||
return negate(x, std::make_index_sequence<N>{}); | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<T, N> normalize(const vector<T, N>& x) | |||
{ | |||
static_assert(std::is_floating_point<T>::value); | |||
return mul(x, T(1) / length(x)); | |||
} | |||
/// @private | |||
template <class T, std::size_t N, std::size_t... I> | |||
inline vector<bool, N> not(const vector<T, N>& x, std::index_sequence<I...>) | |||
{ | |||
return {!x[I]...}; | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<bool, N> not(const vector<T, N>& x) | |||
{ | |||
return not(x, std::make_index_sequence<N>{}); | |||
} | |||
/// @private | |||
template <class T, std::size_t N, std::size_t... I> | |||
inline vector<bool, N> not_equal(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) | |||
{ | |||
return {(x[I] != y[I])...}; | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<bool, N> not_equal(const vector<T, N>& x, const vector<T, N>& y) | |||
{ | |||
return not_equal(x, y, std::make_index_sequence<N>{}); | |||
} | |||
template <std::size_t N1, class T, std::size_t N0> | |||
vector<T, N1> resize(const vector<T, N0>& v) | |||
{ | |||
vector<T, N1> resized; | |||
for (std::size_t i = 0; i < N1; ++i) | |||
{ | |||
resized[i] = (i < N0) ? v[i] : T(0); | |||
} | |||
return resized; | |||
} | |||
/// @private | |||
template <class T, std::size_t N, std::size_t... I> | |||
inline vector<T, N> sub(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) | |||
{ | |||
return {(x[I] - y[I])...}; | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<T, N> sub(const vector<T, N>& x, const vector<T, N>& y) | |||
{ | |||
return sub(x, y, std::make_index_sequence<N>{}); | |||
} | |||
template <std::size_t... Indices, class T, std::size_t N> | |||
inline vector<T, sizeof...(Indices)> swizzle(const vector<T, N>& v) | |||
{ | |||
return { v[Indices]... }; | |||
} | |||
/// @} | |||
} // namespace math | |||
#endif // ANTKEEPER_MATH_VECTOR_FUNCTIONS_HPP | |||
@ -0,0 +1,217 @@ | |||
/* | |||
* Copyright (C) 2020 Christopher J. Howard | |||
* | |||
* This file is part of Antkeeper source code. | |||
* | |||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* Antkeeper source code is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef ANTKEEPER_MATH_VECTOR_OPERATORS_HPP | |||
#define ANTKEEPER_MATH_VECTOR_OPERATORS_HPP | |||
#include "math/vector-type.hpp" | |||
#include "math/vector-functions.hpp" | |||
namespace math { | |||
namespace vector_operators { | |||
/// @addtogroup vector | |||
/// @{ | |||
/// @copydoc add(const vector<T, N>&, const vector<T, N>&) | |||
template <class T, std::size_t N> | |||
vector<T, N> operator+(const vector<T, N>& x, const vector<T, N>& y); | |||
/// @copydoc div(const vector<T, N>&, const vector<T, N>&) | |||
template <class T, std::size_t N> | |||
vector<T, N> operator/(const vector<T, N>& x, const vector<T, N>& y); | |||
/// @copydoc div(const vector<T, N>&, T) | |||
template <class T, std::size_t N> | |||
vector<T, N> operator/(const vector<T, N>& v, T s); | |||
/// @copydoc mul(const vector<T, N>&, const vector<T, N>&) | |||
template <class T, std::size_t N> | |||
vector<T, N> operator*(const vector<T, N>& x, const vector<T, N>& y); | |||
/// @copydoc mul(const vector<T, N>&, T) | |||
template <class T, std::size_t N> | |||
vector<T, N> operator*(const vector<T, N>& v, T s); | |||
/// @copydoc mul(const vector<T, N>&, T) | |||
template <class T, std::size_t N> | |||
vector<T, N> operator*(T s, const vector<T, N>& v); | |||
/// @copydoc negate(const vector<T, N>&) | |||
template <class T, std::size_t N> | |||
vector<T, N> operator-(const vector<T, N>& x); | |||
/// @copydoc sub(const vector<T, N>&, const vector<T, N>&) | |||
template <class T, std::size_t N> | |||
vector<T, N> operator-(const vector<T, N>& x, const vector<T, N>& y); | |||
/** | |||
* Adds two vectors and stores the result in the first vector. | |||
* | |||
* @param x First vector. | |||
* @param y Second vector. | |||
* @return Reference to the first vector. | |||
*/ | |||
template <class T, std::size_t N> | |||
vector<T, N>& operator+=(vector<T, N>& x, const vector<T, N>& y); | |||
/** | |||
* Subtracts two vectors and stores the result in the first vector. | |||
* | |||
* @param x First vector. | |||
* @param y Second vector. | |||
* @return Reference to the first vector. | |||
*/ | |||
template <class T, std::size_t N> | |||
vector<T, N>& operator-=(vector<T, N>& x, const vector<T, N>& y); | |||
/** | |||
* Multiplies two vectors and stores the result in the first vector. | |||
* | |||
* @param x First vector. | |||
* @param y Second vector. | |||
* @return Reference to the first vector. | |||
*/ | |||
template <class T, std::size_t N> | |||
vector<T, N>& operator*=(vector<T, N>& x, const vector<T, N>& y); | |||
/** | |||
* Multiplies a vector and a scalar and stores the result in the vector. | |||
* | |||
* @param v Vector. | |||
* @param s Scalar. | |||
* @return Reference to the vector. | |||
*/ | |||
template <class T, std::size_t N> | |||
vector<T, N>& operator*=(vector<T, N>& v, T s); | |||
/** | |||
* Divides the first vector by the second vector the result in the first vector. | |||
* | |||
* @param x First vector. | |||
* @param y Second vector. | |||
* @return Reference to the first vector. | |||
*/ | |||
template <class T, std::size_t N> | |||
vector<T, N>& operator/=(vector<T, N>& x, const vector<T, N>& y); | |||
/** | |||
* Divides a vector by a scalar and stores the result in the vector. | |||
* | |||
* @param v Vector. | |||
* @param s Scalar. | |||
* @return Reference to the vector. | |||
*/ | |||
template <class T, std::size_t N> | |||
vector<T, N>& operator/=(vector<T, N>& v, T s); | |||
template <class T, std::size_t N> | |||
inline vector<T, N> operator+(const vector<T, N>& x, const vector<T, N>& y) | |||
{ | |||
return add(x, y); | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<T, N> operator-(const vector<T, N>& x) | |||
{ | |||
return negate(x); | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<T, N> operator-(const vector<T, N>& x, const vector<T, N>& y) | |||
{ | |||
return sub(x, y); | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<T, N> operator*(const vector<T, N>& x, const vector<T, N>& y) | |||
{ | |||
return mul(x, y); | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<T, N> operator*(const vector<T, N>& v, T s) | |||
{ | |||
return mul(v, s); | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<T, N> operator*(T s, const vector<T, N>& v) | |||
{ | |||
return mul(v, s); | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<T, N> operator/(const vector<T, N>& x, const vector<T, N>& y) | |||
{ | |||
return div(x, y); | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<T, N> operator/(const vector<T, N>& v, T s) | |||
{ | |||
return div(v, s); | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<T, N>& operator+=(vector<T, N>& x, const vector<T, N>& y) | |||
{ | |||
return (x = x + y); | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<T, N>& operator-=(vector<T, N>& x, const vector<T, N>& y) | |||
{ | |||
return (x = x - y); | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<T, N>& operator*=(vector<T, N>& x, const vector<T, N>& y) | |||
{ | |||
return (x = x * y); | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<T, N>& operator*=(vector<T, N>& v, T s) | |||
{ | |||
return (v = v * s); | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<T, N>& operator/=(vector<T, N>& x, const vector<T, N>& y) | |||
{ | |||
return (x = x * y); | |||
} | |||
template <class T, std::size_t N> | |||
inline vector<T, N>& operator/=(vector<T, N>& v, T s) | |||
{ | |||
return (v = v / s); | |||
} | |||
/// @} | |||
} // namespace vector_operators | |||
} // namespace math | |||
// Bring vector operators into global namespace | |||
using namespace math::vector_operators; | |||
#endif // ANTKEEPER_MATH_VECTOR_OPERATORS_HPP | |||
@ -0,0 +1,131 @@ | |||
/* | |||
* Copyright (C) 2020 Christopher J. Howard | |||
* | |||
* This file is part of Antkeeper source code. | |||
* | |||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* Antkeeper source code is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef ANTKEEPER_MATH_VECTOR_TYPE_HPP | |||
#define ANTKEEPER_MATH_VECTOR_TYPE_HPP | |||
#include <array> | |||
#include <cstddef> | |||
namespace math { | |||
/// @addtogroup vector | |||
/// @{ | |||
/** | |||
* An `N`-dimensional Euclidean vector. | |||
* | |||
* @tparam T Vector component type. | |||
* @tparam N Number of dimensions. | |||
*/ | |||
template <typename T, std::size_t N> | |||
struct vector | |||
{ | |||
typedef T scalar_type; | |||
typedef std::array<T, N> array_type; | |||
scalar_type components[N]; | |||
inline constexpr scalar_type& operator[](std::size_t i) noexcept { return components[i]; } | |||
inline constexpr const scalar_type& operator[](std::size_t i) const noexcept { return components[i]; } | |||
inline constexpr operator array_type&() noexcept { return reinterpret_cast<array_type&>(components[0]); } | |||
inline constexpr operator const array_type&() const noexcept { return reinterpret_cast<const array_type&>(components[0]); } | |||
inline constexpr const scalar_type* data() const noexcept { return components; }; | |||
inline constexpr scalar_type* data() noexcept { return components; }; | |||
inline constexpr std::size_t size() const noexcept { return N; }; | |||
}; | |||
template <typename T> | |||
struct vector<T, 1> | |||
{ | |||
typedef T scalar_type; | |||
typedef std::array<T, 1> array_type; | |||
scalar_type x; | |||
inline constexpr scalar_type& operator[](std::size_t i) noexcept { return *((&x) + i); } | |||
inline constexpr const scalar_type& operator[](std::size_t i) const noexcept { return *((&x) + i); } | |||
inline constexpr operator array_type&() noexcept { return reinterpret_cast<array_type&>(x); } | |||
inline constexpr operator const array_type&() const noexcept { return reinterpret_cast<const array_type&>(x); } | |||
inline constexpr const scalar_type* data() const noexcept { return &x; }; | |||
inline constexpr scalar_type* data() noexcept { return &x; }; | |||
inline constexpr std::size_t size() const noexcept { return 1; }; | |||
}; | |||
template <typename T> | |||
struct vector<T, 2> | |||
{ | |||
typedef T scalar_type; | |||
typedef std::array<T, 2> array_type; | |||
scalar_type x; | |||
scalar_type y; | |||
inline constexpr scalar_type& operator[](std::size_t i) noexcept { return *((&x) + i); } | |||
inline constexpr const scalar_type& operator[](std::size_t i) const noexcept { return *((&x) + i); } | |||
inline constexpr operator array_type&() noexcept { return reinterpret_cast<array_type&>(x); } | |||
inline constexpr operator const array_type&() const noexcept { return reinterpret_cast<const array_type&>(x); } | |||
inline constexpr const scalar_type* data() const noexcept { return &x; }; | |||
inline constexpr scalar_type* data() noexcept { return &x; }; | |||
inline constexpr std::size_t size() const noexcept { return 2; }; | |||
}; | |||
template <typename T> | |||
struct vector<T, 3> | |||
{ | |||
typedef T scalar_type; | |||
typedef std::array<T, 3> array_type; | |||
scalar_type x; | |||
scalar_type y; | |||
scalar_type z; | |||
inline constexpr scalar_type& operator[](std::size_t i) noexcept { return *((&x) + i); } | |||
inline constexpr const scalar_type& operator[](std::size_t i) const noexcept { return *((&x) + i); } | |||
inline constexpr operator array_type&() noexcept { return reinterpret_cast<array_type&>(x); } | |||
inline constexpr operator const array_type&() const noexcept { return reinterpret_cast<const array_type&>(x); } | |||
inline constexpr const scalar_type* data() const noexcept { return &x; }; | |||
inline constexpr scalar_type* data() noexcept { return &x; }; | |||
inline constexpr std::size_t size() const noexcept { return 3; }; | |||
}; | |||
template <typename T> | |||
struct vector<T, 4> | |||
{ | |||
typedef T scalar_type; | |||
typedef std::array<T, 4> array_type; | |||
scalar_type x; | |||
scalar_type y; | |||
scalar_type z; | |||
scalar_type w; | |||
inline constexpr scalar_type& operator[](std::size_t i) noexcept { return *((&x) + i); } | |||
inline constexpr const scalar_type& operator[](std::size_t i) const noexcept { return *((&x) + i); } | |||
inline constexpr operator array_type&() noexcept { return reinterpret_cast<array_type&>(x); } | |||
inline constexpr operator const array_type&() const noexcept { return reinterpret_cast<const array_type&>(x); } | |||
inline constexpr const scalar_type* data() const noexcept { return &x; }; | |||
inline constexpr scalar_type* data() noexcept { return &x; }; | |||
inline constexpr std::size_t size() const noexcept { return 4; }; | |||
}; | |||
static_assert(std::is_trivial<vector<float, 4>>::value); | |||
/// @} | |||
} // namespace math | |||
#endif // ANTKEEPER_MATH_VECTOR_TYPE_HPP | |||