diff --git a/src/entity/commands.cpp b/src/entity/commands.cpp index 4ad4faa..2c141b1 100644 --- a/src/entity/commands.cpp +++ b/src/entity/commands.cpp @@ -157,7 +157,7 @@ void place(entity::registry& registry, entity::id eid, entity::id celestial_body } game::component::transform& transform = registry.get(eid); - transform.local.translation = math::type_cast(double3{x, y, z}); + transform.local.translation = math::vector(double3{x, y, z}); transform.warp = true; } */ diff --git a/src/game/state/splash.cpp b/src/game/state/splash.cpp index 616c41d..e69d9fc 100644 --- a/src/game/state/splash.cpp +++ b/src/game/state/splash.cpp @@ -29,6 +29,8 @@ #include "debug/logger.hpp" #include "resources/resource-manager.hpp" #include "render/material-flags.hpp" +#include "math/matrix.hpp" +#include namespace game { namespace state { diff --git a/src/game/system/astronomy.cpp b/src/game/system/astronomy.cpp index dbcdbd0..098a3dd 100644 --- a/src/game/system/astronomy.cpp +++ b/src/game/system/astronomy.cpp @@ -157,7 +157,7 @@ void astronomy::update(double t, double dt) // Update local transform if (orbit.parent != entt::null) { - transform.local.translation = math::normalize(math::type_cast(r_eus)); + transform.local.translation = math::normalize(float3(r_eus)); transform.local.rotation = math::type_cast(rotation_eus); transform.local.scale = {1.0f, 1.0f, 1.0f}; } @@ -206,12 +206,12 @@ void astronomy::update(double t, double dt) ( math::look_rotation ( - math::type_cast(-observer_blackbody_direction_eus), - math::type_cast(blackbody_up_eus) + float3(-observer_blackbody_direction_eus), + float3(blackbody_up_eus) ) ); - sun_light->set_color(math::type_cast(observer_blackbody_transmitted_illuminance)); + sun_light->set_color(float3(observer_blackbody_transmitted_illuminance)); // Bounce sun light bounce_illuminance += std::max(0.0, math::dot(bounce_normal, -observer_blackbody_direction_eus)) * observer_blackbody_transmitted_illuminance * bounce_albedo; @@ -231,7 +231,7 @@ void astronomy::update(double t, double dt) sky_light_illuminance += starlight_illuminance; // Update sky light - sky_light->set_color(math::type_cast(sky_light_illuminance)); + sky_light->set_color(float3(sky_light_illuminance)); // Bounce sky light bounce_illuminance += sky_light_illuminance * bounce_albedo; @@ -240,9 +240,9 @@ void astronomy::update(double t, double dt) // Upload blackbody params to sky pass if (this->sky_pass) { - this->sky_pass->set_sun_position(math::type_cast(blackbody_position_eus)); - this->sky_pass->set_sun_luminance(math::type_cast(blackbody.luminance)); - this->sky_pass->set_sun_illuminance(math::type_cast(observer_blackbody_illuminance), math::type_cast(observer_blackbody_transmitted_illuminance)); + this->sky_pass->set_sun_position(float3(blackbody_position_eus)); + this->sky_pass->set_sun_luminance(float3(blackbody.luminance)); + this->sky_pass->set_sun_illuminance(float3(observer_blackbody_illuminance), float3(observer_blackbody_transmitted_illuminance)); this->sky_pass->set_sun_angular_radius(static_cast(observer_blackbody_angular_radius)); } @@ -308,23 +308,23 @@ void astronomy::update(double t, double dt) this->sky_pass->set_moon_position(transform.local.translation); this->sky_pass->set_moon_rotation(transform.local.rotation); this->sky_pass->set_moon_angular_radius(static_cast(observer_reflector_angular_radius)); - this->sky_pass->set_moon_sunlight_direction(math::type_cast(-reflector_blackbody_direction_eus)); - this->sky_pass->set_moon_sunlight_illuminance(math::type_cast(reflector_blackbody_illuminance * observer_reflector_transmittance)); - this->sky_pass->set_moon_planetlight_direction(math::type_cast(observer_reflector_direction_eus)); - this->sky_pass->set_moon_planetlight_illuminance(math::type_cast(reflector_observer_illuminance * observer_reflector_transmittance)); - this->sky_pass->set_moon_illuminance(math::type_cast(observer_reflector_illuminance / observer_reflector_transmittance), math::type_cast(observer_reflector_illuminance)); + this->sky_pass->set_moon_sunlight_direction(float3(-reflector_blackbody_direction_eus)); + this->sky_pass->set_moon_sunlight_illuminance(float3(reflector_blackbody_illuminance * observer_reflector_transmittance)); + this->sky_pass->set_moon_planetlight_direction(float3(observer_reflector_direction_eus)); + this->sky_pass->set_moon_planetlight_illuminance(float3(reflector_observer_illuminance * observer_reflector_transmittance)); + this->sky_pass->set_moon_illuminance(float3(observer_reflector_illuminance / observer_reflector_transmittance), float3(observer_reflector_illuminance)); } if (this->moon_light) { - const float3 reflector_up_eus = math::type_cast(icrf_to_eus.r * double3{0, 0, 1}); + const float3 reflector_up_eus = float3(icrf_to_eus.r * double3{0, 0, 1}); - this->moon_light->set_color(math::type_cast(observer_reflector_illuminance)); + this->moon_light->set_color(float3(observer_reflector_illuminance)); this->moon_light->set_rotation ( math::look_rotation ( - math::type_cast(-observer_reflector_direction_eus), + float3(-observer_reflector_direction_eus), reflector_up_eus ) ); @@ -337,7 +337,7 @@ void astronomy::update(double t, double dt) if (bounce_light) { - bounce_light->set_color(math::type_cast(bounce_illuminance)); + bounce_light->set_color(float3(bounce_illuminance)); } } @@ -580,7 +580,7 @@ void astronomy::update_icrf_to_eus(const game::component::celestial_body& body, ( math::transformation::se3 { - math::type_cast(icrf_to_eus.t), + float3(icrf_to_eus.t), math::type_cast(icrf_to_eus.r) } ); diff --git a/src/game/system/atmosphere.cpp b/src/game/system/atmosphere.cpp index b03761d..22874e3 100644 --- a/src/game/system/atmosphere.cpp +++ b/src/game/system/atmosphere.cpp @@ -143,10 +143,10 @@ void atmosphere::update_sky_pass() return; sky_pass->set_atmosphere_upper_limit(static_cast(component->upper_limit)); - sky_pass->set_rayleigh_parameters(static_cast(component->rayleigh_scale_height), math::type_cast(component->rayleigh_scattering)); + sky_pass->set_rayleigh_parameters(static_cast(component->rayleigh_scale_height), math::vector(component->rayleigh_scattering)); sky_pass->set_mie_parameters(static_cast(component->mie_scale_height), static_cast(component->mie_scattering), static_cast(component->mie_extinction), static_cast(component->mie_anisotropy)); - sky_pass->set_ozone_parameters(static_cast(component->ozone_lower_limit), static_cast(component->ozone_upper_limit), static_cast(component->ozone_mode), math::type_cast(component->ozone_absorption)); - sky_pass->set_airglow_illuminance(math::type_cast(component->airglow_illuminance)); + sky_pass->set_ozone_parameters(static_cast(component->ozone_lower_limit), static_cast(component->ozone_upper_limit), static_cast(component->ozone_mode), math::vector(component->ozone_absorption)); + sky_pass->set_airglow_illuminance(math::vector(component->airglow_illuminance)); } void atmosphere::on_atmosphere_construct(entity::registry& registry, entity::id entity_id) diff --git a/src/geom/plane.hpp b/src/geom/plane.hpp index fb8b236..4fa408e 100644 --- a/src/geom/plane.hpp +++ b/src/geom/plane.hpp @@ -99,7 +99,7 @@ plane::plane(const vector_type& a, const vector_type& b, const vector_type& c template plane::plane(const math::vector& coefficients) { - const vector_type abc = math::resize<3>(coefficients); + const vector_type abc = math::vector(coefficients); const float inverse_length = T(1) / math::length(abc); normal = abc * inverse_length; diff --git a/src/math/matrix.hpp b/src/math/matrix.hpp index 2c83a4f..4d46974 100644 --- a/src/math/matrix.hpp +++ b/src/math/matrix.hpp @@ -134,7 +134,7 @@ struct matrix /** * Returns a pointer to the first element. * - * @warning If column_vector_type is not a POD type, elements may not be stored contiguously. + * @warning If matrix::element_type is not a POD type, elements may not be stored contiguously. */ /// @{ constexpr inline element_type* data() noexcept @@ -242,18 +242,18 @@ struct matrix constexpr inline matrix size_cast(std::index_sequence) const noexcept { if constexpr (O == M) - return {((I < N) ? columns[I] : vector::zero()) ...}; + return {((I < N) ? columns[I] : matrix::identity()[I]) ...}; else - return {((I < N) ? vector(columns[I]) : vector::zero()) ...}; + return {((I < N) ? vector(columns[I]) : matrix::identity()[I]) ...}; } /** - * Size-casts this matrix to a matrix with different dimensions. Casting to greater dimensions causes new elements to be set to zero. + * Size-casts this matrix to a matrix with different dimensions. Casting to greater dimensions causes new elements to be set to identity matrix elements. * * @tparam P Target number of columns. * @tparam O Target number of rows. * - * @return *p by *o* matrix. + * @return *p* by *o* matrix. */ template constexpr inline explicit operator matrix() const noexcept @@ -331,63 +331,48 @@ using matrix4x4 = matrix; /** * Adds two matrices. * - * @param x First matrix. - * @param y Second matrix. + * @param a First matrix. + * @param b Second matrix. + * * @return Sum of the two matrices. */ -template -constexpr matrix add(const matrix& x, const matrix& y); - -/// @copydoc add(const matrix&, const matrix&) -template -constexpr matrix add(const matrix& x, const matrix& y); - -/// @copydoc add(const matrix&, const matrix&) -template -constexpr matrix add(const matrix& x, const matrix& y); +template +constexpr matrix add(const matrix& a, const matrix& b) noexcept; /** - * Reinterprets data as an `NxM` matrix of type `T`. + * Adds a matrix and a scalar. * - * @tparam N Number of columns. - * @tparam M Number of rows. - * @tparam T Element type. - * @param data Data to reinterpret. + * @param a Matrix. + * @param b scalar. + * + * @return Sum of the matrix and scalar. */ -template -constexpr matrix& as_matrix(T& data); +template +constexpr matrix add(const matrix& a, T b) noexcept; /** - * Calculates the determinant of a matrix. + * Calculates the determinant of a square matrix. * - * @param m Matrix of which to take the determinant. + * @param m Matrix of which to take the determinant. + * + * @return Determinant of @p m. + * + * @warning Currently only implemented for 2x2, 3x3, and 4x4 matrices. */ -template -constexpr T determinant(const matrix& m); - -/// @copydoc determinant(const matrix&) -template -constexpr T determinant(const matrix& m); - -/// @copydoc determinant(const matrix&) -template -constexpr T determinant(const matrix& m); +template +constexpr T determinant(const matrix& m) noexcept; /** - * Calculates the inverse of a matrix. + * Calculates the inverse of a square matrix. * * @param m Matrix of which to take the inverse. + * + * @return Inverse of matrix @p m. + * + * @warning Currently only implemented for 2x2, 3x3, and 4x4 matrices. */ -template -constexpr matrix inverse(const matrix& m); - -/// @copydoc inverse(const matrix&) -template -constexpr matrix inverse(const matrix& m); - -/// @copydoc inverse(const matrix&) -template -constexpr matrix inverse(const matrix& m); +template +constexpr matrix inverse(const matrix& m) noexcept; /** * Performs a component-wise multiplication of two matrices. @@ -395,151 +380,97 @@ constexpr matrix inverse(const matrix& m); * @param x First matrix multiplicand. * @param y Second matrix multiplicand. */ -template -constexpr matrix componentwise_mul(const matrix& x, const matrix& y); - -/// @copydoc componentwise_mul(const matrix&, const matrix&) -template -constexpr matrix componentwise_mul(const matrix& x, const matrix& y); - -/// @copydoc componentwise_mul(const matrix&, const matrix&) -template -constexpr matrix componentwise_mul(const matrix& x, const matrix& y); +template +constexpr matrix componentwise_mul(const matrix& a, const matrix& b) noexcept; /** - * Creates a viewing transformation matrix. + * Divides a matrix by a 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. + * @param a First matrix. + * @param b Second matrix. + * @return Result of the division. */ -template -constexpr matrix look_at(const vector& position, const vector& target, vector up); +template +constexpr matrix div(const matrix& a, const matrix& b) noexcept; /** - * Multiplies two matrices. + * Divides a matrix by a scalar. * - * @param x First matrix. - * @param y Second matrix. - * @return Product of the two matrices. + * @param a Matrix. + * @param b Scalar. + * @return Result of the division. */ -template -constexpr matrix mul(const matrix& x, const matrix& y); - -/// @copydoc mul(const matrix&, const matrix&); -template -constexpr matrix mul(const matrix& x, const matrix& y); - -/// @copydoc mul(const matrix&, const matrix&); -template -constexpr matrix mul(const matrix& x, const matrix& y); +template +constexpr matrix div(const matrix& a, T b) noexcept; /** - * Multiplies a matrix by a scalar. + * Divides a scalar by a matrix. * - * @param m Matrix. - * @param s Scalar. - * @return Product of the matrix and the scalar.. + * @param a Scalar. + * @param b Matrix. + * @return Result of the division. */ template -constexpr matrix mul(const matrix& m, T s); +constexpr matrix div(T a, const matrix& b) noexcept; /** - * Transforms a vector by a matrix. + * Creates a viewing transformation matrix. * - * @param m Matrix. - * @param v Vector. - * @return Transformed vector. + * @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 -constexpr vector mul(const matrix& m, const vector& v); - -/// @copydoc mul(const matrix&, const vector&) -template -constexpr vector mul(const matrix& m, const vector& v); - -/// @copydoc mul(const matrix&, const vector&) -template -constexpr vector mul(const matrix& m, const vector& v); +constexpr matrix look_at(const vector& position, const vector& target, vector up); /** - * Creates an orthographic projection matrix which will transform the near and far clipping planes to `[-1, 1]`, respectively. + * Multiplies two matrices * - * @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 -constexpr matrix ortho(T left, T right, T bottom, T top, T z_near, T z_far); - -/** - * Creates an orthographic projection matrix which will transform the near and far clipping planes to `[0, 1]`, respectively. + * @tparam T Matrix element type. + * @tparam N Number of columns in matrix @p a, and rows in matrix @p b. + * @tparam M Number of rows in matrix @p a. + * @tparam P Number of columns in matrix @p b. * - * @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 -constexpr matrix ortho_half_z(T left, T right, T bottom, T top, T z_near, T z_far); - -/** - * Calculates the outer product of a pair of vectors. + * @param a First matrix. + * @param b Second matrix. * - * @param c Parameter to be treated as a column vector. - * @param r Parameter to be treated as a row vector. + * @return Product of `a * b`. */ -template -constexpr matrix outer_product(const vector& c, const vector& r); - -/// @copydoc outer_product(const vector&, const vector&) -template -constexpr matrix outer_product(const vector& c, const vector& r); - -/// @copydoc outer_product(const vector&, const vector&) -template -constexpr matrix outer_product(const vector& c, const vector r); +template +constexpr matrix mul(const matrix& a, const matrix& b) noexcept; /** - * Creates a perspective projection matrix which will transform the near and far clipping planes to `[-1, 1]`, respectively. + * Multiplies a matrix by a scalar. * - * @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. + * @param a Matrix. + * @param b Scalar. + * @return Product of the matrix and the scalar. */ -template -matrix perspective(T vertical_fov, T aspect_ratio, T z_near, T z_far); +template +constexpr matrix mul(const matrix& a, T b) noexcept; /** - * Creates a perspective projection matrix which will transform the near and far clipping planes to `[0, 1]`, respectively. + * Calculates the product of a matrix and a row vector. * - * @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. + * @param a Matrix. + * @param b Row vector + * + * @return Product of the matrix and the row vector. */ -template -matrix perspective_half_z(T vertical_fov, T aspect_ratio, T z_near, T z_far); +template +constexpr typename matrix::column_vector_type mul(const matrix& a, const typename matrix::row_vector_type& b) noexcept; /** - * Resizes a matrix. Any new elements will be set to `1` if in the diagonal, and `0` otherwise. + * Calculates the product of a column vector and a matrix. * - * @param m Matrix to resize. - * @return Resized matrix. + * @param a Column vector. + * @param b Matrix. + * + * @return Product of the column vector and the matrix. */ -template -constexpr matrix resize(const matrix& m); +template +constexpr typename matrix::row_vector_type mul(const typename matrix::column_vector_type& a, const matrix& b) noexcept; /** * Constructs a rotation matrix. @@ -591,20 +522,35 @@ constexpr matrix scale(const matrix& m, const vector& v) /** * Subtracts a matrix from another matrix. * - * @param x First matrix. - * @param y Second matrix. + * @param a First matrix. + * @param b Second matrix. + * * @return Difference between the two matrices. */ -template -constexpr matrix sub(const matrix& x, const matrix& y); +template +constexpr matrix sub(const matrix& a, const matrix& b) noexcept; -/// @copydoc sub(const matrix&, const matrix&) -template -constexpr matrix sub(const matrix& x, const matrix& y); +/** + * Subtracts a scalar from matrix. + * + * @param a Matrix. + * @param b Scalar. + * + * @return Difference between the matrix and scalar. + */ +template +constexpr matrix sub(const matrix& a, T b) noexcept; -/// @copydoc sub(const matrix&, const matrix&) -template -constexpr matrix sub(const matrix& x, const matrix& y); +/** + * Subtracts a matrix from a scalar. + * + * @param a Scalar. + * @param b Matrix. + * + * @return Difference between the scalar and matrix. + */ +template +constexpr matrix sub(T a, const matrix& b) noexcept; /** * Translates a matrix. @@ -619,82 +565,52 @@ constexpr matrix translate(const matrix& m, const vector /** * Calculates the transpose of a matrix. * - * @param m Matrix of which to take the transpose. - */ -template -constexpr matrix transpose(const matrix& m); - -/// @copydoc transpose(const matrix&) -template -constexpr matrix transpose(const matrix& m); - -/// @copydoc transpose(const matrix&) -template -constexpr matrix transpose(const matrix& m); - -/** - * Types casts each matrix element and returns a matrix of the casted type. + * @param m Matrix to transpose. * - * @tparam T2 Target matrix element type. - * @tparam T1 Source matrix element type. - * @tparam N Number of columns. - * @tparam M Number of rows. - * @param m Matrix to type cast. - * @return Type-casted matrix. + * @return Transposed matrix. */ -template -constexpr matrix type_cast(const matrix& m); +template +constexpr matrix transpose(const matrix& m) noexcept; -template -constexpr matrix add(const matrix& x, const matrix& y) +/// @private +template +constexpr inline matrix add(const matrix& a, const matrix& b, std::index_sequence) noexcept { - return - {{ - x[0] + y[0], - x[1] + y[1] - }}; + return {(a[I] + b[I]) ...}; } -template -constexpr matrix add(const matrix& x, const matrix& y) +template +constexpr matrix add(const matrix& a, const matrix& b) noexcept { - return - {{ - x[0] + y[0], - x[1] + y[1], - x[2] + y[2] - }}; + return add(a, b, std::make_index_sequence{}); } -template -constexpr matrix add(const matrix& x, const matrix& y) +/// @private +template +constexpr inline matrix add(const matrix& a, T b, std::index_sequence) noexcept { - return - {{ - x[0] + y[0], - x[1] + y[1], - x[2] + y[2], - x[3] + y[3] - }}; + return {(a[I] + b) ...}; } -template -constexpr inline matrix& as_matrix(T& data) +template +constexpr matrix add(const matrix& a, T b) noexcept { - static_assert(std::is_pod>::value); - return reinterpret_cast&>(data); + return add(a, b, std::make_index_sequence{}); } template -constexpr T determinant(const matrix& m) +constexpr T determinant(const matrix& m) noexcept { - return m[0][0] * m[1][1] - m[0][1] * m[1][0]; + return + m[0][0] * m[1][1] - + m[0][1] * m[1][0]; } template -constexpr T determinant(const matrix& m) +constexpr T determinant(const matrix& m) noexcept { - return m[0][0] * m [1][1] * m[2][2] + + 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] - @@ -703,9 +619,10 @@ constexpr T determinant(const matrix& m) } template -constexpr T determinant(const matrix& m) +constexpr T determinant(const matrix& m) noexcept { - 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] - + 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] + @@ -720,317 +637,195 @@ constexpr T determinant(const matrix& m) } template -constexpr matrix inverse(const matrix& m) -{ - static_assert(std::is_floating_point::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 -constexpr matrix inverse(const matrix& m) +constexpr matrix inverse(const matrix& m) noexcept { - static_assert(std::is_floating_point::value); - - const T rd(T(1) / determinant(m)); - + const T inv_det = 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 - } - }}; + { + m[1][1] * inv_det, + -m[0][1] * inv_det, + -m[1][0] * inv_det, + m[0][0] * inv_det + }; } template -constexpr matrix inverse(const matrix& m) +constexpr matrix inverse(const matrix& m) noexcept { - static_assert(std::is_floating_point::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 - } - }}; -} + const T inv_det = T{1} / determinant(m); -template -constexpr matrix componentwise_mul(const matrix& x, const matrix& 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]} - }}; -} + { + (m[1][1] * m[2][2] - m[1][2] * m[2][1]) * inv_det, + (m[0][2] * m[2][1] - m[0][1] * m[2][2]) * inv_det, + (m[0][1] * m[1][2] - m[0][2] * m[1][1]) * inv_det, + + (m[1][2] * m[2][0] - m[1][0] * m[2][2]) * inv_det, + (m[0][0] * m[2][2] - m[0][2] * m[2][0]) * inv_det, + (m[0][2] * m[1][0] - m[0][0] * m[1][2]) * inv_det, -template -constexpr matrix componentwise_mul(const matrix& x, const matrix& 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]} - }}; + (m[1][0] * m[2][1] - m[1][1] * m[2][0]) * inv_det, + (m[0][1] * m[2][0] - m[0][0] * m[2][1]) * inv_det, + (m[0][0] * m[1][1] - m[0][1] * m[1][0]) * inv_det + }; } template -constexpr matrix componentwise_mul(const matrix& x, const matrix& y) +constexpr matrix inverse(const matrix& m) noexcept { + const T inv_det = T{1} / determinant(m); + 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]} - }}; + { + (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]) * inv_det, + (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]) * inv_det, + (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]) * inv_det, + (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]) * inv_det, + + (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]) * inv_det, + (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]) * inv_det, + (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]) * inv_det, + (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]) * inv_det, + + (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]) * inv_det, + (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]) * inv_det, + (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]) * inv_det, + (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]) * inv_det, + + (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]) * inv_det, + (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]) * inv_det, + (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]) * inv_det, + (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]) * inv_det + }; } -template -constexpr matrix look_at(const vector& position, const vector& target, vector up) +/// @private +template +constexpr inline matrix componentwise_mul(const matrix& a, const matrix& b, std::index_sequence) noexcept { - vector forward = normalize(sub(target, position)); - vector right = normalize(cross(forward, up)); - up = cross(right, forward); - - matrix 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)); + return {(a[I] * b[I]) ...}; } -template -constexpr matrix mul(const matrix& x, const matrix& y) +template +constexpr matrix componentwise_mul(const matrix& a, const matrix& b) noexcept { - return - {{ - x[0] * y[0][0] + x[1] * y[0][1], - x[0] * y[1][0] + x[1] * y[1][1] - }}; + return componentwise_mul(a, b, std::make_index_sequence{}); } -template -constexpr matrix mul(const matrix& x, const matrix& y) +/// @private +template +constexpr inline matrix div(const matrix& a, const matrix& b, std::index_sequence) noexcept { - 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] - }}; + return {(a[I] / b[I]) ...}; } -template -constexpr matrix mul(const matrix& x, const matrix& y) +template +constexpr matrix div(const matrix& a, const matrix& b) noexcept { - 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] - }}; + return div(a, b, std::make_index_sequence{}); } /// @private template -constexpr inline matrix mul(const matrix& m, T s, std::index_sequence) +constexpr inline matrix div(const matrix& a, T b, std::index_sequence) noexcept { - return {{(m[I] * s)...}}; + return {(a[I] / b) ...}; } template -constexpr inline matrix mul(const matrix& m, T s) +constexpr matrix div(const matrix& a, T b) noexcept { - return mul(m, s, std::make_index_sequence{}); + return div(a, b, std::make_index_sequence{}); } -template -constexpr vector mul(const matrix& m, const vector& v) +/// @private +template +constexpr inline matrix div(T a, const matrix& b, std::index_sequence) noexcept { - return - { - m[0][0] * v[0] + m[1][0] * v[1], - m[0][1] * v[0] + m[1][1] * v[1] - }; + return {(a / b[I]) ...}; } -template -constexpr vector mul(const matrix& m, const vector& v) +template +constexpr matrix div(T a, const matrix& b) noexcept { - 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] - }; + return div(a, b, std::make_index_sequence{}); } template -constexpr vector mul(const matrix& m, const vector& v) +constexpr matrix look_at(const vector& position, const vector& target, vector up) { - 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] - }; -} + vector forward = normalize(sub(target, position)); + vector right = normalize(cross(forward, up)); + up = cross(right, forward); -template -constexpr matrix ortho(T left, T right, T bottom, T top, T z_near, T z_far) -{ - return + matrix m = {{ - {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)} + {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 -constexpr matrix ortho_half_z(T left, T right, T bottom, T top, T z_near, T z_far) +template +constexpr matrix mul(const matrix& a, const matrix& b) noexcept { - 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(-1) / (z_far - z_near), T(0)}, - {-((right + left) / (right - left)), -((top + bottom) / (top - bottom)), -z_near / (z_far - z_near), T(1)} - }}; + matrix c = matrix::zero(); + + for (std::size_t i = 0; i < P; ++i) + { + for (std::size_t j = 0; j < M; ++j) + { + for (std::size_t k = 0; k < N; ++k) + { + c[i][j] += a[k][j] * b[i][k]; + } + } + } + + return c; } -template -constexpr matrix outer_product(const vector& c, const vector& r) +/// @private +template +constexpr inline matrix mul(const matrix& a, T b, std::index_sequence) noexcept { - return - {{ - {c[0] * r[0], c[1] * r[0]}, - {c[0] * r[1], c[1] * r[1]} - }}; + return {(a[I] * b) ...}; } -template -constexpr matrix outer_product(const vector& c, const vector& r) +template +constexpr matrix mul(const matrix& a, T b) noexcept { - 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]} - }}; + return mul(a, b, std::make_index_sequence{}); } -template -constexpr matrix outer_product(const vector& c, const vector r) +/// @private +template +constexpr inline typename matrix::column_vector_type mul(const matrix& a, const typename matrix::row_vector_type& b, std::index_sequence) noexcept { - 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]} - }}; + return ((a[I] * b[I]) + ...); } -template -matrix perspective(T vertical_fov, T aspect_ratio, T z_near, T z_far) +template +constexpr typename matrix::column_vector_type mul(const matrix& a, const typename matrix::row_vector_type& b) noexcept { - 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_far * z_near) / (z_near - z_far), T(0)} - }}; + return mul(a, b, std::make_index_sequence{}); } -template -matrix perspective_half_z(T vertical_fov, T aspect_ratio, T z_near, T z_far) +/// @private +template +constexpr inline typename matrix::row_vector_type mul(const typename matrix::column_vector_type& a, const matrix& b, std::index_sequence) noexcept { - 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_far), T(-1)}, - {T(0), T(0), -(z_far * z_near) / (z_far - z_near), T(0)} - }}; + return {dot(a, b[I]) ...}; } -template -constexpr matrix resize(const matrix& m) +template +constexpr typename matrix::row_vector_type mul(const typename matrix::column_vector_type& a, const matrix& b) noexcept { - matrix 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; + return mul(a, b, std::make_index_sequence{}); } template @@ -1108,37 +903,43 @@ constexpr matrix scale(const matrix& m, const vector& v) }}); } -template -constexpr matrix sub(const matrix& x, const matrix& y) +/// @private +template +constexpr inline matrix sub(const matrix& a, const matrix& b, std::index_sequence) noexcept { - return - {{ - x[0] - y[0], - x[1] - y[1] - }}; + return {(a[I] - b[I]) ...}; } -template -constexpr matrix sub(const matrix& x, const matrix& y) +template +constexpr matrix sub(const matrix& a, const matrix& b) noexcept { - return - {{ - x[0] - y[0], - x[1] - y[1], - x[2] - y[2] - }}; + return sub(a, b, std::make_index_sequence{}); } -template -constexpr matrix sub(const matrix& x, const matrix& y) +/// @private +template +constexpr inline matrix sub(const matrix& a, T b, std::index_sequence) noexcept { - return - {{ - x[0] - y[0], - x[1] - y[1], - x[2] - y[2], - x[3] - y[3] - }}; + return {(a[I] - b) ...}; +} + +template +constexpr matrix sub(const matrix& a, T b) noexcept +{ + return sub(a, b, std::make_index_sequence{}); +} + +/// @private +template +constexpr inline matrix sub(T a, const matrix& b, std::index_sequence) noexcept +{ + return {(a - b[I]) ...}; +} + +template +constexpr matrix sub(T a, const matrix& b) noexcept +{ + return sub(a, b, std::make_index_sequence{}); } template @@ -1153,161 +954,213 @@ constexpr matrix translate(const matrix& m, const vector }}); } -template -constexpr matrix transpose(const matrix& m) +/// @private +template +constexpr inline typename matrix::column_vector_type transpose_column(const matrix& m, std::size_t i, std::index_sequence) noexcept { - - return - {{ - { - m[0][0], m[1][0] - }, - - { - m[0][1], m[1][1] - } - }}; + return {m[I][i] ...}; } -template -constexpr matrix transpose(const matrix& m) +/// @private +template +constexpr inline matrix transpose(const matrix& m, std::index_sequence) noexcept { - - 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] - } - }}; + return {transpose_column(m, I, std::make_index_sequence{}) ...}; } -template -constexpr matrix transpose(const matrix& m) +template +constexpr matrix transpose(const matrix& m) noexcept { + return transpose(m, std::make_index_sequence{}); +} - 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] - }, +} // namespace math - { - m[0][3], m[1][3], m[2][3], m[3][3] - } - }}; +/// @copydoc math::add(const math::matrix&, const math::matrix&) +template +constexpr inline math::matrix operator+(const math::matrix& a, const math::matrix& b) noexcept +{ + return math::add(a, b); } -/// @private -template -constexpr inline matrix type_cast(const matrix& m, std::index_sequence) +/// @copydoc math::add(const math::matrix&, T) +/// @{ +template +constexpr inline math::matrix operator+(const math::matrix& a, T b) noexcept { - return {type_cast(m[I])...}; + return math::add(a, b); } - -template -constexpr matrix type_cast(const matrix& m) +template +constexpr inline math::matrix operator+(T a, const math::matrix& b) noexcept { - return type_cast(m, std::make_index_sequence{}); + return math::add(b, a); } +/// @} -} // namespace math +/// @copydoc math::div(const math::matrix&, const math::matrix&) +template +constexpr inline math::matrix operator/(const math::matrix& a, const math::matrix& b) noexcept +{ + return math::div(a, b); +} -/// @copydoc math::add(const math::matrix&, const math::matrix&) +/// @copydoc math::div(const math::matrix&, T) template -constexpr math::matrix operator+(const math::matrix& x, const math::matrix& y); +constexpr inline math::matrix operator/(const math::matrix& a, T b) noexcept +{ + return math::div(a, b); +} -/// @copydoc math::mul(const math::matrix&, const math::matrix&) +/// @copydoc math::div(T, const math::matrix&) template -constexpr math::matrix operator*(const math::matrix& x, const math::matrix& y); +constexpr inline math::matrix operator/(T a, const math::matrix& b) noexcept +{ + return math::div(a, b); +} + +/// @copydoc math::mul(const math::matrix&, const math::matrix&) +template +constexpr inline math::matrix operator*(const math::matrix& a, const math::matrix& b) noexcept +{ + return math::mul(a, b); +} /// @copydoc math::mul(const math::matrix&, T) +/// @{ template -constexpr math::matrix operator*(const math::matrix& m, T s); +constexpr inline math::matrix operator*(const math::matrix& a, T b) noexcept +{ + return math::mul(a, b); +} +template +constexpr inline math::matrix operator*(T a, const math::matrix& b) noexcept +{ + return math::mul(b, a); +} +/// @} -/// @copydoc math::mul(const math::matrix&, T) +/// @copydoc math::mul(const math::matrix&, const typename math::matrix::row_vector_type&) +template +constexpr inline typename math::matrix::column_vector_type operator*(const math::matrix& a, const typename math::matrix::row_vector_type& b) noexcept +{ + return math::mul(a, b); +} + +/// @copydoc math::mul(const typename math::matrix::column_vector_type&, const math::matrix&) +template +constexpr inline typename math::matrix::row_vector_type operator*(const typename math::matrix::column_vector_type& a, const math::matrix& b) noexcept +{ + return math::mul(a, b); +} + +/// @copydoc math::sub(const math::matrix&, const math::matrix&) template -constexpr math::matrix operator*(T s, const math::matrix& m); +constexpr inline math::matrix operator-(const math::matrix& a, const math::matrix& b) noexcept +{ + return math::sub(a, b); +} -/// @copydoc math::mul(const math::matrix&, const math::vector&) -template -constexpr math::vector operator*(const math::matrix& m, const math::vector& v); +/// @copydoc math::sub(const math::matrix&, T) +template +constexpr inline math::matrix operator-(const math::matrix& a, T b) noexcept +{ + return math::sub(a, b); +} -/// @copydoc math::sub(const math::matrix&, const math::matrix&) +/// @copydoc math::sub(T, const math::matrix&) template -constexpr math::matrix operator-(const math::matrix& x, const math::matrix& y); +constexpr inline math::matrix operator-(T a, const math::matrix& b) noexcept +{ + return math::sub(a, b); +} /** - * Writes the elements of a matrix to an output stream, with each element delimeted by a space. + * Adds two values and stores the result in the first value. * - * @param os Output stream. - * @param m Matrix. - * @return Output stream. + * @param a First value. + * @param b Second value. + * @return Reference to the first value. */ +/// @{ template -std::ostream& operator<<(std::ostream& os, const math::matrix& m); +constexpr inline math::matrix& operator+=(math::matrix& a, const math::matrix& b) noexcept +{ + return (a = a + b); +} +template +constexpr inline math::matrix& operator+=(math::matrix& a, T b) noexcept +{ + return (a = a + b); +} +/// @} /** - * Reads the elements of a matrix from an input stream, with each element delimeted by a space. + * Subtracts the first value by the second value and stores the result in the first value. * - * @param is Input stream. - * @param m Matrix. - * @return Input stream. + * @param a First value. + * @param b Second value. + * @return Reference to the first value. */ +/// @{ template -std::istream& operator>>(std::istream& is, math::matrix& m); - -template -constexpr inline math::matrix operator+(const math::matrix& x, const math::matrix& y) +constexpr inline math::matrix& operator-=(math::matrix& a, const math::matrix& b) noexcept { - return math::add(x, y); + return (a = a - b); } - template -constexpr inline math::matrix operator*(const math::matrix& x, const math::matrix& y) +constexpr inline math::matrix& operator-=(math::matrix& a, T b) noexcept { - return math::mul(x, y); + return (a = a - b); } +/// @} -template -constexpr inline math::matrix operator*(const math::matrix& m, T s) +/** + * Multiplies two values and stores the result in the first value. + * + * @param a First value. + * @param b Second value. + * @return Reference to the first value. + */ +/// @{ +template +constexpr inline math::matrix& operator*=(math::matrix& a, math::matrix& b) noexcept { - return math::mul(m, s); + return (a = a * b); } - template -constexpr inline math::matrix operator*(T s, const math::matrix& m) +constexpr inline math::matrix& operator*=(math::matrix& a, T b) noexcept { - return math::mul(m, s); + return (a = a * b); } +/// @} -template -constexpr inline math::vector operator*(const math::matrix& m, const math::vector& v) +/** + * Divides the first value by the second value and stores the result in the first value. + * + * @param a First value. + * @param b Second value. + * @return Reference to the first value. + */ +/// @{ +template +constexpr inline math::matrix& operator/=(math::matrix& a, const math::matrix& b) noexcept { - return math::mul(m, v); + return (a = a / b); } - template -constexpr inline math::matrix operator-(const math::matrix& x, const math::matrix& y) +constexpr inline math::matrix& operator/=(math::matrix& a, T b) noexcept { - return math::sub(x, y); + return (a = a / b); } +/// @} +/** + * 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 std::ostream& operator<<(std::ostream& os, const math::matrix& m) { @@ -1321,6 +1174,13 @@ std::ostream& operator<<(std::ostream& os, const math::matrix& m) return os; } +/** + * Reads the elements of a matrix from an input stream, with each element delimeted by a space. + * + * @param is Input stream. + * @param m Matrix. + * @return Input stream. + */ template std::istream& operator>>(std::istream& is, math::matrix& m) { diff --git a/src/math/projection.hpp b/src/math/projection.hpp index a72ab69..5e9446b 100644 --- a/src/math/projection.hpp +++ b/src/math/projection.hpp @@ -20,6 +20,7 @@ #ifndef ANTKEEPER_MATH_PROJECTION_HPP #define ANTKEEPER_MATH_PROJECTION_HPP +#include "math/matrix.hpp" #include namespace math { @@ -56,6 +57,104 @@ T vertical_fov(T h, T r) return T{2} * std::atan(std::tan(h * T{0.5}) / r); } +/** + * Creates an orthographic projection matrix which will transform the near and far clipping planes to `[-1, 1]`, respectively. + * + * @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 +constexpr matrix ortho(T left, T right, T bottom, T top, T z_near, T z_far) noexcept +{ + 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)} + }}; +} + +/** + * Creates an orthographic projection matrix which will transform the near and far clipping planes to `[0, 1]`, respectively. + * + * @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 +constexpr matrix ortho_half_z(T left, T right, T bottom, T top, T z_near, T z_far) noexcept +{ + 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(-1) / (z_far - z_near), T(0)}, + {-((right + left) / (right - left)), -((top + bottom) / (top - bottom)), -z_near / (z_far - z_near), T(1)} + }}; +} + +/** + * Creates a perspective projection matrix which will transform the near and far clipping planes to `[-1, 1]`, respectively. + * + * @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 +matrix 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_far * z_near) / (z_near - z_far), T(0)} + }}; +} + +/** + * Creates a perspective projection matrix which will transform the near and far clipping planes to `[0, 1]`, respectively. + * + * @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 +matrix perspective_half_z(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_far), T(-1)}, + {T(0), T(0), -(z_far * z_near) / (z_far - z_near), T(0)} + }}; +} + } // namespace math #endif // ANTKEEPER_MATH_PROJECTION_HPP diff --git a/src/math/se3.hpp b/src/math/se3.hpp index 91693a5..7b23c2d 100644 --- a/src/math/se3.hpp +++ b/src/math/se3.hpp @@ -95,7 +95,7 @@ se3 se3::inverse() const template typename se3::matrix_type se3::matrix() const { - matrix_type m = math::resize<4, 4>(math::matrix_cast(r)); + matrix_type m = math::matrix(math::matrix_cast(r)); m[3].x() = t.x(); m[3].y() = t.y(); diff --git a/src/math/transform-functions.hpp b/src/math/transform-functions.hpp index 18fcfbf..639f770 100644 --- a/src/math/transform-functions.hpp +++ b/src/math/transform-functions.hpp @@ -75,7 +75,7 @@ transform inverse(const transform& t) template matrix matrix_cast(const transform& t) { - matrix transformation = resize<4, 4>(matrix_cast(t.rotation)); + matrix transformation = matrix(matrix_cast(t.rotation)); transformation[3] = {t.translation[0], t.translation[1], t.translation[2], T(1)}; return scale(transformation, t.scale); } diff --git a/src/math/vector.hpp b/src/math/vector.hpp index 67ee3ca..62fd7a2 100644 --- a/src/math/vector.hpp +++ b/src/math/vector.hpp @@ -308,9 +308,9 @@ constexpr vector abs(const vector& x); */ /// @{ template -constexpr vector add(const vector& x, const vector& y); +constexpr vector add(const vector& x, const vector& y) noexcept; template -constexpr vector add(const vector& x, T y); +constexpr vector add(const vector& x, T y) noexcept; /// @} /** @@ -320,7 +320,7 @@ constexpr vector add(const vector& x, T y); * @return `true` if all elements are `true`, `false` otherwise. */ template -constexpr bool all(const vector& x); +constexpr bool all(const vector& x) noexcept; /** * Checks if any elements of a boolean vector are `true`. @@ -329,15 +329,7 @@ constexpr bool all(const vector& x); * @return `true` if any elements are `true`, `false` otherwise. */ template -constexpr bool any(const vector& x); - -/** - * Reinterprets data as an *n*-dimensional vector of type `T`. - * - * @param data Data to reinterpret. - */ -template -constexpr vector& as_vector(T& data); +constexpr bool any(const vector& x) noexcept; /** * Performs a element-wise ceil operation. @@ -352,15 +344,15 @@ constexpr vector ceil(const vector& x); * Clamps the values of a vector's elements. * * @param x Vector to clamp. - * @param min_val Minimum value. - * @param max_val Maximum value. + * @param min Minimum value. + * @param max Maximum value. * @return Clamped vector. */ /// @{ template -constexpr vector clamp(const vector& x, const vector& min_val, const vector& max_val); +constexpr vector clamp(const vector& x, const vector& min, const vector& max); template -constexpr vector clamp(const vector& x, T min_val, T max_val); +constexpr vector clamp(const vector& x, T min, T max); /// @} /** @@ -381,7 +373,7 @@ vector clamp_length(const vector& x, T max_length); * @return Cross product of the two vectors. */ template -constexpr vector cross(const vector& x, const vector& y); +constexpr vector cross(const vector& x, const vector& y) noexcept; /** * Calculates the distance between two points. @@ -401,7 +393,7 @@ T distance(const vector& p0, const vector& p1); * @return Squared distance between the two points. */ template -constexpr T distance_squared(const vector& p0, const vector& p1); +constexpr T distance_squared(const vector& p0, const vector& p1) noexcept; /** * Divides a vector by a value. @@ -412,9 +404,11 @@ constexpr T distance_squared(const vector& p0, const vector& p1); */ /// @{ template -constexpr vector div(const vector& x, const vector& y); +constexpr vector div(const vector& x, const vector& y) noexcept; template -constexpr vector div(const vector& x, T y); +constexpr vector div(const vector& x, T y) noexcept; +template +constexpr vector div(T x, const vector& y) noexcept; /// @} /** @@ -425,7 +419,7 @@ constexpr vector div(const vector& x, T y); * @return Dot product of the two vectors. */ template -constexpr T dot(const vector& x, const vector& y); +constexpr T dot(const vector& x, const vector& y) noexcept; /** * Compares two vectors for equality @@ -435,7 +429,7 @@ constexpr T dot(const vector& x, const vector& y); * @return Boolean vector containing the result of the element comparisons. */ template -constexpr vector equal(const vector& x, const vector& y); +constexpr vector equal(const vector& x, const vector& y) noexcept; /** * Performs a element-wise floor operation. @@ -479,7 +473,7 @@ constexpr vector fract(const vector& x); * @return Boolean vector containing the result of the element comparisons. */ template -constexpr vector greater_than(const vector& x, const vector& y); +constexpr vector greater_than(const vector& x, const vector& y) noexcept; /** * Performs a element-wise greater-than or equal-to comparison of two vectors. @@ -489,7 +483,7 @@ constexpr vector greater_than(const vector& x, const vector * @return Boolean vector containing the result of the element comparisons. */ template -constexpr vector greater_than_equal(const vector& x, const vector& y); +constexpr vector greater_than_equal(const vector& x, const vector& y) noexcept; /** * Calculates the length of a vector. @@ -507,7 +501,7 @@ T length(const vector& x); * @return Squared length of the vector. */ template -constexpr T length_squared(const vector& x); +constexpr T length_squared(const vector& x) noexcept; /** * Performs a element-wise less-than comparison of two vectors. @@ -517,7 +511,7 @@ constexpr T length_squared(const vector& x); * @return Boolean vector containing the result of the element comparisons. */ template -constexpr vector less_than(const vector& x, const vector& y); +constexpr vector less_than(const vector& x, const vector& y) noexcept; /** * Performs a element-wise less-than or equal-to comparison of two vectors. @@ -527,7 +521,7 @@ constexpr vector less_than(const vector& x, const vector& y * @return Boolean vector containing the result of the element comparisons. */ template -constexpr vector less_than_equal(const vector& x, const vector& y); +constexpr vector less_than_equal(const vector& x, const vector& y) noexcept; /** * Returns a vector containing the maximum elements of two vectors. @@ -594,9 +588,9 @@ constexpr vector mod(const vector& x, T y); */ /// @{ template -constexpr vector mul(const vector& x, const vector& y); +constexpr vector mul(const vector& x, const vector& y) noexcept; template -constexpr vector mul(const vector& x, T y); +constexpr vector mul(const vector& x, T y) noexcept; /// @} /** @@ -606,7 +600,7 @@ constexpr vector mul(const vector& x, T y); * @return Negated vector. */ template -constexpr vector negate(const vector& x); +constexpr vector negate(const vector& x) noexcept; /** * Calculates the unit vector in the same direction as the original vector. @@ -624,7 +618,7 @@ vector normalize(const vector& x); * @return Logically inverted vector. */ template -constexpr vector not(const vector& x); +constexpr vector not(const vector& x) noexcept; /** * Compares two vectors for inequality @@ -634,7 +628,7 @@ constexpr vector not(const vector& x); * @return Boolean vector containing the result of the element comparisons. */ template -constexpr vector not_equal(const vector& x, const vector& y); +constexpr vector not_equal(const vector& x, const vector& y) noexcept; /** * Raises each element to a power. @@ -651,18 +645,6 @@ template vector pow(const vector& x, T y); /// @} -/** - * Resizes a vector. Any new elements will be set to `0`. - * - * @tparam M Target number of elements. - * - * @param x Vector to resize. - * - * @return Resized vector. - */ -template -constexpr vector resize(const vector& x); - /** * Performs a element-wise round operation. * @@ -700,9 +682,11 @@ vector sqrt(const vector& x); */ /// @{ template -constexpr vector sub(const vector& x, const vector& y); +constexpr vector sub(const vector& x, const vector& y) noexcept; +template +constexpr vector sub(const vector& x, T y) noexcept; template -constexpr vector sub(const vector& x, T y); +constexpr vector sub(T x, const vector& y) noexcept; /// @} /** @@ -712,7 +696,7 @@ constexpr vector sub(const vector& x, T y); * @return Sum of the vector's elements. */ template -constexpr T sum(const vector& x); +constexpr T sum(const vector& x) noexcept; /** * Makes an *m*-dimensional vector by rearranging and/or duplicating elements of an *n*-dimensional vector. @@ -726,7 +710,7 @@ constexpr T sum(const vector& x); * @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. */ template -constexpr vector swizzle(const vector& x); +constexpr vector swizzle(const vector& x) noexcept; /** * Performs a element-wise trunc operation. @@ -737,19 +721,6 @@ constexpr vector swizzle(const vector& x); template constexpr vector trunc(const vector& x); -/** - * Types casts each vector element and returns a vector of the casted type. - * - * @tparam U Target vector element type. - * @tparam T Source vector element type. - * @tparam N Number of dimensions. - * @param x Vector to type cast. - * - * @return Type-casted vector. - */ -template -constexpr vector type_cast(const vector& x); - /// @private template constexpr inline vector abs(const vector& x, std::index_sequence) @@ -765,63 +736,56 @@ constexpr inline vector abs(const vector& x) /// @private template -constexpr inline vector add(const vector& x, const vector& y, std::index_sequence) +constexpr inline vector add(const vector& x, const vector& y, std::index_sequence) noexcept { return {(x[I] + y[I])...}; } template -constexpr inline vector add(const vector& x, const vector& y) +constexpr inline vector add(const vector& x, const vector& y) noexcept { return add(x, y, std::make_index_sequence{}); } /// @private template -constexpr inline vector add(const vector& x, T y, std::index_sequence) +constexpr inline vector add(const vector& x, T y, std::index_sequence) noexcept { return {(x[I] + y)...}; } template -constexpr inline vector add(const vector& x, T y) +constexpr inline vector add(const vector& x, T y) noexcept { return add(x, y, std::make_index_sequence{}); } /// @private template -constexpr inline bool all(const vector& x, std::index_sequence) +constexpr inline bool all(const vector& x, std::index_sequence) noexcept { return (x[I] && ...); } template -constexpr inline bool all(const vector& x) +constexpr inline bool all(const vector& x) noexcept { return all(x, std::make_index_sequence{}); } /// @private template -constexpr inline bool any(const vector& x, std::index_sequence) +constexpr inline bool any(const vector& x, std::index_sequence) noexcept { return (x[I] || ...); } template -constexpr inline bool any(const vector& x) +constexpr inline bool any(const vector& x) noexcept { return any(x, std::make_index_sequence{}); } -template -constexpr inline vector& as_vector(T& data) -{ - static_assert(std::is_pod>::value); - return reinterpret_cast&>(data); -} - /// @private template constexpr inline vector ceil(const vector& x, std::index_sequence) @@ -844,22 +808,22 @@ constexpr inline vector clamp(const vector& x, const vector& m } template -constexpr inline vector clamp(const vector& x, const vector& min_val, const vector& max_val) +constexpr inline vector clamp(const vector& x, const vector& min, const vector& max) { - return clamp(x, min_val, max_val, std::make_index_sequence{}); + return clamp(x, min, max, std::make_index_sequence{}); } /// @private template -constexpr inline vector clamp(const vector& x, T min_val, T max_val, std::index_sequence) +constexpr inline vector clamp(const vector& x, T min, T max, std::index_sequence) { - return {std::min(max_val, std::max(min_val, x[I]))...}; + return {std::min(max, std::max(min, x[I]))...}; } template -constexpr inline vector clamp(const vector& x, T min_val, T max_val) +constexpr inline vector clamp(const vector& x, T min, T max) { - return clamp(x, min_val, max_val, std::make_index_sequence{}); + return clamp(x, min, max, std::make_index_sequence{}); } template @@ -871,7 +835,7 @@ vector clamp_length(const vector& x, T max_length) } template -constexpr inline vector cross(const vector& x, const vector& y) +constexpr inline vector cross(const vector& x, const vector& y) noexcept { return { @@ -889,60 +853,72 @@ inline T distance(const vector& p0, const vector& p1) } template -constexpr inline T distance_squared(const vector& p0, const vector& p1) +constexpr inline T distance_squared(const vector& p0, const vector& p1) noexcept { - static_assert(std::is_floating_point::value); return length_squared(sub(p0, p1)); } /// @private template -constexpr inline vector div(const vector& x, const vector& y, std::index_sequence) +constexpr inline vector div(const vector& x, const vector& y, std::index_sequence) noexcept { return {(x[I] / y[I])...}; } template -constexpr inline vector div(const vector& x, const vector& y) +constexpr inline vector div(const vector& x, const vector& y) noexcept { return div(x, y, std::make_index_sequence{}); } /// @private template -constexpr inline vector div(const vector& x, T y, std::index_sequence) +constexpr inline vector div(const vector& x, T y, std::index_sequence) noexcept { return {(x[I] / y)...}; } template -constexpr inline vector div(const vector& x, T y) +constexpr inline vector div(const vector& x, T y) noexcept +{ + return div(x, y, std::make_index_sequence{}); +} + +/// @private +template +constexpr inline vector div(T x, const vector& y, std::index_sequence) noexcept +{ + return {(x / y[I])...}; +} + +template +constexpr inline vector div(T x, const vector& y) noexcept { return div(x, y, std::make_index_sequence{}); } /// @private template -constexpr inline T dot(const vector& x, const vector& y, std::index_sequence) +constexpr inline T dot(const vector& x, const vector& y, std::index_sequence) noexcept { return ((x[I] * y[I]) + ...); } template -constexpr inline T dot(const vector& x, const vector& y) +constexpr inline T dot(const vector& x, const vector& y) noexcept { return dot(x, y, std::make_index_sequence{}); } /// @private template -constexpr inline vector equal(const vector& x, const vector& y, std::index_sequence) +constexpr inline vector equal(const vector& x, const vector& y, std::index_sequence) noexcept { return {(x[I] == y[I])...}; } template -constexpr inline vector equal(const vector& x, const vector& y) +constexpr inline vector equal(const vector& x, const vector& y) noexcept { return equal(x, y, std::make_index_sequence{}); } @@ -1005,26 +981,26 @@ constexpr inline vector fract(const vector& x) /// @private template -constexpr inline vector greater_than(const vector& x, const vector& y, std::index_sequence) +constexpr inline vector greater_than(const vector& x, const vector& y, std::index_sequence) noexcept { return {(x[I] > y[I])...}; } template -constexpr inline vector greater_than(const vector& x, const vector& y) +constexpr inline vector greater_than(const vector& x, const vector& y) noexcept { return greater_than(x, y, std::make_index_sequence{}); } /// @private template -constexpr inline vector greater_than_equal(const vector& x, const vector& y, std::index_sequence) +constexpr inline vector greater_than_equal(const vector& x, const vector& y, std::index_sequence) noexcept { return {(x[I] >= y[I])...}; } template -constexpr inline vector greater_than_equal(const vector& x, const vector& y) +constexpr inline vector greater_than_equal(const vector& x, const vector& y) noexcept { return greater_than_equal(x, y, std::make_index_sequence{}); } @@ -1037,33 +1013,33 @@ inline T length(const vector& x) } template -constexpr inline T length_squared(const vector& x) +constexpr inline T length_squared(const vector& x) noexcept { return dot(x, x); } /// @private template -constexpr inline vector less_than(const vector& x, const vector& y, std::index_sequence) +constexpr inline vector less_than(const vector& x, const vector& y, std::index_sequence) noexcept { return {(x[I] < y[I])...}; } template -constexpr inline vector less_than(const vector& x, const vector& y) +constexpr inline vector less_than(const vector& x, const vector& y) noexcept { return less_than(x, y, std::make_index_sequence{}); } /// @private template -constexpr inline vector less_than_equal(const vector& x, const vector& y, std::index_sequence) +constexpr inline vector less_than_equal(const vector& x, const vector& y, std::index_sequence) noexcept { return {(x[I] <= y[I])...}; } template -constexpr inline vector less_than_equal(const vector& x, const vector& y) +constexpr inline vector less_than_equal(const vector& x, const vector& y) noexcept { return less_than_equal(x, y, std::make_index_sequence{}); } @@ -1136,39 +1112,39 @@ constexpr inline vector mod(const vector& x, T y) /// @private template -constexpr inline vector mul(const vector& x, const vector& y, std::index_sequence) +constexpr inline vector mul(const vector& x, const vector& y, std::index_sequence) noexcept { return {(x[I] * y[I])...}; } template -constexpr inline vector mul(const vector& x, const vector& y) +constexpr inline vector mul(const vector& x, const vector& y) noexcept { return mul(x, y, std::make_index_sequence{}); } /// @private template -constexpr inline vector mul(const vector& x, T y, std::index_sequence) +constexpr inline vector mul(const vector& x, T y, std::index_sequence) noexcept { return {(x[I] * y)...}; } template -constexpr inline vector mul(const vector& x, T y) +constexpr inline vector mul(const vector& x, T y) noexcept { return mul(x, y, std::make_index_sequence{}); } /// @private template -constexpr inline vector negate(const vector& x, std::index_sequence) +constexpr inline vector negate(const vector& x, std::index_sequence) noexcept { return {(-x[I])...}; } template -constexpr inline vector negate(const vector& x) +constexpr inline vector negate(const vector& x) noexcept { return negate(x, std::make_index_sequence{}); } @@ -1177,31 +1153,31 @@ template inline vector normalize(const vector& x) { static_assert(std::is_floating_point::value); - return mul(x, T(1) / length(x)); + return mul(x, T{1} / length(x)); } /// @private template -constexpr inline vector not(const vector& x, std::index_sequence) +constexpr inline vector not(const vector& x, std::index_sequence) noexcept { return {!x[I]...}; } template -constexpr inline vector not(const vector& x) +constexpr inline vector not(const vector& x) noexcept { return not(x, std::make_index_sequence{}); } /// @private template -constexpr inline vector not_equal(const vector& x, const vector& y, std::index_sequence) +constexpr inline vector not_equal(const vector& x, const vector& y, std::index_sequence) noexcept { return {(x[I] != y[I])...}; } template -constexpr inline vector not_equal(const vector& x, const vector& y) +constexpr inline vector not_equal(const vector& x, const vector& y) noexcept { return not_equal(x, y, std::make_index_sequence{}); } @@ -1234,19 +1210,6 @@ inline vector pow(const vector& x, T y) return pow(x, y, std::make_index_sequence{}); } -/// @private -template -constexpr inline vector resize(const vector& x, std::index_sequence) -{ - return {(I < N) ? x[I] : T{0} ...}; -} - -template -constexpr inline vector resize(const vector& x) -{ - return resize(x, std::make_index_sequence{}); -} - /// @private template constexpr inline vector round(const vector& x, std::index_sequence) @@ -1291,45 +1254,58 @@ inline vector sqrt(const vector& x, const vector& y) /// @private template -constexpr inline vector sub(const vector& x, const vector& y, std::index_sequence) +constexpr inline vector sub(const vector& x, const vector& y, std::index_sequence) noexcept { return {(x[I] - y[I])...}; } template -constexpr inline vector sub(const vector& x, const vector& y) +constexpr inline vector sub(const vector& x, const vector& y) noexcept { return sub(x, y, std::make_index_sequence{}); } /// @private template -constexpr inline vector sub(const vector& x, T y, std::index_sequence) +constexpr inline vector sub(const vector& x, T y, std::index_sequence) noexcept { return {(x[I] - y)...}; } template -constexpr inline vector sub(const vector& x, T y) +constexpr inline vector sub(const vector& x, T y) noexcept +{ + return sub(x, y, std::make_index_sequence{}); +} + +/// @private +template +constexpr inline vector sub(T x, const vector& y, std::index_sequence) noexcept +{ + return {(x - y[I])...}; +} + +template +constexpr inline vector sub(T x, const vector& y) noexcept { return sub(x, y, std::make_index_sequence{}); } /// @private template -constexpr inline T sum(const vector& x, std::index_sequence) +constexpr inline T sum(const vector& x, std::index_sequence) noexcept { return (x[I] + ...); } template -constexpr inline T sum(const vector& x) +constexpr inline T sum(const vector& x) noexcept { return sum(x, std::make_index_sequence{}); } template -constexpr inline vector swizzle(const vector& x) +constexpr inline vector swizzle(const vector& x) noexcept { return {x[Indices]...}; } @@ -1348,64 +1324,98 @@ constexpr inline vector trunc(const vector& x) return trunc(x, std::make_index_sequence{}); } -/// @private -template -constexpr inline vector type_cast(const vector& x, std::index_sequence) -{ - return {static_cast(x[I])...}; -} - -template -constexpr inline vector type_cast(const vector& x) -{ - return type_cast(x, std::make_index_sequence{}); -} - } // namespace math /// @copydoc math::add(const math::vector&, const math::vector&) template -constexpr math::vector operator+(const math::vector& x, const math::vector& y); +constexpr inline math::vector operator+(const math::vector& x, const math::vector& y) noexcept +{ + return math::add(x, y); +} /// @copydoc math::add(const math::vector&, T) /// @{ template -constexpr math::vector operator+(const math::vector& x, T y); +constexpr inline math::vector operator+(const math::vector& x, T y) noexcept +{ + return math::add(x, y); +} template -constexpr math::vector operator+(T x, const math::vector& y); +constexpr inline math::vector operator+(T x, const math::vector& y) noexcept +{ + return math::add(y, x); +} /// @} /// @copydoc math::div(const math::vector&, const math::vector&) template -constexpr math::vector operator/(const math::vector& x, const math::vector& y); +constexpr inline math::vector operator/(const math::vector& x, const math::vector& y) noexcept +{ + return math::div(x, y); +} -/// @copydoc math::div(const math::vector&, T y) +/// @copydoc math::div(const math::vector&, T) template -constexpr math::vector operator/(const math::vector& x, T y); +constexpr inline math::vector operator/(const math::vector& x, T y) noexcept +{ + return math::div(x, y); +} + +/// @copydoc math::div(T, const math::vector&) +template +constexpr inline math::vector operator/(T x, const math::vector& y) noexcept +{ + return math::div(x, y); +} /// @copydoc math::mul(const math::vector&, const math::vector&) template -constexpr math::vector operator*(const math::vector& x, const math::vector& y); +constexpr inline math::vector operator*(const math::vector& x, const math::vector& y) noexcept +{ + return math::mul(x, y); +} /// @copydoc math::mul(const math::vector&, T) /// @{ template -constexpr math::vector operator*(const math::vector& x, T y); +constexpr inline math::vector operator*(const math::vector& x, T y) noexcept +{ + return math::mul(x, y); +} template -constexpr math::vector operator*(T x, const math::vector& y); +constexpr inline math::vector operator*(T x, const math::vector& y) noexcept +{ + return math::mul(y, x); +} /// @} /// @copydoc math::negate(const math::vector&) template -constexpr math::vector operator-(const math::vector& x); +constexpr inline math::vector operator-(const math::vector& x) noexcept +{ + return math::negate(x); +} /// @copydoc math::sub(const math::vector&, const math::vector&) template -constexpr math::vector operator-(const math::vector& x, const math::vector& y); +constexpr inline math::vector operator-(const math::vector& x, const math::vector& y) noexcept +{ + return math::sub(x, y); +} /// @copydoc math::sub(const math::vector&, T) template -constexpr math::vector operator-(const math::vector& x, T y); +constexpr inline math::vector operator-(const math::vector& x, T y) noexcept +{ + return math::sub(x, y); +} + +/// @copydoc math::sub(T, const math::vector&) +template +constexpr inline math::vector operator-(T x, const math::vector& y) noexcept +{ + return math::sub(x, y); +} /** * Adds two values and stores the result in the first value. @@ -1416,9 +1426,15 @@ constexpr math::vector operator-(const math::vector& x, T y); */ /// @{ template -constexpr math::vector& operator+=(math::vector& x, const math::vector& y); +constexpr inline math::vector& operator+=(math::vector& x, const math::vector& y) noexcept +{ + return (x = x + y); +} template -constexpr math::vector& operator+=(math::vector& x, T y); +constexpr inline math::vector& operator+=(math::vector& x, T y) noexcept +{ + return (x = x + y); +} /// @} /** @@ -1430,9 +1446,15 @@ constexpr math::vector& operator+=(math::vector& x, T y); */ /// @{ template -constexpr math::vector& operator-=(math::vector& x, const math::vector& y); +constexpr inline math::vector& operator-=(math::vector& x, const math::vector& y) noexcept +{ + return (x = x - y); +} template -constexpr math::vector& operator-=(math::vector& x, T y); +constexpr inline math::vector& operator-=(math::vector& x, T y) noexcept +{ + return (x = x - y); +} /// @} /** @@ -1444,9 +1466,15 @@ constexpr math::vector& operator-=(math::vector& x, T y); */ /// @{ template -constexpr math::vector& operator*=(math::vector& x, const math::vector& y); +constexpr inline math::vector& operator*=(math::vector& x, const math::vector& y) noexcept +{ + return (x = x * y); +} template -constexpr math::vector& operator*=(math::vector& x, T y); +constexpr inline math::vector& operator*=(math::vector& x, T y) noexcept +{ + return (x = x * y); +} /// @} /** @@ -1458,9 +1486,15 @@ constexpr math::vector& operator*=(math::vector& x, T y); */ /// @{ template -constexpr math::vector& operator/=(math::vector& x, const math::vector& y); +constexpr inline math::vector& operator/=(math::vector& x, const math::vector& y) noexcept +{ + return (x = x / y); +} template -constexpr math::vector& operator/=(math::vector& x, T y); +constexpr inline math::vector& operator/=(math::vector& x, T y) noexcept +{ + return (x = x / y); +} /// @} /** @@ -1471,134 +1505,6 @@ constexpr math::vector& operator/=(math::vector& x, T y); * * @return Output stream. */ -template -std::ostream& operator<<(std::ostream& os, const math::vector& x); - -/** - * Reads the elements of a vector from an input stream, with each element delimeted by a space. - * - * @param is Input stream. - * @param x Vector. - * - * @return Input stream. - */ -template -std::istream& operator>>(std::istream& is, math::vector& v); - -template -constexpr inline math::vector operator+(const math::vector& x, const math::vector& y) -{ - return math::add(x, y); -} - -template -constexpr inline math::vector operator+(const math::vector& x, T y) -{ - return math::add(x, y); -} - -template -constexpr inline math::vector operator+(T x, const math::vector& y) -{ - return math::add(y, x); -} - -template -constexpr inline math::vector operator-(const math::vector& x) -{ - return math::negate(x); -} - -template -constexpr inline math::vector operator-(const math::vector& x, const math::vector& y) -{ - return math::sub(x, y); -} - -template -constexpr inline math::vector operator-(const math::vector& x, T y) -{ - return math::sub(x, y); -} - -template -constexpr inline math::vector operator*(const math::vector& x, const math::vector& y) -{ - return math::mul(x, y); -} - -template -constexpr inline math::vector operator*(const math::vector& x, T y) -{ - return math::mul(x, y); -} - -template -constexpr inline math::vector operator*(T x, const math::vector& y) -{ - return math::mul(y, x); -} - -template -constexpr inline math::vector operator/(const math::vector& x, const math::vector& y) -{ - return math::div(x, y); -} - -template -constexpr inline math::vector operator/(const math::vector& x, T y) -{ - return math::div(x, y); -} - -template -constexpr inline math::vector& operator+=(math::vector& x, const math::vector& y) -{ - return (x = x + y); -} - -template -constexpr inline math::vector& operator+=(math::vector& x, T y) -{ - return (x = x + y); -} - -template -constexpr inline math::vector& operator-=(math::vector& x, const math::vector& y) -{ - return (x = x - y); -} - -template -constexpr inline math::vector& operator-=(math::vector& x, T y) -{ - return (x = x - y); -} - -template -constexpr inline math::vector& operator*=(math::vector& x, const math::vector& y) -{ - return (x = x * y); -} - -template -constexpr inline math::vector& operator*=(math::vector& x, T y) -{ - return (x = x * y); -} - -template -constexpr inline math::vector& operator/=(math::vector& x, const math::vector& y) -{ - return (x = x / y); -} - -template -constexpr inline math::vector& operator/=(math::vector& x, T y) -{ - return (x = x / y); -} - template std::ostream& operator<<(std::ostream& os, const math::vector& x) { @@ -1612,6 +1518,14 @@ std::ostream& operator<<(std::ostream& os, const math::vector& x) return os; } +/** + * Reads the elements of a vector from an input stream, with each element delimeted by a space. + * + * @param is Input stream. + * @param x Vector. + * + * @return Input stream. + */ template std::istream& operator>>(std::istream& is, math::vector& x) { diff --git a/src/render/passes/ground-pass.cpp b/src/render/passes/ground-pass.cpp index 1feeece..f74e996 100644 --- a/src/render/passes/ground-pass.cpp +++ b/src/render/passes/ground-pass.cpp @@ -86,7 +86,7 @@ void ground_pass::render(const render::context& ctx, render::queue& queue) const float clip_far = camera.get_clip_far_tween().interpolate(ctx.alpha); float3 model_scale = float3{1.0f, 1.0f, 1.0f} * (clip_near + clip_far) * 0.5f; float4x4 model = math::scale(math::matrix4::identity(), model_scale); - float4x4 view = math::resize<4, 4>(math::resize<3, 3>(ctx.view)); + float4x4 view = float4x4(float3x3(ctx.view)); float4x4 model_view = view * model; const float4x4& projection = ctx.projection; const float4x4& view_projection = ctx.view_projection; diff --git a/src/render/passes/material-pass.cpp b/src/render/passes/material-pass.cpp index d8092bc..452b1c3 100644 --- a/src/render/passes/material-pass.cpp +++ b/src/render/passes/material-pass.cpp @@ -43,6 +43,7 @@ #include "scene/spot-light.hpp" #include "config.hpp" #include "math/quaternion-operators.hpp" +#include "math/projection.hpp" #include #include @@ -504,8 +505,8 @@ void material_pass::render(const render::context& ctx, render::queue& queue) con model = operation.transform; model_view_projection = view_projection * model; model_view = view * model; - normal_model = math::transpose(math::inverse(math::resize<3, 3>(model))); - normal_model_view = math::transpose(math::inverse(math::resize<3, 3>(model_view))); + normal_model = math::transpose(math::inverse(math::matrix(model))); + normal_model_view = math::transpose(math::inverse(math::matrix(model_view))); // Skinning palette if (operation.bone_count && parameters->skinning_palette) diff --git a/src/render/passes/shadow-map-pass.cpp b/src/render/passes/shadow-map-pass.cpp index f844167..01f93fb 100644 --- a/src/render/passes/shadow-map-pass.cpp +++ b/src/render/passes/shadow-map-pass.cpp @@ -35,6 +35,7 @@ #include "math/vector.hpp" #include "math/matrix.hpp" #include "math/quaternion-operators.hpp" +#include "math/projection.hpp" #include #include diff --git a/src/render/passes/sky-pass.cpp b/src/render/passes/sky-pass.cpp index e675210..8cdd733 100644 --- a/src/render/passes/sky-pass.cpp +++ b/src/render/passes/sky-pass.cpp @@ -194,7 +194,7 @@ void sky_pass::render(const render::context& ctx, render::queue& queue) const float clip_far = camera.get_clip_far_tween().interpolate(ctx.alpha); float3 model_scale = float3{1.0f, 1.0f, 1.0f} * (clip_near + clip_far) * 0.5f; float4x4 model = math::scale(math::matrix4::identity(), model_scale); - float4x4 view = math::resize<4, 4>(math::resize<3, 3>(ctx.view)); + float4x4 view = float4x4(float3x3(ctx.view)); float4x4 model_view = view * model; const float4x4& projection = ctx.projection; float4x4 view_projection = projection * view; @@ -300,7 +300,7 @@ void sky_pass::render(const render::context& ctx, render::queue& queue) const { float star_distance = (clip_near + clip_far) * 0.5f; - model = math::resize<4, 4>(math::matrix_cast(icrf_to_eus.r)); + model = float4x4(math::matrix_cast(icrf_to_eus.r)); model = math::scale(model, {star_distance, star_distance, star_distance}); model_view = view * model; @@ -332,7 +332,7 @@ void sky_pass::render(const render::context& ctx, render::queue& queue) const moon_transform.scale = {moon_radius, moon_radius, moon_radius}; model = math::matrix_cast(moon_transform); - float3x3 normal_model = math::transpose(math::inverse(math::resize<3, 3>(model))); + float3x3 normal_model = math::transpose(math::inverse(float3x3(model))); rasterizer->use_program(*moon_shader_program); if (moon_model_input) diff --git a/src/render/renderer.cpp b/src/render/renderer.cpp index ff54494..cf0be48 100644 --- a/src/render/renderer.cpp +++ b/src/render/renderer.cpp @@ -176,7 +176,7 @@ void renderer::process_model_instance(const render::context& ctx, render::queue& render::operation operation; operation.transform = math::matrix_cast(model_instance->get_transform_tween().interpolate(ctx.alpha)); - operation.depth = ctx.clip_near.signed_distance(math::resize<3>(operation.transform[3])); + operation.depth = ctx.clip_near.signed_distance(float3(operation.transform[3])); operation.vertex_array = model->get_vertex_array(); operation.instance_count = model_instance->get_instance_count(); @@ -223,7 +223,7 @@ void renderer::process_billboard(const render::context& ctx, render::queue& queu math::transform billboard_transform = billboard->get_transform_tween().interpolate(ctx.alpha); billboard_op.material = billboard->get_material(); - billboard_op.depth = ctx.clip_near.signed_distance(math::resize<3>(billboard_transform.translation)); + billboard_op.depth = ctx.clip_near.signed_distance(float3(billboard_transform.translation)); // Align billboard if (billboard->get_billboard_type() == scene::billboard_type::spherical) diff --git a/src/render/renderer.hpp b/src/render/renderer.hpp index ddf17e1..79cf1db 100644 --- a/src/render/renderer.hpp +++ b/src/render/renderer.hpp @@ -52,7 +52,7 @@ public: * @param t Current time, in seconds. * @param dt Timestep, in seconds. * @param alpha Subframe interpolation factor. - * @parma collection Collection of scene objects to render. + * @param collection Collection of scene objects to render. */ void render(float t, float dt, float alpha, const scene::collection& collection) const; diff --git a/src/scene/camera.cpp b/src/scene/camera.cpp index a6c7327..4c82fe1 100644 --- a/src/scene/camera.cpp +++ b/src/scene/camera.cpp @@ -22,6 +22,7 @@ #include "math/constants.hpp" #include "math/interpolation.hpp" #include "math/quaternion-operators.hpp" +#include "math/projection.hpp" namespace scene { @@ -101,7 +102,7 @@ float3 camera::project(const float3& object, const float4& viewport) const result[0] = result[0] * viewport[2] + viewport[0]; result[1] = result[1] * viewport[3] + viewport[1]; - return math::resize<3>(result); + return math::vector(result); } float3 camera::unproject(const float3& window, const float4& viewport) const @@ -116,7 +117,7 @@ float3 camera::unproject(const float3& window, const float4& viewport) const result = math::inverse(view_projection[1]) * result; - return math::resize<3>(result) * (1.0f / result[3]); + return math::vector(result) * (1.0f / result[3]); } void camera::set_perspective(float fov, float aspect_ratio, float clip_near, float clip_far) diff --git a/src/scene/text.cpp b/src/scene/text.cpp index 2f5b8ee..92839df 100644 --- a/src/scene/text.cpp +++ b/src/scene/text.cpp @@ -104,7 +104,7 @@ void text::render(const render::context& ctx, render::queue& queue) const return; render_op.transform = math::matrix_cast(get_transform_tween().interpolate(ctx.alpha)); - render_op.depth = ctx.clip_near.signed_distance(math::resize<3>(render_op.transform[3])); + render_op.depth = ctx.clip_near.signed_distance(math::vector(render_op.transform[3])); queue.push_back(render_op); }