/* * 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 . */ #ifndef ANTKEEPER_MATH_TRANSFORM_HPP #define ANTKEEPER_MATH_TRANSFORM_HPP #include #include #include namespace math { /** * SRT transformation. * * @tparam T Scalar type. */ template struct transform { /// Scalar type. using scalar_type = T; /// Vector type. using vector_type = vec3; /// Quaternion type. using quaternion_type = quat; /// Transformation matrix type. using matrix_type = mat4; /// 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 [[nodiscard]] inline constexpr explicit operator transform() const noexcept { return {vec3(translation), quat(rotation), vec3(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 [[nodiscard]] transform inverse(const transform& t) noexcept; /** * Combines two transforms. * * @param x First transform. * @param y Second transform. * * @return Product of the two transforms. */ template [[nodiscard]] transform mul(const transform& x, const transform& y); /** * Transforms a vector by a transform. * * @param t Transform. * @param v Vector. * * @return Transformed vector. */ template [[nodiscard]] constexpr vector mul(const transform& t, const vector& v) noexcept; /** * Transforms a vector by the inverse of a transform. * * @param v Vector. * @param t Transform. * * @return Transformed vector. */ template [[nodiscard]] constexpr vector mul(const vector& v, const transform& t) noexcept; template transform inverse(const transform& t) noexcept { return {-t.translation * t.rotation, conjugate(t.rotation), T{1} / t.scale}; } template transform mul(const transform& x, const transform& y) { return { mul(x, y.translation), normalize(x.rotation * y.rotation), x.scale * y.scale }; } template constexpr vector mul(const transform& t, const vector& v) noexcept { return t.translation + t.rotation * (t.scale * v); } template inline constexpr vector mul(const vector& v, const transform& t) noexcept { return mul(inverse(t), v); } namespace operators { /// @copydoc math::mul(const math::transform&, const math::transform&) template [[nodiscard]] inline math::transform operator*(const math::transform& x, const math::transform& y) { return mul(x, y); } /// @copydoc math::mul(const math::transform&, const math::vec3&) template [[nodiscard]] inline constexpr math::vec3 operator*(const math::transform& t, const math::vec3& v) noexcept { return mul(t, v); } /// @copydoc math::mul(const math::vec3&, const math::transform&) template [[nodiscard]] inline constexpr math::vec3 operator*(const math::vec3& v, const math::transform& 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 inline math::transform& operator*=(math::transform& x, const math::transform& y) { return (x = x * y); } } // namespace operators } // namespace math // Bring transform operators into global namespace using namespace math::operators; #endif // ANTKEEPER_MATH_TRANSFORM_HPP