mirror of
https://github.com/orange-cpp/omath.git
synced 2026-06-12 02:04:35 +00:00
added mat tests and triangle tests
This commit is contained in:
@@ -679,7 +679,7 @@ namespace omath
|
||||
|
||||
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR, class Angle>
|
||||
[[nodiscard("You must use rotation matrix")]]
|
||||
Mat<4, 4, Type, St> mat_rotation_axis_x(const Angle& angle) noexcept
|
||||
OMATH_CONSTEXPR Mat<4, 4, Type, St> mat_rotation_axis_x(const Angle& angle) noexcept
|
||||
{
|
||||
return
|
||||
{
|
||||
@@ -692,7 +692,7 @@ namespace omath
|
||||
|
||||
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR, class Angle>
|
||||
[[nodiscard("You must use rotation matrix")]]
|
||||
Mat<4, 4, Type, St> mat_rotation_axis_y(const Angle& angle) noexcept
|
||||
OMATH_CONSTEXPR Mat<4, 4, Type, St> mat_rotation_axis_y(const Angle& angle) noexcept
|
||||
{
|
||||
return
|
||||
{
|
||||
@@ -705,7 +705,7 @@ namespace omath
|
||||
|
||||
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR, class Angle>
|
||||
[[nodiscard("You must use rotation matrix")]]
|
||||
Mat<4, 4, Type, St> mat_rotation_axis_z(const Angle& angle) noexcept
|
||||
OMATH_CONSTEXPR Mat<4, 4, Type, St> mat_rotation_axis_z(const Angle& angle) noexcept
|
||||
{
|
||||
return
|
||||
{
|
||||
@@ -718,7 +718,7 @@ namespace omath
|
||||
|
||||
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR>
|
||||
[[nodiscard("You must use camera view matrix")]]
|
||||
static Mat<4, 4, Type, St> mat_camera_view(const Vector3<Type>& forward, const Vector3<Type>& right,
|
||||
OMATH_CONSTEXPR static Mat<4, 4, Type, St> mat_camera_view(const Vector3<Type>& forward, const Vector3<Type>& right,
|
||||
const Vector3<Type>& up, const Vector3<Type>& camera_origin) noexcept
|
||||
{
|
||||
return Mat<4, 4, Type, St>
|
||||
@@ -732,12 +732,15 @@ namespace omath
|
||||
|
||||
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR,
|
||||
NDCDepthRange DepthRange = NDCDepthRange::NEGATIVE_ONE_TO_ONE>
|
||||
[[nodiscard("You must use perspective matrix")]]
|
||||
[[nodiscard("You must use perspective matrix")]] OMATH_CONSTEXPR
|
||||
Mat<4, 4, Type, St> mat_perspective_left_handed_vertical_fov(const Type field_of_view, const Type aspect_ratio,
|
||||
const Type near, const Type far) noexcept
|
||||
{
|
||||
const auto fov_half_tan = std::tan(angles::degrees_to_radians(field_of_view) / Type{2});
|
||||
|
||||
#ifdef OMATH_USE_GCEM
|
||||
const auto fov_half_tan = gcem::tan(angles::degrees_to_radians(field_of_view) / Type{2});
|
||||
#else
|
||||
const auto fov_half_tan = std::tan(angles::degrees_to_radians(field_of_view) / Type{2})
|
||||
#endif
|
||||
if constexpr (DepthRange == NDCDepthRange::ZERO_TO_ONE)
|
||||
return {{Type{1} / (aspect_ratio * fov_half_tan), Type{0}, Type{0}, Type{0}},
|
||||
{Type{0}, Type{1} / fov_half_tan, Type{0}, Type{0}},
|
||||
@@ -754,11 +757,15 @@ namespace omath
|
||||
|
||||
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR,
|
||||
NDCDepthRange DepthRange = NDCDepthRange::NEGATIVE_ONE_TO_ONE>
|
||||
[[nodiscard("You must use perspective matrix")]]
|
||||
[[nodiscard("You must use perspective matrix")]] OMATH_CONSTEXPR
|
||||
Mat<4, 4, Type, St> mat_perspective_right_handed_vertical_fov(const Type field_of_view, const Type aspect_ratio,
|
||||
const Type near, const Type far) noexcept
|
||||
{
|
||||
#ifdef OMATH_USE_GCEM
|
||||
const auto fov_half_tan = gcem::tan(angles::degrees_to_radians(field_of_view) / Type{2});
|
||||
#else
|
||||
const auto fov_half_tan = std::tan(angles::degrees_to_radians(field_of_view) / Type{2});
|
||||
#endif
|
||||
|
||||
if constexpr (DepthRange == NDCDepthRange::ZERO_TO_ONE)
|
||||
return {{Type{1} / (aspect_ratio * fov_half_tan), Type{0}, Type{0}, Type{0}},
|
||||
@@ -779,12 +786,16 @@ namespace omath
|
||||
// X and Y scales derived as: X = 1 / tan(hfov/2), Y = aspect / tan(hfov/2).
|
||||
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR,
|
||||
NDCDepthRange DepthRange = NDCDepthRange::NEGATIVE_ONE_TO_ONE>
|
||||
[[nodiscard("You must use perspective matrix")]]
|
||||
[[nodiscard("You must use perspective matrix")]] OMATH_CONSTEXPR
|
||||
Mat<4, 4, Type, St> mat_perspective_left_handed_horizontal_fov(const Type horizontal_fov,
|
||||
const Type aspect_ratio, const Type near,
|
||||
const Type far) noexcept
|
||||
{
|
||||
#ifdef OMATH_USE_GCEM
|
||||
const auto inv_tan_half_hfov = Type{1} / gcem::tan(angles::degrees_to_radians(horizontal_fov) / Type{2});
|
||||
#else
|
||||
const auto inv_tan_half_hfov = Type{1} / std::tan(angles::degrees_to_radians(horizontal_fov) / Type{2});
|
||||
#endif
|
||||
const auto x_axis = inv_tan_half_hfov;
|
||||
const auto y_axis = inv_tan_half_hfov * aspect_ratio;
|
||||
|
||||
@@ -804,12 +815,17 @@ namespace omath
|
||||
|
||||
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR,
|
||||
NDCDepthRange DepthRange = NDCDepthRange::NEGATIVE_ONE_TO_ONE>
|
||||
[[nodiscard("You must use perspective matrix")]]
|
||||
[[nodiscard("You must use perspective matrix")]] OMATH_CONSTEXPR
|
||||
Mat<4, 4, Type, St> mat_perspective_right_handed_horizontal_fov(const Type horizontal_fov,
|
||||
const Type aspect_ratio, const Type near,
|
||||
const Type far) noexcept
|
||||
{
|
||||
#ifdef OMATH_USE_GCEM
|
||||
const auto inv_tan_half_hfov = Type{1} / gcem::tan(angles::degrees_to_radians(horizontal_fov) / Type{2});
|
||||
#else
|
||||
const auto inv_tan_half_hfov = Type{1} / std::tan(angles::degrees_to_radians(horizontal_fov) / Type{2});
|
||||
#endif
|
||||
|
||||
const auto x_axis = inv_tan_half_hfov;
|
||||
const auto y_axis = inv_tan_half_hfov * aspect_ratio;
|
||||
|
||||
@@ -828,7 +844,7 @@ namespace omath
|
||||
}
|
||||
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR,
|
||||
NDCDepthRange DepthRange = NDCDepthRange::NEGATIVE_ONE_TO_ONE>
|
||||
[[nodiscard("You must use ortho matrix")]]
|
||||
[[nodiscard("You must use ortho matrix")]] OMATH_CONSTEXPR
|
||||
Mat<4, 4, Type, St> mat_ortho_left_handed(const Type left, const Type right, const Type bottom, const Type top,
|
||||
const Type near, const Type far) noexcept
|
||||
{
|
||||
@@ -853,7 +869,7 @@ namespace omath
|
||||
}
|
||||
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR,
|
||||
NDCDepthRange DepthRange = NDCDepthRange::NEGATIVE_ONE_TO_ONE>
|
||||
[[nodiscard("You must use ortho matrix")]]
|
||||
[[nodiscard("You must use ortho matrix")]] OMATH_CONSTEXPR
|
||||
Mat<4, 4, Type, St> mat_ortho_right_handed(const Type left, const Type right, const Type bottom, const Type top,
|
||||
const Type near, const Type far) noexcept
|
||||
{
|
||||
@@ -877,7 +893,7 @@ namespace omath
|
||||
std::unreachable();
|
||||
}
|
||||
template<class T = float, MatStoreType St = MatStoreType::COLUMN_MAJOR>
|
||||
Mat<4, 4, T, St> mat_look_at_left_handed(const Vector3<T>& eye, const Vector3<T>& center, const Vector3<T>& up)
|
||||
OMATH_CONSTEXPR Mat<4, 4, T, St> mat_look_at_left_handed(const Vector3<T>& eye, const Vector3<T>& center, const Vector3<T>& up)
|
||||
{
|
||||
const Vector3<T> f = (center - eye).normalized();
|
||||
const Vector3<T> s = f.cross(up).normalized();
|
||||
@@ -886,7 +902,7 @@ namespace omath
|
||||
}
|
||||
|
||||
template<class T = float, MatStoreType St = MatStoreType::COLUMN_MAJOR>
|
||||
Mat<4, 4, T, St>mat_look_at_right_handed(const Vector3<T>& eye, const Vector3<T>& center, const Vector3<T>& up)
|
||||
OMATH_CONSTEXPR Mat<4, 4, T, St> mat_look_at_right_handed(const Vector3<T>& eye, const Vector3<T>& center, const Vector3<T>& up)
|
||||
{
|
||||
const Vector3<T> f = (center - eye).normalized();
|
||||
const Vector3<T> s = f.cross(up).normalized();
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// Created by Orange on 11/13/2024.
|
||||
//
|
||||
#pragma once
|
||||
#include "vector3.hpp"
|
||||
#include "omath/internal/optional_constexpr_math.hpp"
|
||||
#include "vector3.hpp"
|
||||
namespace omath
|
||||
{
|
||||
/*
|
||||
@@ -69,7 +69,11 @@ namespace omath
|
||||
const auto side_b = side_b_length();
|
||||
const auto hypot_value = hypot();
|
||||
|
||||
#ifdef OMATH_USE_GCEM
|
||||
return gcem::abs(side_a * side_a + side_b * side_b - hypot_value * hypot_value) <= 0.0001f;
|
||||
#else
|
||||
return std::abs(side_a * side_a + side_b * side_b - hypot_value * hypot_value) <= 0.0001f;
|
||||
#endif
|
||||
}
|
||||
[[nodiscard]]
|
||||
constexpr Vector side_b_vector() const
|
||||
|
||||
@@ -1,11 +1,25 @@
|
||||
// UnitTestMat.cpp
|
||||
#include "omath/linear_algebra/mat.hpp"
|
||||
#include "omath/linear_algebra/vector3.hpp"
|
||||
#include "omath/trigonometry/angle.hpp"
|
||||
#include "omath/trigonometry/angles.hpp"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace omath;
|
||||
|
||||
#ifdef OMATH_USE_GCEM
|
||||
namespace
|
||||
{
|
||||
using Pitch = Angle<float, static_cast<float>(-90), static_cast<float>(90), AngleFlags::Clamped>;
|
||||
|
||||
constexpr bool close_to(const float actual, const float expected, const float epsilon)
|
||||
{
|
||||
const float diff = actual - expected;
|
||||
return (diff < 0.0f ? -diff : diff) <= epsilon;
|
||||
}
|
||||
} // namespace
|
||||
#endif
|
||||
|
||||
class UnitTestMat : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
@@ -523,3 +537,47 @@ TEST(UnitTestMatStandalone, MatOrthoNegativeOneToOneDefault)
|
||||
|
||||
EXPECT_EQ(ortho_default, ortho_explicit);
|
||||
}
|
||||
|
||||
#ifdef OMATH_USE_GCEM
|
||||
static_assert(
|
||||
[]
|
||||
{
|
||||
constexpr auto scale = mat_extract_scale(mat_scale(Vector3{2.0f, 3.0f, 4.0f}));
|
||||
return close_to(scale.x, 2.0f, 1e-5f) && close_to(scale.y, 3.0f, 1e-5f) && close_to(scale.z, 4.0f, 1e-5f);
|
||||
}(),
|
||||
"Mat scale extraction should be constexpr with gcem");
|
||||
|
||||
static_assert(
|
||||
[]
|
||||
{
|
||||
constexpr auto rotation = mat_rotation_axis_z<float>(Pitch::from_degrees(90.0f));
|
||||
return close_to(rotation.at(0, 0), 0.0f, 1e-5f) && close_to(rotation.at(0, 1), -1.0f, 1e-5f)
|
||||
&& close_to(rotation.at(1, 0), 1.0f, 1e-5f) && close_to(rotation.at(1, 1), 0.0f, 1e-5f)
|
||||
&& close_to(rotation.at(2, 2), 1.0f, 1e-5f) && close_to(rotation.at(3, 3), 1.0f, 1e-5f);
|
||||
}(),
|
||||
"Mat rotation should be constexpr with gcem");
|
||||
|
||||
static_assert(
|
||||
[]
|
||||
{
|
||||
constexpr auto projection =
|
||||
mat_perspective_left_handed_vertical_fov<float, MatStoreType::ROW_MAJOR,
|
||||
NDCDepthRange::ZERO_TO_ONE>(90.0f, 1.0f, 1.0f, 11.0f);
|
||||
return close_to(projection.at(0, 0), 1.0f, 1e-5f) && close_to(projection.at(1, 1), 1.0f, 1e-5f)
|
||||
&& close_to(projection.at(2, 2), 1.1f, 1e-5f) && close_to(projection.at(2, 3), -1.1f, 1e-5f)
|
||||
&& close_to(projection.at(3, 2), 1.0f, 1e-5f);
|
||||
}(),
|
||||
"Mat vertical-FOV perspective should be constexpr with gcem");
|
||||
|
||||
static_assert(
|
||||
[]
|
||||
{
|
||||
constexpr auto projection =
|
||||
mat_perspective_right_handed_horizontal_fov<float, MatStoreType::ROW_MAJOR,
|
||||
NDCDepthRange::ZERO_TO_ONE>(90.0f, 2.0f, 1.0f, 11.0f);
|
||||
return close_to(projection.at(0, 0), 1.0f, 1e-5f) && close_to(projection.at(1, 1), 2.0f, 1e-5f)
|
||||
&& close_to(projection.at(2, 2), -1.1f, 1e-5f) && close_to(projection.at(2, 3), -1.1f, 1e-5f)
|
||||
&& close_to(projection.at(3, 2), -1.0f, 1e-5f);
|
||||
}(),
|
||||
"Mat horizontal-FOV perspective should be constexpr with gcem");
|
||||
#endif
|
||||
|
||||
@@ -8,6 +8,17 @@
|
||||
|
||||
using namespace omath;
|
||||
|
||||
#ifdef OMATH_USE_GCEM
|
||||
namespace
|
||||
{
|
||||
constexpr bool close_to(const float actual, const float expected, const float epsilon)
|
||||
{
|
||||
const float diff = actual - expected;
|
||||
return (diff < 0.0f ? -diff : diff) <= epsilon;
|
||||
}
|
||||
} // namespace
|
||||
#endif
|
||||
|
||||
class UnitTestTriangle : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
@@ -129,3 +140,20 @@ TEST_F(UnitTestTriangle, MidPoint)
|
||||
EXPECT_FLOAT_EQ(mid2.y, (2.0f + 5.0f + 8.0f) / 3.0f);
|
||||
EXPECT_FLOAT_EQ(mid2.z, (3.0f + 6.0f + 9.0f) / 3.0f);
|
||||
}
|
||||
|
||||
#ifdef OMATH_USE_GCEM
|
||||
static_assert(
|
||||
[]
|
||||
{
|
||||
constexpr Triangle<Vector3<float>> triangle{{3.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, {0.0f, 4.0f, 0.0f}};
|
||||
constexpr auto normal = triangle.calculate_normal();
|
||||
constexpr auto mid_point = triangle.mid_point();
|
||||
|
||||
return close_to(triangle.side_a_length(), 3.0f, 1e-5f) && close_to(triangle.side_b_length(), 4.0f, 1e-5f)
|
||||
&& close_to(triangle.hypot(), 5.0f, 1e-5f) && triangle.is_rectangular()
|
||||
&& close_to(normal.length(), 1.0f, 1e-5f) && close_to(normal.z, -1.0f, 1e-5f)
|
||||
&& close_to(mid_point.x, 1.0f, 1e-5f) && close_to(mid_point.y, 4.0f / 3.0f, 1e-5f)
|
||||
&& close_to(mid_point.z, 0.0f, 1e-5f);
|
||||
}(),
|
||||
"Triangle helpers should be constexpr with gcem");
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user