From d2d2397c044c895755609e56aecf79dcdafa26a7 Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Fri, 15 Dec 2023 13:44:39 +0800 Subject: [PATCH] Improve vector functions --- src/engine/math/functions.hpp | 12 +- src/engine/math/matrix-constants.hpp | 4 +- src/engine/math/matrix-functions.hpp | 4 +- src/engine/math/matrix-types.hpp | 31 +- src/engine/math/vector-functions.hpp | 1901 +++++++++++------------- src/engine/math/vector-types.hpp | 25 +- src/engine/scene/object.cpp | 2 +- src/game/states/main-menu-state.cpp | 9 + src/game/systems/astronomy-system.cpp | 8 +- src/game/systems/blackbody-system.cpp | 2 +- src/game/systems/collision-system.cpp | 2 +- src/game/systems/constraint-system.cpp | 2 +- src/game/systems/terrain-system.cpp | 2 +- 13 files changed, 963 insertions(+), 1041 deletions(-) diff --git a/src/engine/math/functions.hpp b/src/engine/math/functions.hpp index 7984c1fa..6f780021 100644 --- a/src/engine/math/functions.hpp +++ b/src/engine/math/functions.hpp @@ -23,7 +23,7 @@ namespace functions { /// @{ /** - * Returns the minimum of two value. + * Returns the minimum of two values. * * @param a First value. * @param b Second value. @@ -31,13 +31,13 @@ namespace functions { * @return `a < b ? a : b`. */ template -[[nodiscard]] inline constexpr T min(T a, T b) noexcept +[[nodiscard]] inline constexpr const T& min(const T& a, const T& b) noexcept { return a < b ? a : b; } /** - * Returns the maximum of two value. + * Returns the maximum of two values. * * @param a First value. * @param b Second value. @@ -45,7 +45,7 @@ template * @return `a > b ? a : b`. */ template -[[nodiscard]] inline constexpr T max(T a, T b) noexcept +[[nodiscard]] inline constexpr const T& max(const T& a, const T& b) noexcept { return a > b ? a : b; } @@ -60,7 +60,7 @@ template * @return @p x constrained to [`min_val`, `max_val`]. */ template -[[nodiscard]] inline constexpr T clamp(T x, T min_val, T max_val) noexcept +[[nodiscard]] inline constexpr const T& clamp(const T& x, const T& min_val, const T& max_val) noexcept { return min(max(x, min_val), max_val); } @@ -524,7 +524,7 @@ template } /** - * Splits a value into its integer and fractional components. + * Splits a value into its fractional and integer components. * * @param x Value to split. * diff --git a/src/engine/math/matrix-constants.hpp b/src/engine/math/matrix-constants.hpp index 00828dd8..880e4e80 100644 --- a/src/engine/math/matrix-constants.hpp +++ b/src/engine/math/matrix-constants.hpp @@ -22,10 +22,8 @@ namespace constants { template [[nodiscard]] consteval matrix fill_matrix(const T& value) noexcept { - vector v; - v.fill(value); matrix m; - m.fill(v); + m.fill(value); return m; } diff --git a/src/engine/math/matrix-functions.hpp b/src/engine/math/matrix-functions.hpp index f9f7a7b5..c06f7230 100644 --- a/src/engine/math/matrix-functions.hpp +++ b/src/engine/math/matrix-functions.hpp @@ -492,7 +492,7 @@ constexpr matrix inverse(const matrix& m) noexcept template constexpr mat4 look_at_rh(const vec3& position, const vec3& target, const vec3& up) { - const auto f = normalize(sub(target, position)); + const auto f = normalize(target - position); const auto r = normalize(cross(f, up)); const auto u = cross(r, f); const auto t = vec3{dot(position, r), dot(position, u), dot(position, f)}; @@ -509,7 +509,7 @@ constexpr mat4 look_at_rh(const vec3& position, const vec3& target, con template constexpr std::tuple, mat4> look_at_rh_inv(const vec3& position, const vec3& target, const vec3& up) { - const auto f = normalize(sub(target, position)); + const auto f = normalize(target - position); const auto r = normalize(cross(f, up)); const auto u = cross(r, f); diff --git a/src/engine/math/matrix-types.hpp b/src/engine/math/matrix-types.hpp index e227b7e3..643b486a 100644 --- a/src/engine/math/matrix-types.hpp +++ b/src/engine/math/matrix-types.hpp @@ -304,37 +304,37 @@ struct matrix /// @{ /** Returns `true` if the matrix is empty, `false` otherwise. */ - [[nodiscard]] inline constexpr bool empty() noexcept + [[nodiscard]] inline static consteval bool empty() noexcept { return element_count; }; /** Returns the number of columns in the matrix. */ - [[nodiscard]] inline constexpr size_type size() const noexcept + [[nodiscard]] inline static consteval size_type size() noexcept { return column_count; }; /** Returns the number of columns in the matrix. */ - [[nodiscard]] inline constexpr size_type max_size() const noexcept + [[nodiscard]] inline static consteval size_type max_size() noexcept { return column_count; }; /** Returns the number of columns in the matrix. */ - [[nodiscard]] inline constexpr size_type size_columns() const noexcept + [[nodiscard]] inline static consteval size_type size_columns() noexcept { return column_count; }; /** Returns the number of rows in the matrix. */ - [[nodiscard]] inline constexpr size_type size_rows() const noexcept + [[nodiscard]] inline static consteval size_type size_rows() noexcept { return row_count; }; /** Returns the number of elements in the matrix. */ - [[nodiscard]] inline constexpr size_type size_elements() const noexcept + [[nodiscard]] inline static consteval size_type size_elements() noexcept { return element_count; }; @@ -381,6 +381,25 @@ struct matrix }; /// @} + + /// @name Comparison + /// @{ + + /** + * Tests two matrices for equality. + * + * @return `true` if the two matrices are equivalent, `false` otherwise. + */ + [[nodiscard]] inline constexpr friend bool operator==(const matrix&, const matrix&) noexcept = default; + + /** + * Compares the columns of two matrices lexicographically. + * + * @return Lexicographical ordering of the two matrices. + */ + [[nodiscard]] inline constexpr friend auto operator<=>(const matrix&, const matrix&) noexcept = default; + + /// @} }; /// @name Tuple-like interface diff --git a/src/engine/math/vector-functions.hpp b/src/engine/math/vector-functions.hpp index 87a07f51..56f9f6a6 100644 --- a/src/engine/math/vector-functions.hpp +++ b/src/engine/math/vector-functions.hpp @@ -24,509 +24,678 @@ // import ; // import ; -namespace math { -namespace functions { +/// @name Vector operators +/// @{ /** - * Returns the absolute values of each element. + * Adds two vectors. * - * @param x Input vector. + * @param lhs Vector on the left-hand side. + * @param rhs Vector on the right-hand side. * - * @return Absolute values of input vector elements. + * @return @p lhs + @p rhs. + * + * @relates math::types::vector */ template -[[nodiscard]] constexpr vector abs(const vector& x); +[[nodiscard]] inline constexpr math::vec operator+(const math::vec& lhs, const math::vec& rhs) noexcept +{ + math::vec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = lhs[i] + rhs[i]; + } + return result; +} /** - * Adds two values. + * Adds a vector and a scalar. * - * @param x First value. - * @param y Second value. + * @param lhs Vector on the left-hand side. + * @param rhs Scalar on the right-hand side. * - * @return Sum of the two values. + * @return @p lhs + @p rhs. + * + * @relates math::types::vector */ -/// @{ template -[[nodiscard]] constexpr vector add(const vector& x, const vector& y) noexcept; -template -[[nodiscard]] constexpr vector add(const vector& x, T y) noexcept; -/// @} +[[nodiscard]] inline constexpr math::vec operator+(const math::vec& lhs, const T& rhs) noexcept +{ + math::vec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = lhs[i] + rhs; + } + return result; +} /** - * Checks if all elements of a boolean vector are `true`. - * - * @param x Vector to be tested for truth. + * Adds a scalar and a vector. * - * @return `true` if all elements are `true`, `false` otherwise. - */ -template -[[nodiscard]] constexpr bool all(const vector& x) noexcept; - -/** - * Calculates the angle between two direction vectors. + * @param lhs Scalar on the left-hand side. + * @param rhs Vector on the right-hand side. * - * @param from First direction vector. - * @param to Second direction vector. + * @return @p lhs + @p rhs. * - * @return Angle between the two direction vectors, in radians. + * @relates math::types::vector */ -template -[[nodiscard]] T angle(const vector& from, const vector& to); +template +[[nodiscard]] inline constexpr math::vec operator+(const T& lhs, const math::vec& rhs) noexcept +{ + return rhs + lhs; +} /** - * Checks if any elements of a boolean vector are `true`. - * - * @param x Vector to be tested for truth. + * Negates a vector. * - * @return `true` if any elements are `true`, `false` otherwise. - */ -template -[[nodiscard]] constexpr bool any(const vector& x) noexcept; - -/** - * Performs an element-wise ceil operation. + * @param v Vector to negate. * - * @param x Input vector. + * @return `-v`. * - * @return Component-wise ceil of input vector. + * @relates math::types::vector */ -template -[[nodiscard]] constexpr vector ceil(const vector& x); +template +[[nodiscard]] inline constexpr math::vec operator-(const math::vec& v) noexcept +{ + math::vec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = -v[i]; + } + return result; +} /** - * Clamps the values of a vector's elements. + * Subtracts two vectors. * - * @param x Vector to clamp. - * @param min Minimum value. - * @param max Maximum value. + * @param lhs Vector on the left-hand side. + * @param rhs Vector on the right-hand side. * - * @return Clamped vector. + * @return @p lhs - @p rhs. + * + * @relates math::types::vector */ -/// @{ template -[[nodiscard]] constexpr vector clamp(const vector& x, const vector& min, const vector& max); -template -[[nodiscard]] constexpr vector clamp(const vector& x, T min, T max); -/// @} +[[nodiscard]] inline constexpr math::vec operator-(const math::vec& lhs, const math::vec& rhs) noexcept +{ + math::vec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = lhs[i] - rhs[i]; + } + return result; +} /** - * Clamps the length of a vector. - * - * @param x Vector to clamp. - * @param max_length Maximum length. + * Subtracts a scalar from a vector. * - * @return Length-clamped vector. - */ -template -[[nodiscard]] vector clamp_length(const vector& x, T max_length); - -/** - * Calculates the cross product of two vectors. + * @param lhs Vector on the left-hand side. + * @param rhs Scalar on the right-hand side. * - * @param x First vector. - * @param y Second vector. + * @return @p lhs - @p rhs. * - * @return Cross product of the two vectors. + * @relates math::types::vector */ -template -[[nodiscard]] constexpr vector cross(const vector& x, const vector& y) noexcept; +template +[[nodiscard]] inline constexpr math::vec operator-(const math::vec& lhs, const T& rhs) noexcept +{ + math::vec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = lhs[i] - rhs; + } + return result; +} /** - * Calculates the distance between two points. - * - * @param p0 First of two points. - * @param p1 Second of two points. + * Subtracts a vector from a scalar. * - * @return Distance between the two points. - */ -template -[[nodiscard]] T distance(const vector& p0, const vector& p1); - -/** - * Divides a vector by a value. + * @param lhs Scalar on the left-hand side. + * @param rhs Vector on the right-hand side. * - * @param x First value. - * @param y Second value. + * @return @p lhs - @p rhs. * - * @return Result of the division. + * @relates math::types::vector */ -/// @{ template -[[nodiscard]] constexpr vector div(const vector& x, const vector& y) noexcept; -template -[[nodiscard]] constexpr vector div(const vector& x, T y) noexcept; -template -[[nodiscard]] constexpr vector div(T x, const vector& y) noexcept; -/// @} +[[nodiscard]] inline constexpr math::vec operator-(const T& lhs, const math::vec& rhs) noexcept +{ + math::vec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = lhs - rhs[i]; + } + return result; +} /** - * Calculates the dot product of two vectors. + * Multiplies the elements of two vectors. * - * @param x First vector. - * @param y Second vector. + * @param lhs Vector on the left-hand side. + * @param rhs Vector on the right-hand side. * - * @return Dot product of the two vectors. + * @return @p lhs * @p rhs. + * + * @relates math::types::vector */ template -[[nodiscard]] constexpr T dot(const vector& x, const vector& y) noexcept; +[[nodiscard]] inline constexpr math::vec operator*(const math::vec& lhs, const math::vec& rhs) noexcept +{ + math::vec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = lhs[i] * rhs[i]; + } + return result; +} /** - * Compares two vectors for equality + * Multiplies a vector by a scalar. * - * @param x First vector. - * @param y Second vector. + * @param lhs Vector on the left-hand side. + * @param rhs Scalar on the right-hand side. * - * @return Boolean vector containing the result of the element comparisons. + * @return @p lhs * @p rhs. + * + * @relates math::types::vector */ template -[[nodiscard]] constexpr vector equal(const vector& x, const vector& y) noexcept; +[[nodiscard]] inline constexpr math::vec operator*(const math::vec& lhs, const T& rhs) noexcept +{ + math::vec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = lhs[i] * rhs; + } + return result; +} /** - * Performs a element-wise floor operation. - * - * @param x Input vector. + * Multiplies a scalar by a vector. * - * @return Component-wise floor of input vector. - */ -template -[[nodiscard]] constexpr vector floor(const vector& x); - -/** - * Performs a multiply-add operation. + * @param lhs Scalar on the left-hand side. + * @param rhs Vector on the right-hand side. * - * @param x Input vector - * @param y Value to multiply. - * @param z Value to add. + * @return @p lhs * @p rhs. * - * @return Vector containing the multiply-add results. + * @relates math::types::vector */ -/// @{ -template -[[nodiscard]] constexpr vector fma(const vector& x, const vector& y, const vector& z); template -[[nodiscard]] constexpr vector fma(const vector& x, T y, T z); -/// @} +[[nodiscard]] inline constexpr math::vec operator*(const T& lhs, const math::vec& rhs) noexcept +{ + return rhs * lhs; +} /** - * Returns a vector containing the fractional part of each element. + * Divides the elements of a vector by the elements of another vector. * - * @param x Input vector. + * @param lhs Vector on the left-hand side. + * @param rhs Vector on the right-hand side. * - * @return Fractional parts of input vector. + * @return @p lhs / @p rhs. + * + * @relates math::types::vector */ -template -[[nodiscard]] constexpr vector fract(const vector& x); +template +[[nodiscard]] inline constexpr math::vec operator/(const math::vec& lhs, const math::vec& rhs) noexcept +{ + math::vec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = lhs[i] / rhs[i]; + } + return result; +} /** - * Performs a element-wise greater-than comparison of two vectors. + * Divides the elements of a vector by a scalar. * - * @param x First vector. - * @param y Second vector. + * @param lhs Vector on the left-hand side. + * @param rhs Scalar on the right-hand side. * - * @return Boolean vector containing the result of the element comparisons. + * @return @p lhs / @p rhs. + * + * @relates math::types::vector */ template -[[nodiscard]] constexpr vector greater_than(const vector& x, const vector& y) noexcept; +[[nodiscard]] inline constexpr math::vec operator/(const math::vec& lhs, const T& rhs) noexcept +{ + math::vec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = lhs[i] / rhs; + } + return result; +} /** - * Performs a element-wise greater-than or equal-to comparison of two vectors. + * Divides a scalar by the elements of a vector. * - * @param x First vector. - * @param y Second vector. + * @param lhs Scalar on the left-hand side. + * @param rhs Vector on the right-hand side. * - * @return Boolean vector containing the result of the element comparisons. + * @return @p lhs / @p rhs. + * + * @relates math::types::vector */ template -[[nodiscard]] constexpr vector greater_than_equal(const vector& x, const vector& y) noexcept; +[[nodiscard]] inline constexpr math::vec operator/(const T& lhs, const math::vec& rhs) noexcept +{ + math::vec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = lhs / rhs[i]; + } + return result; +} /** - * Calculates the inverse length of a vector. + * Adds two vectors, storing the result in the first vector. * - * @param x Vector of which to calculate the inverse length. + * @param lhs Vector on the left-hand side. + * @param rhs Vector on the right-hand side. * - * @return Inverse length of the vector. + * @return @p lhs + @p rhs. + * + * @relates math::types::vector */ -template -[[nodiscard]] T inv_length(const vector& x); +template +inline constexpr math::vec& operator+=(math::vec& lhs, const math::vec& rhs) noexcept +{ + for (std::size_t i = 0; i < N; ++i) + { + lhs[i] += rhs[i]; + } + return lhs; +} /** - * Calculates the length of a vector. + * Adds a vector and a scalar, storing the result in the vector. * - * @param x Vector of which to calculate the length. + * @param lhs Scalar on the left-hand side. + * @param rhs Vector on the right-hand side. * - * @return Length of the vector. + * @return @p lhs + @p rhs. + * + * @relates math::types::vector */ -template -[[nodiscard]] T length(const vector& x); +template +inline constexpr math::vec& operator+=(math::vec& lhs, const T& rhs) noexcept +{ + for (std::size_t i = 0; i < N; ++i) + { + lhs[i] += rhs; + } + return lhs; +} /** - * Performs a element-wise less-than comparison of two vectors. + * Subtracts two vectors, storing the result in the first vector. * - * @param x First vector. - * @param y Second vector. + * @param lhs Vector on the left-hand side. + * @param rhs Vector on the right-hand side. * - * @return Boolean vector containing the result of the element comparisons. + * @return @p lhs - @p rhs. + * + * @relates math::types::vector */ template -[[nodiscard]] constexpr vector less_than(const vector& x, const vector& y) noexcept; +inline constexpr math::vec& operator-=(math::vec& lhs, const math::vec& rhs) noexcept +{ + for (std::size_t i = 0; i < N; ++i) + { + lhs[i] -= rhs[i]; + } + return lhs; +} /** - * Performs a element-wise less-than or equal-to comparison of two vectors. + * Subtracts a scalar from a vector, storing the result in the vector. * - * @param x First vector. - * @param y Second vector. + * @param lhs Vector on the left-hand side. + * @param rhs Scalar on the right-hand side. * - * @return Boolean vector containing the result of the element comparisons. + * @return @p lhs - @p rhs. + * + * @relates math::types::vector */ template -[[nodiscard]] constexpr vector less_than_equal(const vector& x, const vector& y) noexcept; +inline constexpr math::vec& operator-=(math::vec& lhs, const T& rhs) noexcept +{ + for (std::size_t i = 0; i < N; ++i) + { + lhs[i] -= rhs; + } + return lhs; +} /** - * Returns a vector containing the maximum elements of two vectors. + * Multiplies two vectors, storing the result in the first vector. * - * @param x First vector. - * @param y Second vector. + * @param lhs Vector on the left-hand side. + * @param rhs Vector on the right-hand side. * - * @return Maximum elements of the two vectors. + * @return @p lhs * @p rhs. + * + * @relates math::types::vector */ template -[[nodiscard]] constexpr vector max(const vector& x, const vector& y); +inline constexpr math::vec& operator*=(math::vec& lhs, const math::vec& rhs) noexcept +{ + for (std::size_t i = 0; i < N; ++i) + { + lhs[i] *= rhs[i]; + } + return lhs; +} /** - * Returns the value of the greatest element in a vector. + * Multiplies a vector by a scalar, storing the result in the vector. * - * @param x Input vector. + * @param lhs Vector on the left-hand side. + * @param rhs Scalar on the right-hand side. + * + * @return @p lhs * @p rhs. * - * @return Value of the greatest element in the input vector. + * @relates math::types::vector */ template -[[nodiscard]] constexpr T max(const vector& x); +inline constexpr math::vec& operator*=(math::vec& lhs, const T& rhs) noexcept +{ + for (std::size_t i = 0; i < N; ++i) + { + lhs[i] *= rhs; + } + return lhs; +} /** - * Returns a vector containing the minimum elements of two vectors. + * Divides two vectors, storing the result in the first vector. * - * @param x First vector. - * @param y Second vector. + * @param lhs Vector on the left-hand side. + * @param rhs Vector on the right-hand side. * - * @return Minimum elements of the two vectors. + * @return @p lhs / @p rhs. + * + * @relates math::types::vector */ template -[[nodiscard]] constexpr vector min(const vector& x, const vector& y); +inline constexpr math::vec& operator/=(math::vec& lhs, const math::vec& rhs) noexcept +{ + for (std::size_t i = 0; i < N; ++i) + { + lhs[i] /= rhs[i]; + } + return lhs; +} /** - * Returns the value of the smallest element in a vector. + * Divides a vector by a scalar, storing the result in the vector. * - * @param x Input vector. + * @param lhs Vector on the left-hand side. + * @param rhs Scalar on the right-hand side. * - * @return Value of the smallest element in the input vector. + * @return @p lhs / @p rhs. + * + * @relates math::types::vector */ template -[[nodiscard]] constexpr T min(const vector& x); +inline constexpr math::vec& operator/=(math::vec& lhs, const T& rhs) noexcept +{ + for (std::size_t i = 0; i < N; ++i) + { + lhs[i] /= rhs; + } + return lhs; +} /** - * Calculates the element-wise remainder of the division operation `x / y`. + * Logically inverts a Boolean vector. * - * @param x First vector. - * @param y Second vector. + * @param v Vector to invert. * - * @return Remainders of `x / y`. + * @return `!v`. + * + * @relates math::types::vector */ -/// @{ -template -[[nodiscard]] constexpr vector mod(const vector& x, const vector& y); -template -[[nodiscard]] constexpr vector mod(const vector& x, T y); +template +[[nodiscard]] inline constexpr math::bvec operator!(const math::bvec& v) noexcept +{ + math::bvec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = !v[i]; + } + return result; +} + /// @} +namespace math { +namespace functions { + +/// @name Vector relational functions +/// @{ + /** - * Multiplies two values. + * Performs an element-wise less-than comparison of two vectors. * - * @param x First value. - * @param y Second value. + * @param lhs First vector. + * @param rhs Second vector. * - * @return Product of the two values. + * @return Boolean vector containing the result of the element comparisons. */ -/// @{ template -[[nodiscard]] constexpr vector mul(const vector& x, const vector& y) noexcept; -template -[[nodiscard]] constexpr vector mul(const vector& x, T y) noexcept; -/// @} +[[nodiscard]] inline constexpr bvec less_than(const vec& lhs, const vec& rhs) noexcept +{ + bvec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = lhs[i] < rhs[i]; + } + return result; +} /** - * Negates a vector. + * Performs an element-wise less-than or equal-to comparison of two vectors. * - * @param x Vector to negate. + * @param lhs First vector. + * @param rhs Second vector. * - * @return Negated vector. + * @return Boolean vector containing the result of the element comparisons. */ template -[[nodiscard]] constexpr vector negate(const vector& x) noexcept; +[[nodiscard]] inline constexpr bvec less_than_equal(const vec& lhs, const vec& rhs) noexcept +{ + bvec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = lhs[i] <= rhs[i]; + } + return result; +} /** - * Calculates the unit vector in the same direction as the original vector. + * Performs an element-wise greater-than comparison of two vectors. * - * @param x Vector to normalize. + * @param lhs First vector. + * @param rhs Second vector. * - * @return Unit vector. + * @return Boolean vector containing the result of the element comparisons. */ -template -[[nodiscard]] vector normalize(const vector& x); +template +[[nodiscard]] inline constexpr bvec greater_than(const vec& lhs, const vec& rhs) noexcept +{ + bvec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = lhs[i] > rhs[i]; + } + return result; +} /** - * Linearly interpolates between two vectors. - * - * @tparam T Floating-point type. + * Performs an element-wise greater-than or equal-to comparison of two vectors. * - * @param a First vector. - * @param b Second vector. - * @param t Interpolation factor. + * @param lhs First vector. + * @param rhs Second vector. * - * @return `(b - a) * t + a` + * @return Boolean vector containing the result of the element comparisons. */ template -[[nodiscard]] inline constexpr vector lerp(const vector& a, const vector& b, T t) noexcept +[[nodiscard]] inline constexpr bvec greater_than_equal(const vec& lhs, const vec& rhs) noexcept { - return (b - a) * t + a; + bvec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = lhs[i] >= rhs[i]; + } + return result; } /** - * Logically inverts a boolean vector. + * Compares two vectors for equality * - * @param x Vector to be inverted. + * @param lhs First vector. + * @param rhs Second vector. * - * @return Logically inverted vector. + * @return Boolean vector containing the result of the element comparisons. */ template -[[nodiscard]] constexpr vector logical_not(const vector& x) noexcept; +[[nodiscard]] inline constexpr bvec equal(const vec& lhs, const vec& rhs) noexcept +{ + bvec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = lhs[i] == rhs[i]; + } + return result; +} /** * Compares two vectors for inequality * - * @param x First vector. - * @param y Second vector. + * @param lhs First vector. + * @param rhs Second vector. * * @return Boolean vector containing the result of the element comparisons. */ template -[[nodiscard]] constexpr vector not_equal(const vector& x, const vector& y) noexcept; - -/** - * Raises each element to a power. - * - * @param x Input vector - * @param y Exponent. - * - * @return Vector with its elements raised to the given power. - */ -/// @{ -template -[[nodiscard]] vector pow(const vector& x, const vector& y); -template -[[nodiscard]] vector pow(const vector& x, T y); -/// @} - -/** - * Performs a element-wise round operation. - * - * @param x Input vector - * - * @return Component-wise round of input vector. - */ -template -[[nodiscard]] constexpr vector round(const vector& x); - -/** - * Returns a vector containing the signs of each element. - * - * @param x Input vector - * @return Signs of input vector elements. - */ -template -[[nodiscard]] constexpr vector sign(const vector& x); +[[nodiscard]] inline constexpr bvec not_equal(const vec& lhs, const vec& rhs) noexcept +{ + bvec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = lhs[i] != rhs[i]; + } + return result; +} /** - * Calculates the signed angle between two direction vectors about axis. + * Checks if any elements of a Boolean vector are `true`. * - * @param from First direction vector. - * @param to Second direction vector. - * @param axis Axis direction vector. + * @param v Vector to be tested for truth. * - * @return Signed angle between @p from and @p to about @p axis, in radians. + * @return `true` if any elements are `true`, `false` otherwise. */ -template -[[nodiscard]] T signed_angle(const vector& x, const vector& y, const vector& n); +template +[[nodiscard]] inline constexpr bool any_of(const bvec& v) noexcept +{ + for (std::size_t i = 0; i < N; ++i) + { + if (v[i]) + { + return true; + } + } + + return false; +} /** - * Calculates the square distance between two points. The square distance can be calculated faster than the distance because a call to `std::sqrt` is saved. + * Checks if all elements of a Boolean vector are `true`. * - * @param p0 First of two points. - * @param p1 Second of two points. + * @param v Vector to be tested for truth. * - * @return Square distance between the two points. + * @return `true` if all elements are `true`, `false` otherwise. */ -template -[[nodiscard]] constexpr T sqr_distance(const vector& p0, const vector& p1) noexcept; +template +[[nodiscard]] inline constexpr bool all_of(const bvec& v) noexcept +{ + for (std::size_t i = 0; i < N; ++i) + { + if (!v[i]) + { + return false; + } + } + + return true; +} /** - * Calculates the square length of a vector. The square length can be calculated faster than the length because a call to `std::sqrt` is saved. + * Checks if all elements of a Boolean vector are `false`. * - * @param x Vector of which to calculate the square length. + * @param v Vector to be tested for truth. * - * @return Square length of the vector. + * @return `true` if all elements are `false`, `false` otherwise. */ -template -[[nodiscard]] constexpr T sqr_length(const vector& x) noexcept; +template +[[nodiscard]] inline constexpr bool none_of(const bvec& v) noexcept +{ + for (std::size_t i = 0; i < N; ++i) + { + if (v[i]) + { + return false; + } + } + + return true; +} -/** - * Takes the square root of each element. - * - * @param x Input vector - * - * @return Square roots of the input vector elements. - */ -template -[[nodiscard]] vector sqrt(const vector& x); +/// @} -/** - * Subtracts a value by another value. - * - * @param x First value. - * @param y Second value. - * - * @return Difference between the two values. - */ +/// @name Vector functions /// @{ -template -[[nodiscard]] constexpr vector sub(const vector& x, const vector& y) noexcept; -template -[[nodiscard]] constexpr vector sub(const vector& x, T y) noexcept; -template -[[nodiscard]] constexpr vector sub(T x, const vector& y) noexcept; -/// @} /** - * Calculates the sum of all elements in a vector. + * Calculates the dot product of two vectors. * - * @param x Vector to sum. - * @return Sum of the vector's elements. + * @param lhs First vector. + * @param rhs Second vector. + * + * @return Dot product of the two vectors. */ template -[[nodiscard]] constexpr T sum(const vector& x) noexcept; +[[nodiscard]] inline constexpr T dot(const vec& lhs, const vec& rhs) noexcept +{ + T result = lhs[0] * rhs[0]; + for (std::size_t i = 1; i < N; ++i) + { + result += lhs[i] * rhs[i]; + } + return result; +} /** - * Makes an *m*-dimensional vector by rearranging and/or duplicating elements of an *n*-dimensional vector. - * - * @tparam Indices List of indices of elements in @p x. - * @tparam T Vector element type. - * @tparam N Number of dimensions in @p x. + * Calculates the cross product of two vectors. * - * @param x Vector to swizzle. + * @param lhs First vector. + * @param rhs Second vector. * - * @return Vector containing elements from @p x in the order specified by @p Indices. The size of the returned vector is equivalent to the number of indices in @p Indices. + * @return Cross product of the two vectors. */ -template -[[nodiscard]] constexpr vector swizzle(const vector& x) noexcept; +template +[[nodiscard]] inline constexpr vec3 cross(const vec3& lhs, const vec3& rhs) noexcept +{ + return + { + lhs[1] * rhs[2] - lhs[2] * rhs[1], + lhs[2] * rhs[0] - lhs[0] * rhs[2], + lhs[0] * rhs[1] - lhs[1] * rhs[0] + }; +} /** * Calculates the triple product of three vectors. @@ -538,850 +707,558 @@ template * @return Triple product of the three vectors (`dot(x, cross(y, z)`). */ template -[[nodiscard]] constexpr T triple(const vector& x, const vector& y, const vector& z) noexcept; +[[nodiscard]] inline constexpr T triple(const vec3& x, const vec3& y, const vec3& z) noexcept +{ + return dot(x, cross(y, z)); +} /** - * Performs a element-wise trunc operation. + * Calculates the square length of a vector. The square length can be calculated faster than the length because a call to `std::sqrt` is saved. * - * @param x Input vector - * @return Component-wise trunc of input vector. + * @param v Vector of which to calculate the square length. + * + * @return Square length of the vector. */ -template -[[nodiscard]] constexpr vector trunc(const vector& x); - -/// @private -template -inline constexpr vector abs(const vector& x, std::index_sequence) -{ - return {std::abs(x[I])...}; -} - -template -inline constexpr vector abs(const vector& x) -{ - return abs(x, std::make_index_sequence{}); -} - -/// @private -template -inline constexpr vector add(const vector& x, const vector& y, std::index_sequence) noexcept -{ - return {(x[I] + y[I])...}; -} - -template -inline constexpr vector add(const vector& x, const vector& y) noexcept -{ - return add(x, y, std::make_index_sequence{}); -} - -/// @private -template -inline constexpr vector add(const vector& x, T y, std::index_sequence) noexcept -{ - return {(x[I] + y)...}; -} - -template -inline constexpr vector add(const vector& x, T y) noexcept -{ - return add(x, y, std::make_index_sequence{}); -} - -/// @private -template -inline constexpr bool all(const vector& x, std::index_sequence) noexcept -{ - return (x[I] && ...); -} - -template -inline constexpr bool all(const vector& x) noexcept -{ - return all(x, std::make_index_sequence{}); -} - -template -T angle(const vector& from, const vector& to) -{ - return std::acos(std::min(std::max(dot(from, to), T{-1}), T{1})); -} - -/// @private -template -inline constexpr bool any(const vector& x, std::index_sequence) noexcept -{ - return (x[I] || ...); -} - -template -inline constexpr bool any(const vector& x) noexcept -{ - return any(x, std::make_index_sequence{}); -} - -/// @private -template -inline constexpr vector ceil(const vector& x, std::index_sequence) -{ - return {std::ceil(x[I])...}; -} - -template -inline constexpr vector ceil(const vector& x) -{ - return ceil(x, std::make_index_sequence{}); -} - -/// @private -template -inline constexpr vector clamp(const vector& x, const vector& min_val, const vector& max_val, std::index_sequence) -{ - return {std::min(max_val[I], std::max(min_val[I], x[I]))...}; -} - -template -inline constexpr vector clamp(const vector& x, const vector& min, const vector& max) -{ - return clamp(x, min, max, std::make_index_sequence{}); -} - -/// @private -template -inline constexpr vector clamp(const vector& x, T min, T max, std::index_sequence) -{ - return {std::min(max, std::max(min, x[I]))...}; -} - -template -inline constexpr vector clamp(const vector& x, T min, T max) -{ - return clamp(x, min, max, std::make_index_sequence{}); -} - -template -vector clamp_length(const vector& x, T max_length) -{ - const auto length2 = sqr_length(x); - return (length2 > max_length * max_length) ? (x * (max_length / std::sqrt(length2))) : x; -} - -template -inline constexpr vector cross(const vector& x, const vector& y) noexcept -{ - return - { - x[1] * y[2] - x[2] * y[1], - x[2] * y[0] - x[0] * y[2], - x[0] * y[1] - x[1] * y[0] - }; -} - -template -inline T distance(const vector& p0, const vector& p1) -{ - return length(sub(p0, p1)); -} - -/// @private -template -inline constexpr vector div(const vector& x, const vector& y, std::index_sequence) noexcept -{ - return {(x[I] / y[I])...}; -} - -template -inline constexpr vector div(const vector& x, const vector& y) noexcept -{ - return div(x, y, std::make_index_sequence{}); -} - -/// @private -template -inline constexpr vector div(const vector& x, T y, std::index_sequence) noexcept -{ - return {(x[I] / y)...}; -} - -template -inline constexpr vector div(const vector& x, T y) noexcept -{ - return div(x, y, std::make_index_sequence{}); -} - -/// @private -template -inline constexpr vector div(T x, const vector& y, std::index_sequence) noexcept -{ - return {(x / y[I])...}; -} - -template -inline constexpr vector div(T x, const vector& y) noexcept -{ - return div(x, y, std::make_index_sequence{}); -} - -/// @private -template -inline constexpr T dot(const vector& x, const vector& y, std::index_sequence) noexcept -{ - return ((x[I] * y[I]) + ...); -} - -template -inline constexpr T dot(const vector& x, const vector& y) noexcept -{ - return dot(x, y, std::make_index_sequence{}); -} - -/// @private -template -inline constexpr vector equal(const vector& x, const vector& y, std::index_sequence) noexcept -{ - return {(x[I] == y[I])...}; -} - -template -inline constexpr vector equal(const vector& x, const vector& y) noexcept -{ - return equal(x, y, std::make_index_sequence{}); -} - -/// @private -template -inline constexpr vector floor(const vector& x, std::index_sequence) -{ - return {std::floor(x[I])...}; -} - -template -inline constexpr vector floor(const vector& x) -{ - return floor(x, std::make_index_sequence{}); -} - -/// @private -template -inline constexpr vector fma(const vector& x, const vector& y, const vector& z, std::index_sequence) -{ - return {std::fma(x[I], y[I], z[I])...}; -} - -template -inline constexpr vector fma(const vector& x, const vector& y, const vector& z) -{ - return fma(x, y, z, std::make_index_sequence{}); -} - -/// @private -template -inline constexpr vector fma(const vector& x, T y, T z, std::index_sequence) -{ - return {std::fma(x[I], y, z)...}; -} - -template -inline constexpr vector fma(const vector& x, T y, T z) -{ - return fma(x, y, z, std::make_index_sequence{}); -} - -/// @private -template -inline constexpr vector fract(const vector& x, std::index_sequence) -{ - return {x[I] - std::floor(x[I])...}; -} - -template -inline constexpr vector fract(const vector& x) -{ - return fract(x, std::make_index_sequence{}); -} - -/// @private -template -inline constexpr vector greater_than(const vector& x, const vector& y, std::index_sequence) noexcept -{ - return {(x[I] > y[I])...}; -} - -template -inline constexpr vector greater_than(const vector& x, const vector& y) noexcept -{ - return greater_than(x, y, std::make_index_sequence{}); -} - -/// @private -template -inline constexpr vector greater_than_equal(const vector& x, const vector& y, std::index_sequence) noexcept -{ - return {(x[I] >= y[I])...}; -} - template -inline constexpr vector greater_than_equal(const vector& x, const vector& y) noexcept +[[nodiscard]] inline constexpr T sqr_length(const vec& v) noexcept { - return greater_than_equal(x, y, std::make_index_sequence{}); -} - -template -inline T inv_length(const vector& x) -{ - return T{1} / length(x); -} - -template -inline T length(const vector& x) -{ - return std::sqrt(sqr_length(x)); -} - -/// @private -template -inline constexpr vector less_than(const vector& x, const vector& y, std::index_sequence) noexcept -{ - return {(x[I] < y[I])...}; -} - -template -inline constexpr vector less_than(const vector& x, const vector& y) noexcept -{ - return less_than(x, y, std::make_index_sequence{}); -} - -/// @private -template -inline constexpr vector less_than_equal(const vector& x, const vector& y, std::index_sequence) noexcept -{ - return {(x[I] <= y[I])...}; -} - -template -inline constexpr vector less_than_equal(const vector& x, const vector& y) noexcept -{ - return less_than_equal(x, y, std::make_index_sequence{}); -} - -/// @private -template -inline constexpr vector max(const vector& x, const vector& y, std::index_sequence) -{ - return {std::max(x[I], y[I])...}; -} - -template -constexpr vector max(const vector& x, const vector& y) -{ - return max(x, y, std::make_index_sequence{}); -} - -template -inline constexpr T max(const vector& x) -{ - return *std::max_element(x.elements, x.elements + N); -} - -/// @private -template -inline constexpr vector min(const vector& x, const vector& y, std::index_sequence) -{ - return {std::min(x[I], y[I])...}; -} - -template -constexpr vector min(const vector& x, const vector& y) -{ - return min(x, y, std::make_index_sequence{}); -} - -template -inline constexpr T min(const vector& x) -{ - return *std::min_element(x.elements, x.elements + N); -} - -/// @private -template -inline constexpr vector mod(const vector& x, const vector& y, std::index_sequence) -{ - return {std::fmod(x[I], y[I])...}; -} - -template -inline constexpr vector mod(const vector& x, const vector& y) -{ - return mod(x, y, std::make_index_sequence{}); -} - -/// @private -template -inline constexpr vector mod(const vector& x, T y, std::index_sequence) -{ - return {std::fmod(x[I], y)...}; -} - -template -inline constexpr vector mod(const vector& x, T y) -{ - return mod(x, y, std::make_index_sequence{}); -} - -/// @private -template -inline constexpr vector mul(const vector& x, const vector& y, std::index_sequence) noexcept -{ - return {(x[I] * y[I])...}; -} - -template -inline constexpr vector mul(const vector& x, const vector& y) noexcept -{ - return mul(x, y, std::make_index_sequence{}); -} - -/// @private -template -inline constexpr vector mul(const vector& x, T y, std::index_sequence) noexcept -{ - return {(x[I] * y)...}; -} - -template -inline constexpr vector mul(const vector& x, T y) noexcept -{ - return mul(x, y, std::make_index_sequence{}); -} - -/// @private -template -inline constexpr vector negate(const vector& x, std::index_sequence) noexcept -{ - return {(-x[I])...}; -} - -template -inline constexpr vector negate(const vector& x) noexcept -{ - return negate(x, std::make_index_sequence{}); -} - -template -inline vector normalize(const vector& x) -{ - return mul(x, inv_length(x)); -} - -/// @private -template -inline constexpr vector logical_not(const vector& x, std::index_sequence) noexcept -{ - return {!x[I]...}; -} - -template -inline constexpr vector logical_not(const vector& x) noexcept -{ - return logical_not(x, std::make_index_sequence{}); -} - -/// @private -template -inline constexpr vector not_equal(const vector& x, const vector& y, std::index_sequence) noexcept -{ - return {(x[I] != y[I])...}; -} - -template -inline constexpr vector not_equal(const vector& x, const vector& y) noexcept -{ - return not_equal(x, y, std::make_index_sequence{}); -} - -/// @private -template -inline vector pow(const vector& x, const vector& y, std::index_sequence) -{ - return {std::pow(x[I], y[I])...}; -} - -template -inline vector pow(const vector& x, const vector& y) -{ - return pow(x, y, std::make_index_sequence{}); -} - -/// @private -template -inline vector pow(const vector& x, T y, std::index_sequence) -{ - return {std::pow(x[I], y)...}; -} - -template -inline vector pow(const vector& x, T y) -{ - return pow(x, y, std::make_index_sequence{}); -} - -/// @private -template -inline constexpr vector round(const vector& x, std::index_sequence) -{ - return {std::round(x[I])...}; -} - -template -inline constexpr vector round(const vector& x) -{ - return round(x, std::make_index_sequence{}); -} - -/// @private -template -inline constexpr vector sign(const vector& x, std::index_sequence) -{ - return {std::copysign(T{1}, x[I])...}; -} - -template -inline constexpr vector sign(const vector& x) -{ - return sign(x, std::make_index_sequence{}); -} - -template -T signed_angle(const vector& from, const vector& to, const vector& axis) -{ - return std::atan2(triple(axis, from, to), dot(from, to)); -} - -template -inline constexpr T sqr_distance(const vector& p0, const vector& p1) noexcept -{ - return sqr_length(sub(p0, p1)); -} - -template -inline constexpr T sqr_length(const vector& x) noexcept -{ - return dot(x, x); -} - -/// @private -template -inline vector sqrt(const vector& x, std::index_sequence) -{ - return {std::sqrt(x[I])...}; + return dot(v, v); } +/** + * Calculates the length of a vector. + * + * @param v Vector of which to calculate the length. + * + * @return Length of the vector. + */ template -inline vector sqrt(const vector& x, const vector& y) -{ - return sqrt(x, std::make_index_sequence{}); -} - -/// @private -template -inline constexpr vector sub(const vector& x, const vector& y, std::index_sequence) noexcept +[[nodiscard]] inline T length(const vec& v) { - return {(x[I] - y[I])...}; + return std::sqrt(sqr_length(v)); } -template -inline constexpr vector sub(const vector& x, const vector& y) noexcept +/** + * Calculates the inverse length of a vector. + * + * @param v Vector of which to calculate the inverse length. + * + * @return Inverse length of the vector. + */ +template +[[nodiscard]] inline T inv_length(const vec& v) { - return sub(x, y, std::make_index_sequence{}); + return T{1} / length(v); } -/// @private -template -inline constexpr vector sub(const vector& x, T y, std::index_sequence) noexcept +/** + * Calculates the unit vector in the same direction as the original vector. + * + * @param v Vector to normalize. + * + * @return Unit vector. + */ +template +[[nodiscard]] inline vec normalize(const vec& v) { - return {(x[I] - y)...}; + return v * inv_length(v); } +/** + * Calculates the square distance between two points. The square 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 Square distance between the two points. + */ template -inline constexpr vector sub(const vector& x, T y) noexcept +[[nodiscard]] inline constexpr T sqr_distance(const vec& p0, const vec& p1) noexcept { - return sub(x, y, std::make_index_sequence{}); + return sqr_length(p0 - p1); } -/// @private -template -inline constexpr vector sub(T x, const vector& y, std::index_sequence) noexcept +/** + * 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 +[[nodiscard]] inline T distance(const vec& p0, const vec& p1) { - return {(x - y[I])...}; + return length(p0 - p1); } +/** + * Returns the absolute values of each element. + * + * @param v Input vector. + * + * @return Absolute values of input vector elements. + */ template -inline constexpr vector sub(T x, const vector& y) noexcept +[[nodiscard]] inline constexpr vec abs(const vec& v) { - return sub(x, y, std::make_index_sequence{}); -} - -/// @private -template -inline constexpr T sum(const vector& x, std::index_sequence) noexcept -{ - return (x[I] + ...); + vec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = std::abs(v[i]); + } + return result; } -template -inline constexpr T sum(const vector& x) noexcept +/** + * Calculates the angle between two direction vectors. + * + * @param from First direction vector. + * @param to Second direction vector. + * + * @return Angle between the two direction vectors, in radians. + */ +template +[[nodiscard]] inline T angle(const vec& from, const vec& to) { - return sum(x, std::make_index_sequence{}); + return std::acos(std::min(std::max(dot(from, to), T{-1}), T{1})); } -template -inline constexpr vector swizzle(const vector& x) noexcept +/** + * Performs an element-wise ceil operation. + * + * @param v Input vector. + * + * @return Component-wise ceil of input vector. + */ +template +[[nodiscard]] inline constexpr vec ceil(const vec& v) { - return {x[Indices]...}; + vec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = std::ceil(v[i]); + } + return result; } -template -inline constexpr T triple(const vector& x, const vector& y, const vector& z) noexcept +/// @{ +/** + * Clamps the values of a vector's elements. + * + * @param v Vector to clamp. + * @param min Minimum value. + * @param max Maximum value. + * + * @return Clamped vector. + */ +template +[[nodiscard]] inline constexpr vec clamp(const vec& v, const vec& min, const vec& max) noexcept { - return dot(x, cross(y, z)); + vec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = v[i] < min[i] ? min[i] : max[i] < v[i] ? max[i] : v[i]; + } + return result; } -/// @private -template -inline constexpr vector trunc(const vector& x, std::index_sequence) +template +[[nodiscard]] inline constexpr vec clamp(const vec& v, const T& min, const T& max) noexcept { - return {std::trunc(x[I])...}; + vec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = v[i] < min ? min : max < v[i] ? max : v[i]; + } + return result; } +/// @} +/** + * Clamps the length of a vector. + * + * @param v Vector to clamp. + * @param max_length Maximum length. + * + * @return Length-clamped vector. + */ template -inline constexpr vector trunc(const vector& x) +[[nodiscard]] vec clamp_length(const vec& v, T max_length) { - return trunc(x, std::make_index_sequence{}); + const auto length2 = sqr_length(v); + return (length2 > max_length * max_length) ? (v * (max_length / std::sqrt(length2))) : v; } -} // namespace functions - -// Bring math::functions into math namespace -using namespace functions; - -} // namespace math - -/// @copydoc math::add(const vector&, const vector&) -template -[[nodiscard]] inline constexpr math::vector operator+(const math::vector& x, const math::vector& y) noexcept +/** + * Performs an element-wise floor operation. + * + * @param v Input vector. + * + * @return Component-wise floor of input vector. + */ +template +[[nodiscard]] inline constexpr vec floor(const vec& v) { - return math::add(x, y); + vec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = std::floor(v[i]); + } + return result; } -/// @copydoc math::add(const vector&, T) /// @{ +/** + * Performs a multiply-add operation. + * + * @param x Input vector + * @param y Value to multiply. + * @param z Value to add. + * + * @return Vector containing the multiply-add results. + */ template -[[nodiscard]] inline constexpr math::vector operator+(const math::vector& x, T y) noexcept +[[nodiscard]] inline constexpr vec fma(const vec& x, const vec& y, const vec& z) { - return math::add(x, y); + vec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = std::fma(x[i], y[i], z[i]); + } + return result; } + template -[[nodiscard]] inline constexpr math::vector operator+(T x, const math::vector& y) noexcept +[[nodiscard]] inline constexpr vec fma(const vec& x, T y, T z) { - return math::add(y, x); + vec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = std::fma(x[i], y, z); + } + return result; } /// @} -/// @copydoc math::div(const vector&, const vector&) -template -[[nodiscard]] inline constexpr math::vector operator/(const math::vector& x, const math::vector& y) noexcept +/** + * Returns a vector containing the fractional part of each element. + * + * @param v Input vector. + * + * @return Fractional parts of input vector. + */ +template +[[nodiscard]] inline constexpr vec fract(const vec& v) { - return math::div(x, y); + vec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = v[i] - std::floor(v[i]); + } + return result; } -/// @copydoc math::div(const vector&, T) +/** + * Returns a vector containing the minimum elements of two vectors. + * + * @param x First vector. + * @param y Second vector. + * + * @return Minimum elements of the two vectors. + */ template -[[nodiscard]] inline constexpr math::vector operator/(const math::vector& x, T y) noexcept +[[nodiscard]] inline constexpr vec min(const vec& x, const vec& y) noexcept { - return math::div(x, y); + vec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = y[i] < x[i] ? y[i] : x[i]; + } + return result; } -/// @copydoc math::div(T, const vector&) +/** + * Returns a vector containing the maximum elements of two vectors. + * + * @param x First vector. + * @param y Second vector. + * + * @return Maximum elements of the two vectors. + */ template -[[nodiscard]] inline constexpr math::vector operator/(T x, const math::vector& y) noexcept +[[nodiscard]] inline constexpr vec max(const vec& x, const vec& y) noexcept { - return math::div(x, y); + vec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = x[i] < y[i] ? y[i] : x[i]; + } + return result; } -/// @copydoc math::mul(const vector&, const vector&) +/** + * Returns a reference to the smallest element in a vector. + * + * @param v Input vector. + * + * @return Reference to the smallest element in @p v. + */ template -[[nodiscard]] inline constexpr math::vector operator*(const math::vector& x, const math::vector& y) noexcept +[[nodiscard]] constexpr const T& min_element(const vec& v) noexcept { - return math::mul(x, y); + const T* result = &v[0]; + for (std::size_t i = 1; i < N; ++i) + { + if (*result > v[i]) + { + result = &v[i]; + } + } + return *result; } -/// @copydoc math::mul(const vector&, T) -/// @{ -template -[[nodiscard]] inline constexpr math::vector operator*(const math::vector& x, T y) noexcept -{ - return math::mul(x, y); -} +/** + * Returns a reference to the greatest element in a vector. + * + * @param v Input vector. + * + * @return Reference to the greatest element in @p v. + */ template -[[nodiscard]] inline constexpr math::vector operator*(T x, const math::vector& y) noexcept +[[nodiscard]] inline constexpr const T& max_element(const vec& v) noexcept { - return math::mul(y, x); + const T* result = &v[0]; + for (std::size_t i = 1; i < N; ++i) + { + if (*result < v[i]) + { + result = &v[i]; + } + } + return *result; } -/// @} -/// @copydoc math::negate(const vector&) -template -[[nodiscard]] inline constexpr math::vector operator-(const math::vector& x) noexcept +/// @{ +/** + * Calculates the element-wise remainder of the division operation `lhs / rhs`. + * + * @param lhs Left-hand side. + * @param rhs Right-hand side. + * + * @return Remainders of `lhs / rhs`. + */ +template +[[nodiscard]] constexpr vec mod(const vec& lhs, const vec& rhs) { - return math::negate(x); + vec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = std::fmod(lhs[i], rhs[i]); + } + return result; } -/// @copydoc math::sub(const vector&, const vector&) -template -[[nodiscard]] inline constexpr math::vector operator-(const math::vector& x, const math::vector& y) noexcept +template +[[nodiscard]] constexpr vec mod(const vec& lhs, T rhs) { - return math::sub(x, y); + vec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = std::fmod(lhs[i], rhs); + } + return result; } -/// @copydoc math::sub(const vector&, T) -template -[[nodiscard]] inline constexpr math::vector operator-(const math::vector& x, T y) noexcept +template +[[nodiscard]] constexpr vec mod(T lhs, const vec& rhs) { - return math::sub(x, y); + vec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = std::fmod(lhs, rhs[i]); + } + return result; } +/// @} -/// @copydoc math::sub(T, const vector&) +/** + * Linearly interpolates between two vectors. + * + * @tparam T Floating-point type. + * + * @param a First vector. + * @param b Second vector. + * @param t Interpolation factor. + * + * @return `(b - a) * t + a` + */ template -[[nodiscard]] inline constexpr math::vector operator-(T x, const math::vector& y) noexcept +[[nodiscard]] inline constexpr vec lerp(const vec& a, const vec& b, T t) noexcept { - return math::sub(x, y); + return (b - a) * t + a; } +/// @{ /** - * Adds two values and stores the result in the first value. + * Raises each element to a power. * - * @param x First value. - * @param y Second value. + * @param x Input vector. + * @param y Exponent. * - * @return Reference to the first value. + * @return Vector with its elements raised to the given power. */ -/// @{ -template -inline constexpr math::vector& operator+=(math::vector& x, const math::vector& y) noexcept +template +[[nodiscard]] inline vec pow(const vec& x, const vec& y) { - return (x = x + y); + vec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = std::pow(x[i], y[i]); + } + return result; } -template -inline constexpr math::vector& operator+=(math::vector& x, T y) noexcept + +template +[[nodiscard]] inline vec pow(const vec& x, T y) { - return (x = x + y); + vec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = std::pow(x[i], y); + } + return result; } /// @} /** - * Subtracts the first value by the second value and stores the result in the first value. + * Performs an element-wise round operation. * - * @param x First value. - * @param y Second value. + * @param v Input vector * - * @return Reference to the first value. + * @return Component-wise round of input vector. */ -/// @{ -template -inline constexpr math::vector& operator-=(math::vector& x, const math::vector& y) noexcept -{ - return (x = x - y); -} -template -inline constexpr math::vector& operator-=(math::vector& x, T y) noexcept +template +[[nodiscard]] inline constexpr vec round(const vec& v) { - return (x = x - y); + vec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = std::round(v[i]); + } + return result; } -/// @} /** - * Multiplies two values and stores the result in the first value. + * Returns a vector containing the signs of each element. * - * @param x First value. - * @param y Second value. + * @param v Input vector * - * @return Reference to the first value. + * @return Signs of input vector elements. */ -/// @{ -template -inline constexpr math::vector& operator*=(math::vector& x, const math::vector& y) noexcept +template +[[nodiscard]] inline constexpr vec sign(const vec& v) { - return (x = x * y); + vec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = std::copysign(T{1}, v[i]); + } + return result; } -template -inline constexpr math::vector& operator*=(math::vector& x, T y) noexcept + +/** + * Calculates the signed angle between two direction vectors about axis. + * + * @param from First direction vector. + * @param to Second direction vector. + * @param axis Axis direction vector. + * + * @return Signed angle between @p from and @p to about @p axis, in radians. + */ +template +[[nodiscard]] inline T signed_angle(const vec3& from, const vec3& to, const vec3& axis) { - return (x = x * y); + return std::atan2(triple(axis, from, to), dot(from, to)); } -/// @} /** - * Divides the first value by the second value and stores the result in the first value. + * Takes the square root of each element. * - * @param x First value. - * @param y Second value. + * @param v Input vector * - * @return Reference to the first value. + * @return Square roots of the input vector elements. */ -/// @{ -template -inline constexpr math::vector& operator/=(math::vector& x, const math::vector& y) noexcept +template +[[nodiscard]] inline vec sqrt(const vec& v) { - return (x = x / y); + vec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = std::sqrt(v[i]); + } + return result; } + +/** + * Calculates the sum of all elements in a vector. + * + * @param x Vector to sum. + * @return Sum of the vector's elements. + */ template -inline constexpr math::vector& operator/=(math::vector& x, T y) noexcept +[[nodiscard]] inline constexpr T sum(const vec& v) noexcept { - return (x = x / y); + T result = v[0]; + for (std::size_t i = 1; i < N; ++i) + { + result += v[i]; + } + return result; } -/// @} /** - * Tests two vector for equality + * Makes an *m*-dimensional vector by rearranging and/or duplicating elements of an *n*-dimensional vector. + * + * @tparam Indices List of indices of elements in @p v. + * @tparam T Vector element type. + * @tparam N Number of dimensions in @p v. * - * @param x First value. - * @param y Second value. + * @param v Vector to swizzle. * - * @return `true` if the vectors are identical, `false` otherwise. + * @return Vector containing elements from @p v in the order specified by @p Indices. The size of the returned vector is equivalent to the number of indices in @p Indices. */ -template -[[nodiscard]] inline constexpr bool operator==(const math::vector& x, const math::vector& y) noexcept +template +[[nodiscard]] inline constexpr vec swizzle(const vec& v) noexcept { - // if consteval - // { - for (std::size_t i = 0; i < N; ++i) - { - if (x[i] != y[i]) - { - return false; - } - } - - return true; - // } - // else - // { - // !std::memcmp(x.data(), y.data(), N * sizeof(T)); - // } + return {v[Indices]...}; } /** - * Tests two vector for inequality + * Performs an element-wise trunc operation. * - * @param x First value. - * @param y Second value. + * @param v Input vector * - * @return `false` if the vectors are identical, `true` otherwise. + * @return Component-wise trunc of input vector. */ -template -[[nodiscard]] inline constexpr bool operator!=(const math::vector& x, const math::vector& y) noexcept +template +[[nodiscard]] inline constexpr vec trunc(const vec& v) { - return !(x == y); + vec result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = std::trunc(v[i]); + } + return result; } +/// @} + +} // namespace functions + +// Bring math::functions into math namespace +using namespace functions; + +} // namespace math + #endif // ANTKEEPER_MATH_VECTOR_FUNCTIONS_HPP diff --git a/src/engine/math/vector-types.hpp b/src/engine/math/vector-types.hpp index 530d0fc7..88ddd928 100644 --- a/src/engine/math/vector-types.hpp +++ b/src/engine/math/vector-types.hpp @@ -277,19 +277,19 @@ struct vector /// @{ /** Returns `true` if the vector is empty, `false` otherwise. */ - [[nodiscard]] inline static constexpr bool empty() noexcept + [[nodiscard]] inline static consteval bool empty() noexcept { return N; }; /** Returns the number of elements in the vector. */ - [[nodiscard]] inline static constexpr size_type size() noexcept + [[nodiscard]] inline static consteval size_type size() noexcept { return N; }; /** Returns the number of elements in the vector. */ - [[nodiscard]] inline static constexpr size_type max_size() noexcept + [[nodiscard]] inline static consteval size_type max_size() noexcept { return N; }; @@ -323,6 +323,25 @@ struct vector }; /// @} + + /// @name Comparison + /// @{ + + /** + * Tests two vectors for equality. + * + * @return `true` if the two vectors are equivalent, `false` otherwise. + */ + [[nodiscard]] inline constexpr friend bool operator==(const vector&, const vector&) noexcept = default; + + /** + * Compares the elements of two vectors lexicographically. + * + * @return Lexicographical ordering of the two vectors. + */ + [[nodiscard]] inline constexpr friend auto operator<=>(const vector&, const vector&) noexcept = default; + + /// @} }; /// @name Tuple-like interface diff --git a/src/engine/scene/object.cpp b/src/engine/scene/object.cpp index 50835799..714b16b8 100644 --- a/src/engine/scene/object.cpp +++ b/src/engine/scene/object.cpp @@ -14,7 +14,7 @@ std::size_t object_base::next_object_type_id() void object_base::look_at(const vector_type& position, const vector_type& target, const vector_type& up) { m_transform.translation = position; - m_transform.rotation = math::look_rotation(math::normalize(math::sub(target, position)), up); + m_transform.rotation = math::look_rotation(math::normalize(target - position), up); transformed(); } diff --git a/src/game/states/main-menu-state.cpp b/src/game/states/main-menu-state.cpp index c28f6dde..9a586118 100644 --- a/src/game/states/main-menu-state.cpp +++ b/src/game/states/main-menu-state.cpp @@ -275,6 +275,15 @@ main_menu_state::main_menu_state(::game& ctx, bool fade_in): ctx.function_queue.push(std::bind(::enable_menu_controls, std::ref(ctx))); debug::log_trace("Entered main menu state"); + + using namespace math; + ivec3 a{0, 1, 2}; + ivec3 b{0, 1, 2}; + + debug::log_debug("a < b: {}", static_cast(a < b)); + debug::log_debug("a > b: {}", static_cast(a > b)); + debug::log_debug("a == b: {}", static_cast(a == b)); + debug::log_debug("a != b: {}", static_cast(a != b)); } main_menu_state::~main_menu_state() diff --git a/src/game/systems/astronomy-system.cpp b/src/game/systems/astronomy-system.cpp index b3e797d1..476d31b4 100644 --- a/src/game/systems/astronomy-system.cpp +++ b/src/game/systems/astronomy-system.cpp @@ -187,9 +187,9 @@ void astronomy_system::update(float t, float dt) ) ); - sun_light->set_illuminance(static_cast(math::max(observer_blackbody_transmitted_illuminance))); + sun_light->set_illuminance(static_cast(math::max_element(observer_blackbody_transmitted_illuminance))); - const auto max_component = math::max(observer_blackbody_transmitted_illuminance); + const auto max_component = math::max_element(observer_blackbody_transmitted_illuminance); if (max_component > 0.0) { sun_light->set_color(math::fvec3(observer_blackbody_transmitted_illuminance / max_component)); @@ -282,9 +282,9 @@ void astronomy_system::update(float t, float dt) { const math::fvec3 reflector_up_eus = math::fvec3(icrf_to_eus.r * math::dvec3{0, 0, 1}); - moon_light->set_illuminance(static_cast(math::max(observer_reflector_illuminance))); + moon_light->set_illuminance(static_cast(math::max_element(observer_reflector_illuminance))); - const auto max_component = math::max(observer_reflector_illuminance); + const auto max_component = math::max_element(observer_reflector_illuminance); if (max_component > 0.0) { moon_light->set_color(math::fvec3(observer_reflector_illuminance / max_component)); diff --git a/src/game/systems/blackbody-system.cpp b/src/game/systems/blackbody-system.cpp index 098b6007..c1df26ca 100644 --- a/src/game/systems/blackbody-system.cpp +++ b/src/game/systems/blackbody-system.cpp @@ -58,7 +58,7 @@ void blackbody_system::update_blackbody(entity::id entity_id) const math::dvec3 rgb_luminance = math::simpson(rgb_spectral_luminance, m_visible_wavelengths_nm.begin(), m_visible_wavelengths_nm.end()); // Extract luminance and color from RGB luminance - blackbody.luminance = math::max(rgb_luminance); + blackbody.luminance = math::max_element(rgb_luminance); blackbody.color = rgb_luminance / blackbody.luminance; } diff --git a/src/game/systems/collision-system.cpp b/src/game/systems/collision-system.cpp index 115aacd9..b8d6b34a 100644 --- a/src/game/systems/collision-system.cpp +++ b/src/game/systems/collision-system.cpp @@ -42,7 +42,7 @@ entity::id collision_system::pick_nearest(const geom::ray& ray, std::u const geom::sphere sphere = { transform.world * picking.sphere.center, - picking.sphere.radius * math::max(transform.world.scale) + picking.sphere.radius * math::max_element(transform.world.scale) }; // Test for intersection between ray and sphere diff --git a/src/game/systems/constraint-system.cpp b/src/game/systems/constraint-system.cpp index 5858656e..4426eb5b 100644 --- a/src/game/systems/constraint-system.cpp +++ b/src/game/systems/constraint-system.cpp @@ -326,7 +326,7 @@ void constraint_system::handle_track_to_constraint(transform_component& transfor const transform_component* target_transform = registry.try_get(constraint.target); if (target_transform) { - transform.world.rotation = math::look_rotation(math::normalize(math::sub(target_transform->world.translation, transform.world.translation)), constraint.up); + transform.world.rotation = math::look_rotation(math::normalize(target_transform->world.translation - transform.world.translation), constraint.up); } } } diff --git a/src/game/systems/terrain-system.cpp b/src/game/systems/terrain-system.cpp index 770b5c91..d80f4c8c 100644 --- a/src/game/systems/terrain-system.cpp +++ b/src/game/systems/terrain-system.cpp @@ -74,7 +74,7 @@ entity::id terrain_system::generate(std::shared_ptr heightmap, con const auto cell_quad_dimensions = math::uvec2{static_cast(heightmap_dimensions[0] - 1) / grid.dimensions.x(), static_cast(heightmap_dimensions[1] - 1) / grid.dimensions.y()}; const auto cell_vert_dimensions = cell_quad_dimensions + 1u; - const auto max_scale = math::max(transform.scale); + const auto max_scale = math::max_element(transform.scale); const auto scale_ratio = transform.scale / max_scale; const auto vertex_scale = scale_ratio * math::fvec3{2.0f / static_cast(cell_quad_dimensions.x()), 2.0f, 2.0f / static_cast(cell_quad_dimensions.y())}; const auto vertex_translation = -scale_ratio;