@ -1,103 +0,0 @@ | |||
/* | |||
* Copyright (C) 2023 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 <engine/math/transform-type.hpp> | |||
#include <engine/math/quaternion.hpp> | |||
namespace math { | |||
/** | |||
* Calculates the inverse of a transform. | |||
* | |||
* @param t Transform of which to take the inverse. | |||
*/ | |||
template <class T> | |||
[[nodiscard]] 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> | |||
[[nodiscard]] 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> | |||
[[nodiscard]] 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> | |||
[[nodiscard]] 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 = matrix<T, 4, 4>(matrix<T, 3, 3>(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)), | |||
mul(x.scale, y.scale) | |||
}; | |||
} | |||
template <class T> | |||
vector<T, 3> mul(const transform<T>& t, const vector<T, 3>& v) | |||
{ | |||
return add(t.translation, (mul(t.rotation, mul(v, t.scale)))); | |||
} | |||
} // namespace math | |||
#endif // ANTKEEPER_MATH_TRANSFORM_FUNCTIONS_HPP | |||
@ -1,63 +0,0 @@ | |||
/* | |||
* Copyright (C) 2023 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 <engine/math/transform-type.hpp> | |||
#include <engine/math/transform-functions.hpp> | |||
/// @copydoc math::mul(const math::transform<T>&, const math::transform<T>&) | |||
template <class T> | |||
[[nodiscard]] math::transform<T> operator*(const math::transform<T>& x, const math::transform<T>& y); | |||
/// @copydoc math::mul(const math::transform<T>&, const math::vector<T, 3>&) | |||
template <class T> | |||
[[nodiscard]] math::vector<T, 3> operator*(const math::transform<T>& t, const math::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> | |||
math::transform<T>& operator*=(math::transform<T>& x, const math::transform<T>& y); | |||
template <class T> | |||
inline math::transform<T> operator*(const math::transform<T>& x, const math::transform<T>& y) | |||
{ | |||
return mul(x, y); | |||
} | |||
template <class T> | |||
inline math::vector<T, 3> operator*(const math::transform<T>& t, const math::vector<T, 3>& v) | |||
{ | |||
return mul(t, v); | |||
} | |||
template <class T> | |||
inline math::transform<T>& operator*=(math::transform<T>& x, const math::vector<T, 3>& y) | |||
{ | |||
return (x = x * y); | |||
} | |||
#endif // ANTKEEPER_MATH_TRANSFORM_OPERATORS_HPP | |||
@ -1,59 +0,0 @@ | |||
/* | |||
* Copyright (C) 2023 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 <engine/math/vector.hpp> | |||
#include <engine/math/quaternion.hpp> | |||
namespace math { | |||
/** | |||
* 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; | |||
/// Identity transform. | |||
static const transform identity; | |||
}; | |||
template <class T> | |||
const transform<T> transform<T>::identity = | |||
{ | |||
vector<T, 3>::zero(), | |||
quaternion<T>::identity(), | |||
vector<T, 3>::one() | |||
}; | |||
} // namespace math | |||
#endif // ANTKEEPER_MATH_TRANSFORM_TYPE_HPP |
@ -0,0 +1,235 @@ | |||
/* | |||
* Copyright (C) 2023 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_HPP | |||
#define ANTKEEPER_MATH_TRANSFORM_HPP | |||
#include <engine/math/vector.hpp> | |||
#include <engine/math/quaternion.hpp> | |||
#include <engine/math/matrix.hpp> | |||
namespace math { | |||
/** | |||
* 3D transformation. | |||
* | |||
* Transformations are applied in the following order: scale, rotation, translation. | |||
* | |||
* @tparam T Scalar type. | |||
*/ | |||
template <class T> | |||
struct transform | |||
{ | |||
/// Scalar type. | |||
using scalar_type = T; | |||
/// Vector type. | |||
using vector_type = vector<T, 3>; | |||
/// Quaternion type. | |||
using quaternion_type = quaternion<T>; | |||
/// Transformation matrix type. | |||
using matrix_type = matrix<T, 4, 4>; | |||
/// Translation vector. | |||
vector_type translation; | |||
/// Rotation quaternion. | |||
quaternion_type rotation; | |||
/// Scale vector. | |||
vector_type scale; | |||
/** | |||
* Constructs a matrix representing the transformation. | |||
* | |||
* @return Transformation matrix. | |||
*/ | |||
/// @{ | |||
[[nodiscard]] constexpr explicit operator matrix_type() const noexcept | |||
{ | |||
matrix_type matrix = matrix_type(quaternion_type::matrix_type(rotation)); | |||
matrix[0][0] *= scale[0]; | |||
matrix[0][1] *= scale[0]; | |||
matrix[0][2] *= scale[0]; | |||
matrix[1][0] *= scale[1]; | |||
matrix[1][1] *= scale[1]; | |||
matrix[1][2] *= scale[1]; | |||
matrix[2][0] *= scale[2]; | |||
matrix[2][1] *= scale[2]; | |||
matrix[2][2] *= scale[2]; | |||
matrix[3][0] = translation[0]; | |||
matrix[3][1] = translation[1]; | |||
matrix[3][2] = translation[2]; | |||
return matrix; | |||
} | |||
[[nodiscard]] inline constexpr matrix_type matrix() const noexcept | |||
{ | |||
return matrix_type(*this); | |||
} | |||
/// @} | |||
/* | |||
* Type-casts the transform scalars using `static_cast`. | |||
* | |||
* @tparam U Target scalar type. | |||
* | |||
* @return Type-casted transform. | |||
*/ | |||
template <class U> | |||
[[nodiscard]] inline constexpr explicit operator transform<U>() const noexcept | |||
{ | |||
return {math::vector<U, 3>(translation), math::quaternion<U>(rotation), math::vector<U, 3>(scale)}; | |||
} | |||
/// Returns an identity transform. | |||
[[nodiscard]] static inline constexpr transform identity() noexcept | |||
{ | |||
return {vector_type::zero(), quaternion_type::identity(), vector_type::one()}; | |||
} | |||
}; | |||
/** | |||
* Calculates the inverse of a transform. | |||
* | |||
* @param t Transform of which to take the inverse. | |||
*/ | |||
template <class T> | |||
[[nodiscard]] transform<T> inverse(const transform<T>& t) noexcept; | |||
/** | |||
* Combines two transforms. | |||
* | |||
* @param x First transform. | |||
* @param y Second transform. | |||
* | |||
* @return Product of the two transforms. | |||
*/ | |||
template <class T> | |||
[[nodiscard]] transform<T> mul(const transform<T>& x, const transform<T>& y); | |||
/** | |||
* Transforms a vector by a transform. | |||
* | |||
* @param t Transform. | |||
* @param v Vector. | |||
* | |||
* @return Transformed vector. | |||
*/ | |||
template <class T> | |||
[[nodiscard]] constexpr vector<T, 3> mul(const transform<T>& t, const vector<T, 3>& v) noexcept; | |||
/** | |||
* Transforms a vector by the inverse of a transform. | |||
* | |||
* @param v Vector. | |||
* @param t Transform. | |||
* | |||
* @return Transformed vector. | |||
*/ | |||
template <class T> | |||
[[nodiscard]] constexpr vector<T, 3> mul(const vector<T, 3>& v, const transform<T>& t) noexcept; | |||
template <class T> | |||
transform<T> inverse(const transform<T>& t) noexcept | |||
{ | |||
transform<T> inverse_t; | |||
inverse_t.scale = T{1} / t.scale; | |||
inverse_t.rotation = conjugate(t.rotation); | |||
inverse_t.translation = -(inverse_t.rotation * t.translation); | |||
return inverse_t; | |||
} | |||
template <class T> | |||
transform<T> mul(const transform<T>& x, const transform<T>& y) | |||
{ | |||
return | |||
{ | |||
mul(x, y.translation), | |||
normalize(x.rotation * y.rotation), | |||
x.scale * y.scale | |||
}; | |||
} | |||
template <class T> | |||
constexpr vector<T, 3> mul(const transform<T>& t, const vector<T, 3>& v) noexcept | |||
{ | |||
return t.translation + t.rotation * (t.scale * v); | |||
} | |||
template <class T> | |||
inline constexpr vector<T, 3> mul(const vector<T, 3>& v, const transform<T>& t) noexcept | |||
{ | |||
return mul(inverse(t), v); | |||
} | |||
namespace operators { | |||
/// @copydoc math::mul(const math::transform<T>&, const math::transform<T>&) | |||
template <class T> | |||
[[nodiscard]] inline math::transform<T> operator*(const math::transform<T>& x, const math::transform<T>& y) | |||
{ | |||
return mul(x, y); | |||
} | |||
/// @copydoc math::mul(const math::transform<T>&, const math::vector<T, 3>&) | |||
template <class T> | |||
[[nodiscard]] inline constexpr math::vector<T, 3> operator*(const math::transform<T>& t, const math::vector<T, 3>& v) noexcept | |||
{ | |||
return mul(t, v); | |||
} | |||
/// @copydoc math::mul(const math::vector<T, 3>&, const math::transform<T>&) | |||
template <class T> | |||
[[nodiscard]] inline constexpr math::vector<T, 3> operator*(const math::vector<T, 3>& v, const math::transform<T>& t) noexcept | |||
{ | |||
return mul(v, t); | |||
} | |||
/** | |||
* Combines 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> | |||
inline math::transform<T>& operator*=(math::transform<T>& x, const math::transform<T>& y) | |||
{ | |||
return (x = x * y); | |||
} | |||
} // namespace operators | |||
} // namespace math | |||
// Bring transform operators into global namespace | |||
using namespace math::operators; | |||
#endif // ANTKEEPER_MATH_TRANSFORM_HPP |