@ -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 | |||||