mirror of
https://github.com/orange-cpp/omath.git
synced 2026-02-13 07:03:25 +00:00
Compare commits
15 Commits
feature/ro
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| fee135d82e | |||
| e8c7abf925 | |||
| 6ae3e37172 | |||
| afc613fcc0 | |||
| d7a721f62e | |||
| 5aae9d6842 | |||
| 3e4598313d | |||
| d231139b83 | |||
| 9c4e2a3319 | |||
| 7597d95778 | |||
| 5aa0e2e949 | |||
| b7b1154f29 | |||
| b10e26e6ba | |||
| ba23fee243 | |||
| 32e0f9e636 |
24
.vscode/launch.json
vendored
Normal file
24
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": " Unit Tests (Debug)",
|
||||||
|
"type": "lldb",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceRoot}/out/Debug/unit_tests",
|
||||||
|
"args": [],
|
||||||
|
"cwd": "${workspaceRoot}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": " Unit Tests (Release)",
|
||||||
|
"type": "lldb",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceRoot}/out/Release/unit_tests",
|
||||||
|
"args": [],
|
||||||
|
"cwd": "${workspaceRoot}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -29,7 +29,7 @@ set_target_properties(
|
|||||||
find_package(OpenGL)
|
find_package(OpenGL)
|
||||||
find_package(GLEW REQUIRED)
|
find_package(GLEW REQUIRED)
|
||||||
find_package(glfw3 CONFIG REQUIRED)
|
find_package(glfw3 CONFIG REQUIRED)
|
||||||
target_link_libraries(example_glfw3 PRIVATE omath::omath GLEW::GLEW glfw OpenGL::OpenGL)
|
target_link_libraries(example_glfw3 PRIVATE omath::omath GLEW::GLEW glfw OpenGL::GL)
|
||||||
|
|
||||||
if(OMATH_ENABLE_VALGRIND)
|
if(OMATH_ENABLE_VALGRIND)
|
||||||
omath_setup_valgrind(example_projection_matrix_builder)
|
omath_setup_valgrind(example_projection_matrix_builder)
|
||||||
|
|||||||
@@ -8,43 +8,96 @@
|
|||||||
|
|
||||||
namespace omath::collision
|
namespace omath::collision
|
||||||
{
|
{
|
||||||
class Ray
|
template<class T = Vector3<float>>
|
||||||
|
class Ray final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Vector3<float> start;
|
using VectorType = T;
|
||||||
Vector3<float> end;
|
VectorType start;
|
||||||
|
VectorType end;
|
||||||
bool infinite_length = false;
|
bool infinite_length = false;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
Vector3<float> direction_vector() const noexcept;
|
constexpr VectorType direction_vector() const noexcept
|
||||||
|
{
|
||||||
|
return end - start;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
Vector3<float> direction_vector_normalized() const noexcept;
|
constexpr VectorType direction_vector_normalized() const noexcept
|
||||||
|
{
|
||||||
|
return direction_vector().normalized();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
class LineTracer
|
|
||||||
|
template<class RayType = Ray<>>
|
||||||
|
class LineTracer final
|
||||||
{
|
{
|
||||||
|
using TriangleType = Triangle<typename RayType::VectorType>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LineTracer() = delete;
|
LineTracer() = delete;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
static bool can_trace_line(const Ray& ray, const Triangle<Vector3<float>>& triangle) noexcept;
|
constexpr static bool can_trace_line(const RayType& ray, const TriangleType& triangle) noexcept
|
||||||
|
{
|
||||||
|
return get_ray_hit_point(ray, triangle) == ray.end;
|
||||||
|
}
|
||||||
|
|
||||||
// Realization of Möller–Trumbore intersection algorithm
|
// Realization of Möller–Trumbore intersection algorithm
|
||||||
// https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm
|
// https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
static Vector3<float> get_ray_hit_point(const Ray& ray, const Triangle<Vector3<float>>& triangle) noexcept;
|
constexpr static auto get_ray_hit_point(const RayType& ray, const TriangleType& triangle) noexcept
|
||||||
|
{
|
||||||
|
constexpr float k_epsilon = std::numeric_limits<float>::epsilon();
|
||||||
|
|
||||||
|
const auto side_a = triangle.side_a_vector();
|
||||||
|
const auto side_b = triangle.side_b_vector();
|
||||||
|
|
||||||
|
const auto ray_dir = ray.direction_vector();
|
||||||
|
|
||||||
|
const auto p = ray_dir.cross(side_b);
|
||||||
|
const auto det = side_a.dot(p);
|
||||||
|
|
||||||
|
if (std::abs(det) < k_epsilon)
|
||||||
|
return ray.end;
|
||||||
|
|
||||||
|
const auto inv_det = 1 / det;
|
||||||
|
const auto t = ray.start - triangle.m_vertex2;
|
||||||
|
const auto u = t.dot(p) * inv_det;
|
||||||
|
|
||||||
|
if ((u < 0 && std::abs(u) > k_epsilon) || (u > 1 && std::abs(u - 1) > k_epsilon))
|
||||||
|
return ray.end;
|
||||||
|
|
||||||
|
const auto q = t.cross(side_a);
|
||||||
|
// ReSharper disable once CppTooWideScopeInitStatement
|
||||||
|
const auto v = ray_dir.dot(q) * inv_det;
|
||||||
|
|
||||||
|
if ((v < 0 && std::abs(v) > k_epsilon) || (u + v > 1 && std::abs(u + v - 1) > k_epsilon))
|
||||||
|
return ray.end;
|
||||||
|
|
||||||
|
const auto t_hit = side_b.dot(q) * inv_det;
|
||||||
|
|
||||||
|
if (ray.infinite_length && t_hit <= k_epsilon)
|
||||||
|
return ray.end;
|
||||||
|
|
||||||
|
if (t_hit <= k_epsilon || t_hit > 1 - k_epsilon)
|
||||||
|
return ray.end;
|
||||||
|
|
||||||
|
return ray.start + ray_dir * t_hit;
|
||||||
|
}
|
||||||
|
|
||||||
template<class MeshType>
|
template<class MeshType>
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
static Vector3<float> get_ray_hit_point(const Ray& ray, const MeshType& mesh) noexcept
|
constexpr static auto get_ray_hit_point(const RayType& ray, const MeshType& mesh) noexcept
|
||||||
{
|
{
|
||||||
Vector3<float> mesh_hit = ray.end;
|
auto mesh_hit = ray.end;
|
||||||
|
|
||||||
auto begin = mesh.m_element_buffer_object.cbegin();
|
const auto begin = mesh.m_element_buffer_object.cbegin();
|
||||||
auto end = mesh.m_element_buffer_object.cend();
|
const auto end = mesh.m_element_buffer_object.cend();
|
||||||
for (auto current = begin; current < end; current = std::next(current))
|
for (auto current = begin; current < end; current = std::next(current))
|
||||||
{
|
{
|
||||||
auto face = mesh.make_face_in_world_space(current);
|
const auto face = mesh.make_face_in_world_space(current);
|
||||||
|
|
||||||
auto ray_stop_point = get_ray_hit_point(ray, face);
|
auto ray_stop_point = get_ray_hit_point(ray, face);
|
||||||
if (ray_stop_point.distance_to(ray.start) < mesh_hit.distance_to(ray.start))
|
if (ray_stop_point.distance_to(ray.start) < mesh_hit.distance_to(ray.start))
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ namespace omath::collision
|
|||||||
|
|
||||||
template<class V>
|
template<class V>
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
static constexpr bool near_zero(const V& v, const float eps = 1e-7f)
|
static constexpr bool near_zero(const V& v, const float eps = 1e-7f) noexcept
|
||||||
{
|
{
|
||||||
return v.dot(v) <= eps * eps;
|
return v.dot(v) <= eps * eps;
|
||||||
}
|
}
|
||||||
@@ -146,7 +146,7 @@ namespace omath::collision
|
|||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr bool handle_line(VectorType& direction)
|
constexpr bool handle_line(VectorType& direction) noexcept
|
||||||
{
|
{
|
||||||
const auto& a = m_points[0];
|
const auto& a = m_points[0];
|
||||||
const auto& b = m_points[1];
|
const auto& b = m_points[1];
|
||||||
@@ -158,21 +158,11 @@ namespace omath::collision
|
|||||||
{
|
{
|
||||||
// ReSharper disable once CppTooWideScopeInitStatement
|
// ReSharper disable once CppTooWideScopeInitStatement
|
||||||
auto n = ab.cross(ao); // Needed to valid handle collision if colliders placed at same origin pos
|
auto n = ab.cross(ao); // Needed to valid handle collision if colliders placed at same origin pos
|
||||||
if (near_zero(n))
|
direction = near_zero(n) ? any_perp(ab) : n.cross(ab);
|
||||||
{
|
return false;
|
||||||
// collinear: origin lies on ray AB (often on segment), pick any perp to escape
|
|
||||||
direction = any_perp(ab);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
direction = n.cross(ab);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*this = {a};
|
|
||||||
direction = ao;
|
|
||||||
}
|
}
|
||||||
|
*this = {a};
|
||||||
|
direction = ao;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,4 +23,52 @@ namespace omath::frostbite_engine
|
|||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
Mat4X4 calc_perspective_projection_matrix(float field_of_view, float aspect_ratio, float near, float far) noexcept;
|
Mat4X4 calc_perspective_projection_matrix(float field_of_view, float aspect_ratio, float near, float far) noexcept;
|
||||||
} // namespace omath::unity_engine
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType units_to_centimeters(const FloatingType& units)
|
||||||
|
{
|
||||||
|
return units / static_cast<FloatingType>(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType units_to_meters(const FloatingType& units)
|
||||||
|
{
|
||||||
|
return units;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType units_to_kilometers(const FloatingType& units)
|
||||||
|
{
|
||||||
|
return units_to_meters(units) / static_cast<FloatingType>(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType centimeters_to_units(const FloatingType& centimeters)
|
||||||
|
{
|
||||||
|
return centimeters * static_cast<FloatingType>(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType meters_to_units(const FloatingType& meters)
|
||||||
|
{
|
||||||
|
return meters;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType kilometers_to_units(const FloatingType& kilometers)
|
||||||
|
{
|
||||||
|
return meters_to_units(kilometers * static_cast<FloatingType>(1000));
|
||||||
|
}
|
||||||
|
} // namespace omath::frostbite_engine
|
||||||
|
|||||||
@@ -23,4 +23,54 @@ namespace omath::iw_engine
|
|||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
Mat4X4 calc_perspective_projection_matrix(float field_of_view, float aspect_ratio, float near, float far) noexcept;
|
Mat4X4 calc_perspective_projection_matrix(float field_of_view, float aspect_ratio, float near, float far) noexcept;
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType units_to_centimeters(const FloatingType& units)
|
||||||
|
{
|
||||||
|
constexpr auto centimeter_in_unit = static_cast<FloatingType>(2.54);
|
||||||
|
return units * centimeter_in_unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType units_to_meters(const FloatingType& units)
|
||||||
|
{
|
||||||
|
return units_to_centimeters(units) / static_cast<FloatingType>(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType units_to_kilometers(const FloatingType& units)
|
||||||
|
{
|
||||||
|
return units_to_meters(units) / static_cast<FloatingType>(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType centimeters_to_units(const FloatingType& centimeters)
|
||||||
|
{
|
||||||
|
constexpr auto centimeter_in_unit = static_cast<FloatingType>(2.54);
|
||||||
|
return centimeters / centimeter_in_unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType meters_to_units(const FloatingType& meters)
|
||||||
|
{
|
||||||
|
return centimeters_to_units(meters * static_cast<FloatingType>(100));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType kilometers_to_units(const FloatingType& kilometers)
|
||||||
|
{
|
||||||
|
return meters_to_units(kilometers * static_cast<FloatingType>(1000));
|
||||||
|
}
|
||||||
} // namespace omath::iw_engine
|
} // namespace omath::iw_engine
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "omath/engines/opengl_engine/constants.hpp"
|
#include "omath/engines/opengl_engine/constants.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace omath::opengl_engine
|
namespace omath::opengl_engine
|
||||||
{
|
{
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
@@ -23,4 +22,52 @@ namespace omath::opengl_engine
|
|||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
Mat4X4 calc_perspective_projection_matrix(float field_of_view, float aspect_ratio, float near, float far) noexcept;
|
Mat4X4 calc_perspective_projection_matrix(float field_of_view, float aspect_ratio, float near, float far) noexcept;
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType units_to_centimeters(const FloatingType& units)
|
||||||
|
{
|
||||||
|
return units / static_cast<FloatingType>(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType units_to_meters(const FloatingType& units)
|
||||||
|
{
|
||||||
|
return units;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType units_to_kilometers(const FloatingType& units)
|
||||||
|
{
|
||||||
|
return units_to_meters(units) / static_cast<FloatingType>(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType centimeters_to_units(const FloatingType& centimeters)
|
||||||
|
{
|
||||||
|
return centimeters * static_cast<FloatingType>(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType meters_to_units(const FloatingType& meters)
|
||||||
|
{
|
||||||
|
return meters;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType kilometers_to_units(const FloatingType& kilometers)
|
||||||
|
{
|
||||||
|
return meters_to_units(kilometers * static_cast<FloatingType>(1000));
|
||||||
|
}
|
||||||
} // namespace omath::opengl_engine
|
} // namespace omath::opengl_engine
|
||||||
|
|||||||
@@ -22,4 +22,54 @@ namespace omath::source_engine
|
|||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
Mat4X4 calc_perspective_projection_matrix(float field_of_view, float aspect_ratio, float near, float far) noexcept;
|
Mat4X4 calc_perspective_projection_matrix(float field_of_view, float aspect_ratio, float near, float far) noexcept;
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType units_to_centimeters(const FloatingType& units)
|
||||||
|
{
|
||||||
|
constexpr auto centimeter_in_unit = static_cast<FloatingType>(2.54);
|
||||||
|
return units * centimeter_in_unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType units_to_meters(const FloatingType& units)
|
||||||
|
{
|
||||||
|
return units_to_centimeters(units) / static_cast<FloatingType>(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType units_to_kilometers(const FloatingType& units)
|
||||||
|
{
|
||||||
|
return units_to_meters(units) / static_cast<FloatingType>(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType centimeters_to_units(const FloatingType& centimeters)
|
||||||
|
{
|
||||||
|
constexpr auto centimeter_in_unit = static_cast<FloatingType>(2.54);
|
||||||
|
return centimeters / centimeter_in_unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType meters_to_units(const FloatingType& meters)
|
||||||
|
{
|
||||||
|
return centimeters_to_units(meters * static_cast<FloatingType>(100));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType kilometers_to_units(const FloatingType& kilometers)
|
||||||
|
{
|
||||||
|
return meters_to_units(kilometers * static_cast<FloatingType>(1000));
|
||||||
|
}
|
||||||
} // namespace omath::source_engine
|
} // namespace omath::source_engine
|
||||||
|
|||||||
@@ -23,4 +23,52 @@ namespace omath::unity_engine
|
|||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
Mat4X4 calc_perspective_projection_matrix(float field_of_view, float aspect_ratio, float near, float far) noexcept;
|
Mat4X4 calc_perspective_projection_matrix(float field_of_view, float aspect_ratio, float near, float far) noexcept;
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType units_to_centimeters(const FloatingType& units)
|
||||||
|
{
|
||||||
|
return units / static_cast<FloatingType>(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType units_to_meters(const FloatingType& units)
|
||||||
|
{
|
||||||
|
return units;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType units_to_kilometers(const FloatingType& units)
|
||||||
|
{
|
||||||
|
return units_to_meters(units) / static_cast<FloatingType>(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType centimeters_to_units(const FloatingType& centimeters)
|
||||||
|
{
|
||||||
|
return centimeters * static_cast<FloatingType>(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType meters_to_units(const FloatingType& meters)
|
||||||
|
{
|
||||||
|
return meters;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType kilometers_to_units(const FloatingType& kilometers)
|
||||||
|
{
|
||||||
|
return meters_to_units(kilometers * static_cast<FloatingType>(1000));
|
||||||
|
}
|
||||||
} // namespace omath::unity_engine
|
} // namespace omath::unity_engine
|
||||||
|
|||||||
@@ -23,4 +23,52 @@ namespace omath::unreal_engine
|
|||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
Mat4X4 calc_perspective_projection_matrix(float field_of_view, float aspect_ratio, float near, float far) noexcept;
|
Mat4X4 calc_perspective_projection_matrix(float field_of_view, float aspect_ratio, float near, float far) noexcept;
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType units_to_centimeters(const FloatingType& units)
|
||||||
|
{
|
||||||
|
return units;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType units_to_meters(const FloatingType& units)
|
||||||
|
{
|
||||||
|
return units / static_cast<FloatingType>(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType units_to_kilometers(const FloatingType& units)
|
||||||
|
{
|
||||||
|
return units_to_meters(units) / static_cast<FloatingType>(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType centimeters_to_units(const FloatingType& centimeters)
|
||||||
|
{
|
||||||
|
return centimeters;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType meters_to_units(const FloatingType& meters)
|
||||||
|
{
|
||||||
|
return meters * static_cast<FloatingType>(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FloatingType>
|
||||||
|
requires std::is_floating_point_v<FloatingType>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr FloatingType kilometers_to_units(const FloatingType& kilometers)
|
||||||
|
{
|
||||||
|
return meters_to_units(kilometers * static_cast<FloatingType>(1000));
|
||||||
|
}
|
||||||
} // namespace omath::unreal_engine
|
} // namespace omath::unreal_engine
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by Orange on 11/13/2024.
|
|
||||||
//
|
|
||||||
#include "omath/collision/line_tracer.hpp"
|
|
||||||
|
|
||||||
namespace omath::collision
|
|
||||||
{
|
|
||||||
bool LineTracer::can_trace_line(const Ray& ray, const Triangle<Vector3<float>>& triangle) noexcept
|
|
||||||
{
|
|
||||||
return get_ray_hit_point(ray, triangle) == ray.end;
|
|
||||||
}
|
|
||||||
Vector3<float> Ray::direction_vector() const noexcept
|
|
||||||
{
|
|
||||||
return end - start;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3<float> Ray::direction_vector_normalized() const noexcept
|
|
||||||
{
|
|
||||||
return direction_vector().normalized();
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3<float> LineTracer::get_ray_hit_point(const Ray& ray, const Triangle<Vector3<float>>& triangle) noexcept
|
|
||||||
{
|
|
||||||
constexpr float k_epsilon = std::numeric_limits<float>::epsilon();
|
|
||||||
|
|
||||||
const auto side_a = triangle.side_a_vector();
|
|
||||||
const auto side_b = triangle.side_b_vector();
|
|
||||||
|
|
||||||
const auto ray_dir = ray.direction_vector();
|
|
||||||
|
|
||||||
const auto p = ray_dir.cross(side_b);
|
|
||||||
const auto det = side_a.dot(p);
|
|
||||||
|
|
||||||
if (std::abs(det) < k_epsilon)
|
|
||||||
return ray.end;
|
|
||||||
|
|
||||||
const auto inv_det = 1.0f / det;
|
|
||||||
const auto t = ray.start - triangle.m_vertex2;
|
|
||||||
const auto u = t.dot(p) * inv_det;
|
|
||||||
|
|
||||||
if ((u < 0 && std::abs(u) > k_epsilon) || (u > 1 && std::abs(u - 1) > k_epsilon))
|
|
||||||
return ray.end;
|
|
||||||
|
|
||||||
const auto q = t.cross(side_a);
|
|
||||||
// ReSharper disable once CppTooWideScopeInitStatement
|
|
||||||
const auto v = ray_dir.dot(q) * inv_det;
|
|
||||||
|
|
||||||
if ((v < 0 && std::abs(v) > k_epsilon) || (u + v > 1 && std::abs(u + v - 1) > k_epsilon))
|
|
||||||
return ray.end;
|
|
||||||
|
|
||||||
const auto t_hit = side_b.dot(q) * inv_det;
|
|
||||||
|
|
||||||
if (ray.infinite_length && t_hit <= k_epsilon)
|
|
||||||
return ray.end;
|
|
||||||
|
|
||||||
if (t_hit <= k_epsilon || t_hit > 1.0f - k_epsilon)
|
|
||||||
return ray.end;
|
|
||||||
|
|
||||||
return ray.start + ray_dir * t_hit;
|
|
||||||
}
|
|
||||||
} // namespace omath::collision
|
|
||||||
@@ -8,6 +8,125 @@
|
|||||||
#include <print>
|
#include <print>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
|
TEST(unit_test_frostbite_engine, UnitsToCentimeters_BasicValues)
|
||||||
|
{
|
||||||
|
EXPECT_FLOAT_EQ(omath::frostbite_engine::units_to_centimeters(0.0f), 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(omath::frostbite_engine::units_to_centimeters(1.0f), 0.01f);
|
||||||
|
EXPECT_FLOAT_EQ(omath::frostbite_engine::units_to_centimeters(100.0f), 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(omath::frostbite_engine::units_to_centimeters(-250.0f), -2.5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_frostbite_engine, UnitsToMeters_BasicValues)
|
||||||
|
{
|
||||||
|
EXPECT_DOUBLE_EQ(omath::frostbite_engine::units_to_meters(0.0), 0.0);
|
||||||
|
EXPECT_DOUBLE_EQ(omath::frostbite_engine::units_to_meters(1.0), 1.0);
|
||||||
|
EXPECT_DOUBLE_EQ(omath::frostbite_engine::units_to_meters(123.456), 123.456);
|
||||||
|
EXPECT_DOUBLE_EQ(omath::frostbite_engine::units_to_meters(-42.0), -42.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_frostbite_engine, UnitsToKilometers_BasicValues)
|
||||||
|
{
|
||||||
|
EXPECT_NEAR(omath::frostbite_engine::units_to_kilometers(0.0), 0.0, 1e-15);
|
||||||
|
EXPECT_NEAR(omath::frostbite_engine::units_to_kilometers(1.0), 0.001, 1e-15);
|
||||||
|
EXPECT_NEAR(omath::frostbite_engine::units_to_kilometers(1000.0), 1.0, 1e-12);
|
||||||
|
EXPECT_NEAR(omath::frostbite_engine::units_to_kilometers(-2500.0), -2.5, 1e-12);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_frostbite_engine, CentimetersToUnits_BasicValues)
|
||||||
|
{
|
||||||
|
EXPECT_FLOAT_EQ(omath::frostbite_engine::centimeters_to_units(0.0f), 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(omath::frostbite_engine::centimeters_to_units(0.01f), 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(omath::frostbite_engine::centimeters_to_units(1.0f), 100.0f);
|
||||||
|
EXPECT_FLOAT_EQ(omath::frostbite_engine::centimeters_to_units(-2.5f), -250.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_frostbite_engine, MetersToUnits_BasicValues)
|
||||||
|
{
|
||||||
|
EXPECT_DOUBLE_EQ(omath::frostbite_engine::meters_to_units(0.0), 0.0);
|
||||||
|
EXPECT_DOUBLE_EQ(omath::frostbite_engine::meters_to_units(1.0), 1.0);
|
||||||
|
EXPECT_DOUBLE_EQ(omath::frostbite_engine::meters_to_units(123.456), 123.456);
|
||||||
|
EXPECT_DOUBLE_EQ(omath::frostbite_engine::meters_to_units(-42.0), -42.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_frostbite_engine, KilometersToUnits_BasicValues)
|
||||||
|
{
|
||||||
|
EXPECT_NEAR(omath::frostbite_engine::kilometers_to_units(0.0), 0.0, 1e-12);
|
||||||
|
EXPECT_NEAR(omath::frostbite_engine::kilometers_to_units(0.001), 1.0, 1e-12);
|
||||||
|
EXPECT_NEAR(omath::frostbite_engine::kilometers_to_units(1.0), 1000.0, 1e-9);
|
||||||
|
EXPECT_NEAR(omath::frostbite_engine::kilometers_to_units(-2.5), -2500.0, 1e-9);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_frostbite_engine, RoundTrip_UnitsCentimeters)
|
||||||
|
{
|
||||||
|
constexpr float units_f = 12345.678f;
|
||||||
|
const auto cm_f = omath::frostbite_engine::units_to_centimeters(units_f);
|
||||||
|
const auto units_f_back = omath::frostbite_engine::centimeters_to_units(cm_f);
|
||||||
|
EXPECT_NEAR(units_f_back, units_f, 1e-3f);
|
||||||
|
|
||||||
|
constexpr double units_d = -987654.321;
|
||||||
|
const auto cm_d = omath::frostbite_engine::units_to_centimeters(units_d);
|
||||||
|
const auto units_d_back = omath::frostbite_engine::centimeters_to_units(cm_d);
|
||||||
|
EXPECT_NEAR(units_d_back, units_d, 1e-9);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_frostbite_engine, RoundTrip_UnitsMeters)
|
||||||
|
{
|
||||||
|
constexpr float units_f = 5432.125f;
|
||||||
|
constexpr auto m_f = omath::frostbite_engine::units_to_meters(units_f);
|
||||||
|
constexpr auto units_f_back = omath::frostbite_engine::meters_to_units(m_f);
|
||||||
|
EXPECT_FLOAT_EQ(units_f_back, units_f);
|
||||||
|
|
||||||
|
constexpr double units_d = -123456.789;
|
||||||
|
constexpr auto m_d = omath::frostbite_engine::units_to_meters(units_d);
|
||||||
|
constexpr auto units_d_back = omath::frostbite_engine::meters_to_units(m_d);
|
||||||
|
EXPECT_DOUBLE_EQ(units_d_back, units_d);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_frostbite_engine, RoundTrip_UnitsKilometers)
|
||||||
|
{
|
||||||
|
constexpr float units_f = 100000.0f;
|
||||||
|
constexpr auto km_f = omath::frostbite_engine::units_to_kilometers(units_f);
|
||||||
|
constexpr auto units_f_back = omath::frostbite_engine::kilometers_to_units(km_f);
|
||||||
|
EXPECT_NEAR(units_f_back, units_f, 1e-2f);
|
||||||
|
|
||||||
|
constexpr double units_d = -7654321.123;
|
||||||
|
constexpr auto km_d = omath::frostbite_engine::units_to_kilometers(units_d);
|
||||||
|
constexpr auto units_d_back = omath::frostbite_engine::kilometers_to_units(km_d);
|
||||||
|
EXPECT_NEAR(units_d_back, units_d, 1e-6);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_frostbite_engine, ConversionChainConsistency)
|
||||||
|
{
|
||||||
|
const double units = 424242.42;
|
||||||
|
|
||||||
|
const auto cm_direct = omath::frostbite_engine::units_to_centimeters(units);
|
||||||
|
const auto cm_via_units = units / 100.0;
|
||||||
|
EXPECT_NEAR(cm_direct, cm_via_units, 1e-12);
|
||||||
|
|
||||||
|
const auto km_direct = omath::frostbite_engine::units_to_kilometers(units);
|
||||||
|
const auto km_via_meters = omath::frostbite_engine::units_to_meters(units) / 1000.0;
|
||||||
|
EXPECT_NEAR(km_direct, km_via_meters, 1e-12);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_frostbite_engine, SupportsFloatAndDouble)
|
||||||
|
{
|
||||||
|
static_assert(std::is_same_v<decltype(omath::frostbite_engine::units_to_centimeters(1.0f)), float>);
|
||||||
|
static_assert(std::is_same_v<decltype(omath::frostbite_engine::units_to_centimeters(1.0)), double>);
|
||||||
|
static_assert(std::is_same_v<decltype(omath::frostbite_engine::meters_to_units(1.0f)), float>);
|
||||||
|
static_assert(std::is_same_v<decltype(omath::frostbite_engine::kilometers_to_units(1.0)), double>);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_frostbite_engine, ConstexprConversions)
|
||||||
|
{
|
||||||
|
constexpr double units = 1000.0;
|
||||||
|
constexpr double cm = omath::frostbite_engine::units_to_centimeters(units);
|
||||||
|
constexpr double m = omath::frostbite_engine::units_to_meters(units);
|
||||||
|
constexpr double km = omath::frostbite_engine::units_to_kilometers(units);
|
||||||
|
|
||||||
|
static_assert(cm == 10.0, "units_to_centimeters constexpr failed");
|
||||||
|
static_assert(m == 1000.0, "units_to_meters constexpr failed");
|
||||||
|
static_assert(km == 1.0, "units_to_kilometers constexpr failed");
|
||||||
|
}
|
||||||
TEST(unit_test_frostbite_engine, ForwardVector)
|
TEST(unit_test_frostbite_engine, ForwardVector)
|
||||||
{
|
{
|
||||||
const auto forward = omath::frostbite_engine::forward_vector({});
|
const auto forward = omath::frostbite_engine::forward_vector({});
|
||||||
|
|||||||
@@ -7,6 +7,125 @@
|
|||||||
#include <omath/engines/opengl_engine/formulas.hpp>
|
#include <omath/engines/opengl_engine/formulas.hpp>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
|
TEST(unit_test_opengl, UnitsToCentimeters_BasicValues)
|
||||||
|
{
|
||||||
|
EXPECT_FLOAT_EQ(omath::opengl_engine::units_to_centimeters(0.0f), 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(omath::opengl_engine::units_to_centimeters(1.0f), 0.01f);
|
||||||
|
EXPECT_FLOAT_EQ(omath::opengl_engine::units_to_centimeters(100.0f), 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(omath::opengl_engine::units_to_centimeters(-250.0f), -2.5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_opengl, UnitsToMeters_BasicValues)
|
||||||
|
{
|
||||||
|
EXPECT_DOUBLE_EQ(omath::opengl_engine::units_to_meters(0.0), 0.0);
|
||||||
|
EXPECT_DOUBLE_EQ(omath::opengl_engine::units_to_meters(1.0), 1.0);
|
||||||
|
EXPECT_DOUBLE_EQ(omath::opengl_engine::units_to_meters(123.456), 123.456);
|
||||||
|
EXPECT_DOUBLE_EQ(omath::opengl_engine::units_to_meters(-42.0), -42.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_opengl, UnitsToKilometers_BasicValues)
|
||||||
|
{
|
||||||
|
EXPECT_NEAR(omath::opengl_engine::units_to_kilometers(0.0), 0.0, 1e-15);
|
||||||
|
EXPECT_NEAR(omath::opengl_engine::units_to_kilometers(1.0), 0.001, 1e-15);
|
||||||
|
EXPECT_NEAR(omath::opengl_engine::units_to_kilometers(1000.0), 1.0, 1e-12);
|
||||||
|
EXPECT_NEAR(omath::opengl_engine::units_to_kilometers(-2500.0), -2.5, 1e-12);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_opengl, CentimetersToUnits_BasicValues)
|
||||||
|
{
|
||||||
|
EXPECT_FLOAT_EQ(omath::opengl_engine::centimeters_to_units(0.0f), 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(omath::opengl_engine::centimeters_to_units(0.01f), 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(omath::opengl_engine::centimeters_to_units(1.0f), 100.0f);
|
||||||
|
EXPECT_FLOAT_EQ(omath::opengl_engine::centimeters_to_units(-2.5f), -250.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_opengl, MetersToUnits_BasicValues)
|
||||||
|
{
|
||||||
|
EXPECT_DOUBLE_EQ(omath::opengl_engine::meters_to_units(0.0), 0.0);
|
||||||
|
EXPECT_DOUBLE_EQ(omath::opengl_engine::meters_to_units(1.0), 1.0);
|
||||||
|
EXPECT_DOUBLE_EQ(omath::opengl_engine::meters_to_units(123.456), 123.456);
|
||||||
|
EXPECT_DOUBLE_EQ(omath::opengl_engine::meters_to_units(-42.0), -42.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_opengl, KilometersToUnits_BasicValues)
|
||||||
|
{
|
||||||
|
EXPECT_NEAR(omath::opengl_engine::kilometers_to_units(0.0), 0.0, 1e-12);
|
||||||
|
EXPECT_NEAR(omath::opengl_engine::kilometers_to_units(0.001), 1.0, 1e-12);
|
||||||
|
EXPECT_NEAR(omath::opengl_engine::kilometers_to_units(1.0), 1000.0, 1e-9);
|
||||||
|
EXPECT_NEAR(omath::opengl_engine::kilometers_to_units(-2.5), -2500.0, 1e-9);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_opengl, RoundTrip_UnitsCentimeters)
|
||||||
|
{
|
||||||
|
constexpr float units_f = 12345.678f;
|
||||||
|
const auto cm_f = omath::opengl_engine::units_to_centimeters(units_f);
|
||||||
|
const auto units_f_back = omath::opengl_engine::centimeters_to_units(cm_f);
|
||||||
|
EXPECT_NEAR(units_f_back, units_f, 1e-3f);
|
||||||
|
|
||||||
|
constexpr double units_d = -987654.321;
|
||||||
|
const auto cm_d = omath::opengl_engine::units_to_centimeters(units_d);
|
||||||
|
const auto units_d_back = omath::opengl_engine::centimeters_to_units(cm_d);
|
||||||
|
EXPECT_NEAR(units_d_back, units_d, 1e-9);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_opengl, RoundTrip_UnitsMeters)
|
||||||
|
{
|
||||||
|
constexpr float units_f = 5432.125f;
|
||||||
|
const auto m_f = omath::opengl_engine::units_to_meters(units_f);
|
||||||
|
const auto units_f_back = omath::opengl_engine::meters_to_units(m_f);
|
||||||
|
EXPECT_FLOAT_EQ(units_f_back, units_f);
|
||||||
|
|
||||||
|
constexpr double units_d = -123456.789;
|
||||||
|
const auto m_d = omath::opengl_engine::units_to_meters(units_d);
|
||||||
|
const auto units_d_back = omath::opengl_engine::meters_to_units(m_d);
|
||||||
|
EXPECT_DOUBLE_EQ(units_d_back, units_d);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_opengl, RoundTrip_UnitsKilometers)
|
||||||
|
{
|
||||||
|
constexpr float units_f = 100000.0f;
|
||||||
|
const auto km_f = omath::opengl_engine::units_to_kilometers(units_f);
|
||||||
|
const auto units_f_back = omath::opengl_engine::kilometers_to_units(km_f);
|
||||||
|
EXPECT_NEAR(units_f_back, units_f, 1e-2f);
|
||||||
|
|
||||||
|
constexpr double units_d = -7654321.123;
|
||||||
|
const auto km_d = omath::opengl_engine::units_to_kilometers(units_d);
|
||||||
|
const auto units_d_back = omath::opengl_engine::kilometers_to_units(km_d);
|
||||||
|
EXPECT_NEAR(units_d_back, units_d, 1e-6);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_opengl, ConversionChainConsistency)
|
||||||
|
{
|
||||||
|
const double units = 424242.42;
|
||||||
|
|
||||||
|
const auto cm_direct = omath::opengl_engine::units_to_centimeters(units);
|
||||||
|
const auto cm_via_units = units / 100.0;
|
||||||
|
EXPECT_NEAR(cm_direct, cm_via_units, 1e-12);
|
||||||
|
|
||||||
|
const auto km_direct = omath::opengl_engine::units_to_kilometers(units);
|
||||||
|
const auto km_via_meters = omath::opengl_engine::units_to_meters(units) / 1000.0;
|
||||||
|
EXPECT_NEAR(km_direct, km_via_meters, 1e-12);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_opengl, SupportsFloatAndDouble)
|
||||||
|
{
|
||||||
|
static_assert(std::is_same_v<decltype(omath::opengl_engine::units_to_centimeters(1.0f)), float>);
|
||||||
|
static_assert(std::is_same_v<decltype(omath::opengl_engine::units_to_centimeters(1.0)), double>);
|
||||||
|
static_assert(std::is_same_v<decltype(omath::opengl_engine::meters_to_units(1.0f)), float>);
|
||||||
|
static_assert(std::is_same_v<decltype(omath::opengl_engine::kilometers_to_units(1.0)), double>);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_opengl, ConstexprConversions)
|
||||||
|
{
|
||||||
|
constexpr double units = 1000.0;
|
||||||
|
constexpr double cm = omath::opengl_engine::units_to_centimeters(units);
|
||||||
|
constexpr double m = omath::opengl_engine::units_to_meters(units);
|
||||||
|
constexpr double km = omath::opengl_engine::units_to_kilometers(units);
|
||||||
|
|
||||||
|
static_assert(cm == 10.0, "units_to_centimeters constexpr failed");
|
||||||
|
static_assert(m == 1000.0, "units_to_meters constexpr failed");
|
||||||
|
static_assert(km == 1.0, "units_to_kilometers constexpr failed");
|
||||||
|
}
|
||||||
TEST(unit_test_opengl, ForwardVector)
|
TEST(unit_test_opengl, ForwardVector)
|
||||||
{
|
{
|
||||||
const auto forward = omath::opengl_engine::forward_vector({});
|
const auto forward = omath::opengl_engine::forward_vector({});
|
||||||
|
|||||||
@@ -7,6 +7,129 @@
|
|||||||
#include <omath/engines/source_engine/formulas.hpp>
|
#include <omath/engines/source_engine/formulas.hpp>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
|
TEST(unit_test_source_engine_units, HammerUnitsToCentimeters_BasicValues)
|
||||||
|
{
|
||||||
|
EXPECT_FLOAT_EQ(omath::source_engine::units_to_centimeters(0.0f), 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(omath::source_engine::units_to_centimeters(1.0f), 2.54f);
|
||||||
|
EXPECT_FLOAT_EQ(omath::source_engine::units_to_centimeters(10.0f), 25.4f);
|
||||||
|
EXPECT_FLOAT_EQ(omath::source_engine::units_to_centimeters(-2.0f), -5.08f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_source_engine_units, HammerUnitsToMeters_BasicValues)
|
||||||
|
{
|
||||||
|
EXPECT_NEAR(omath::source_engine::units_to_meters(0.0), 0.0, 1e-12);
|
||||||
|
EXPECT_NEAR(omath::source_engine::units_to_meters(1.0), 0.0254, 1e-12);
|
||||||
|
EXPECT_NEAR(omath::source_engine::units_to_meters(100.0), 2.54, 1e-12);
|
||||||
|
EXPECT_NEAR(omath::source_engine::units_to_meters(-4.0), -0.1016, 1e-12);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_source_engine_units, HammerUnitsToKilometers_BasicValues)
|
||||||
|
{
|
||||||
|
EXPECT_NEAR(omath::source_engine::units_to_kilometers(0.0), 0.0, 1e-15);
|
||||||
|
EXPECT_NEAR(omath::source_engine::units_to_kilometers(1.0), 0.0000254, 1e-15);
|
||||||
|
EXPECT_NEAR(omath::source_engine::units_to_kilometers(1000.0), 0.0254, 1e-15);
|
||||||
|
EXPECT_NEAR(omath::source_engine::units_to_kilometers(-10.0), -0.000254, 1e-15);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_source_engine_units, CentimetersToHammerUnits_BasicValues)
|
||||||
|
{
|
||||||
|
EXPECT_FLOAT_EQ(omath::source_engine::centimeters_to_units(0.0f), 0.0f);
|
||||||
|
EXPECT_NEAR(omath::source_engine::centimeters_to_units(2.54f), 1.0f, 1e-6f);
|
||||||
|
EXPECT_NEAR(omath::source_engine::centimeters_to_units(25.4f), 10.0f, 1e-5f);
|
||||||
|
EXPECT_NEAR(omath::source_engine::centimeters_to_units(-5.08f), -2.0f, 1e-6f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_source_engine_units, MetersToHammerUnits_BasicValues)
|
||||||
|
{
|
||||||
|
EXPECT_NEAR(omath::source_engine::meters_to_units(0.0), 0.0, 1e-12);
|
||||||
|
EXPECT_NEAR(omath::source_engine::meters_to_units(0.0254), 1.0, 1e-12);
|
||||||
|
EXPECT_NEAR(omath::source_engine::meters_to_units(2.54), 100.0, 1e-10);
|
||||||
|
EXPECT_NEAR(omath::source_engine::meters_to_units(-0.0508), -2.0, 1e-12);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_source_engine_units, KilometersToHammerUnits_BasicValues)
|
||||||
|
{
|
||||||
|
EXPECT_NEAR(omath::source_engine::kilometers_to_units(0.0), 0.0, 1e-9);
|
||||||
|
EXPECT_NEAR(omath::source_engine::kilometers_to_units(0.0000254), 1.0, 1e-9);
|
||||||
|
EXPECT_NEAR(omath::source_engine::kilometers_to_units(0.00254), 100.0, 1e-7);
|
||||||
|
EXPECT_NEAR(omath::source_engine::kilometers_to_units(-0.0000508), -2.0, 1e-9);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_source_engine_units, RoundTrip_HammerToCentimetersToHammer)
|
||||||
|
{
|
||||||
|
constexpr float hu_f = 123.456f;
|
||||||
|
constexpr auto cm_f = omath::source_engine::units_to_centimeters(hu_f);
|
||||||
|
constexpr auto hu_f_back = omath::source_engine::centimeters_to_units(cm_f);
|
||||||
|
EXPECT_NEAR(hu_f_back, hu_f, 1e-5f);
|
||||||
|
|
||||||
|
constexpr double hu_d = -98765.4321;
|
||||||
|
constexpr auto cm_d = omath::source_engine::units_to_centimeters(hu_d);
|
||||||
|
constexpr auto hu_d_back = omath::source_engine::centimeters_to_units(cm_d);
|
||||||
|
EXPECT_NEAR(hu_d_back, hu_d, 1e-10);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_source_engine_units, RoundTrip_HammerToMetersToHammer)
|
||||||
|
{
|
||||||
|
constexpr float hu_f = 2500.25f;
|
||||||
|
constexpr auto m_f = omath::source_engine::units_to_meters(hu_f);
|
||||||
|
constexpr auto hu_f_back = omath::source_engine::meters_to_units(m_f);
|
||||||
|
EXPECT_NEAR(hu_f_back, hu_f, 1e-4f);
|
||||||
|
|
||||||
|
constexpr double hu_d = -42000.125;
|
||||||
|
constexpr auto m_d = omath::source_engine::units_to_meters(hu_d);
|
||||||
|
constexpr auto hu_d_back = omath::source_engine::meters_to_units(m_d);
|
||||||
|
EXPECT_NEAR(hu_d_back, hu_d, 1e-10);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_source_engine_units, RoundTrip_HammerToKilometersToHammer)
|
||||||
|
{
|
||||||
|
constexpr float hu_f = 100000.0f;
|
||||||
|
constexpr auto km_f = omath::source_engine::units_to_kilometers(hu_f);
|
||||||
|
constexpr auto hu_f_back = omath::source_engine::kilometers_to_units(km_f);
|
||||||
|
EXPECT_NEAR(hu_f_back, hu_f, 1e-2f); // looser due to float scaling
|
||||||
|
|
||||||
|
constexpr double hu_d = -1234567.89;
|
||||||
|
constexpr auto km_d = omath::source_engine::units_to_kilometers(hu_d);
|
||||||
|
constexpr auto hu_d_back = omath::source_engine::kilometers_to_units(km_d);
|
||||||
|
EXPECT_NEAR(hu_d_back, hu_d, 1e-7);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_source_engine_units, ConversionChainConsistency)
|
||||||
|
{
|
||||||
|
// hu -> cm -> m -> km should match direct helpers
|
||||||
|
constexpr auto hu = 54321.123;
|
||||||
|
|
||||||
|
constexpr auto cm = omath::source_engine::units_to_centimeters(hu);
|
||||||
|
constexpr auto m_via_cm = cm / 100.0;
|
||||||
|
constexpr auto km_via_cm = m_via_cm / 1000.0;
|
||||||
|
|
||||||
|
constexpr auto m_direct = omath::source_engine::units_to_meters(hu);
|
||||||
|
constexpr auto km_direct = omath::source_engine::units_to_kilometers(hu);
|
||||||
|
|
||||||
|
EXPECT_NEAR(m_direct, m_via_cm, 1e-12);
|
||||||
|
EXPECT_NEAR(km_direct, km_via_cm, 1e-15);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_source_engine_units, SupportsFloatAndDoubleTypes)
|
||||||
|
{
|
||||||
|
static_assert(std::is_same_v<decltype(omath::source_engine::units_to_centimeters(1.0f)), float>);
|
||||||
|
static_assert(std::is_same_v<decltype(omath::source_engine::units_to_centimeters(1.0)), double>);
|
||||||
|
static_assert(std::is_same_v<decltype(omath::source_engine::meters_to_units(1.0f)), float>);
|
||||||
|
static_assert(std::is_same_v<decltype(omath::source_engine::kilometers_to_units(1.0)), double>);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_source_engine_units, ConstexprEvaluation)
|
||||||
|
{
|
||||||
|
constexpr double hu = 10.0;
|
||||||
|
constexpr double cm = omath::source_engine::units_to_centimeters(hu);
|
||||||
|
constexpr double m = omath::source_engine::units_to_meters(hu);
|
||||||
|
constexpr double km = omath::source_engine::units_to_kilometers(hu);
|
||||||
|
|
||||||
|
static_assert(cm == 25.4, "constexpr hu->cm failed");
|
||||||
|
static_assert(m == 0.254, "constexpr hu->m failed");
|
||||||
|
static_assert(km == 0.000254, "constexpr hu->km failed");
|
||||||
|
}
|
||||||
|
|
||||||
TEST(unit_test_source_engine, ForwardVector)
|
TEST(unit_test_source_engine, ForwardVector)
|
||||||
{
|
{
|
||||||
const auto forward = omath::source_engine::forward_vector({});
|
const auto forward = omath::source_engine::forward_vector({});
|
||||||
|
|||||||
@@ -8,6 +8,126 @@
|
|||||||
#include <print>
|
#include <print>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
|
TEST(unit_test_unity_engine, UnitsToCentimeters_BasicValues)
|
||||||
|
{
|
||||||
|
EXPECT_FLOAT_EQ(omath::unity_engine::units_to_centimeters(0.0f), 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(omath::unity_engine::units_to_centimeters(1.0f), 0.01f);
|
||||||
|
EXPECT_FLOAT_EQ(omath::unity_engine::units_to_centimeters(100.0f), 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(omath::unity_engine::units_to_centimeters(-250.0f), -2.5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_unity_engine, UnitsToMeters_BasicValues)
|
||||||
|
{
|
||||||
|
EXPECT_DOUBLE_EQ(omath::unity_engine::units_to_meters(0.0), 0.0);
|
||||||
|
EXPECT_DOUBLE_EQ(omath::unity_engine::units_to_meters(1.0), 1.0);
|
||||||
|
EXPECT_DOUBLE_EQ(omath::unity_engine::units_to_meters(123.456), 123.456);
|
||||||
|
EXPECT_DOUBLE_EQ(omath::unity_engine::units_to_meters(-42.0), -42.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_unity_engine, UnitsToKilometers_BasicValues)
|
||||||
|
{
|
||||||
|
EXPECT_NEAR(omath::unity_engine::units_to_kilometers(0.0), 0.0, 1e-15);
|
||||||
|
EXPECT_NEAR(omath::unity_engine::units_to_kilometers(1.0), 0.001, 1e-15);
|
||||||
|
EXPECT_NEAR(omath::unity_engine::units_to_kilometers(1000.0), 1.0, 1e-12);
|
||||||
|
EXPECT_NEAR(omath::unity_engine::units_to_kilometers(-2500.0), -2.5, 1e-12);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_unity_engine, CentimetersToUnits_BasicValues)
|
||||||
|
{
|
||||||
|
EXPECT_FLOAT_EQ(omath::unity_engine::centimeters_to_units(0.0f), 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(omath::unity_engine::centimeters_to_units(0.01f), 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(omath::unity_engine::centimeters_to_units(1.0f), 100.0f);
|
||||||
|
EXPECT_FLOAT_EQ(omath::unity_engine::centimeters_to_units(-2.5f), -250.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_unity_engine, MetersToUnits_BasicValues)
|
||||||
|
{
|
||||||
|
EXPECT_DOUBLE_EQ(omath::unity_engine::meters_to_units(0.0), 0.0);
|
||||||
|
EXPECT_DOUBLE_EQ(omath::unity_engine::meters_to_units(1.0), 1.0);
|
||||||
|
EXPECT_DOUBLE_EQ(omath::unity_engine::meters_to_units(123.456), 123.456);
|
||||||
|
EXPECT_DOUBLE_EQ(omath::unity_engine::meters_to_units(-42.0), -42.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_unity_engine, KilometersToUnits_BasicValues)
|
||||||
|
{
|
||||||
|
EXPECT_NEAR(omath::unity_engine::kilometers_to_units(0.0), 0.0, 1e-12);
|
||||||
|
EXPECT_NEAR(omath::unity_engine::kilometers_to_units(0.001), 1.0, 1e-12);
|
||||||
|
EXPECT_NEAR(omath::unity_engine::kilometers_to_units(1.0), 1000.0, 1e-9);
|
||||||
|
EXPECT_NEAR(omath::unity_engine::kilometers_to_units(-2.5), -2500.0, 1e-9);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_unity_engine, RoundTrip_UnitsCentimeters)
|
||||||
|
{
|
||||||
|
constexpr float units_f = 12345.678f;
|
||||||
|
constexpr auto cm_f = omath::unity_engine::units_to_centimeters(units_f);
|
||||||
|
constexpr auto units_f_back = omath::unity_engine::centimeters_to_units(cm_f);
|
||||||
|
EXPECT_NEAR(units_f_back, units_f, 1e-3f);
|
||||||
|
|
||||||
|
constexpr double units_d = -987654.321;
|
||||||
|
constexpr auto cm_d = omath::unity_engine::units_to_centimeters(units_d);
|
||||||
|
constexpr auto units_d_back = omath::unity_engine::centimeters_to_units(cm_d);
|
||||||
|
EXPECT_NEAR(units_d_back, units_d, 1e-9);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_unity_engine, RoundTrip_UnitsMeters)
|
||||||
|
{
|
||||||
|
constexpr float units_f = 5432.125f;
|
||||||
|
constexpr auto m_f = omath::unity_engine::units_to_meters(units_f);
|
||||||
|
constexpr auto units_f_back = omath::unity_engine::meters_to_units(m_f);
|
||||||
|
EXPECT_FLOAT_EQ(units_f_back, units_f);
|
||||||
|
|
||||||
|
constexpr double units_d = -123456.789;
|
||||||
|
constexpr auto m_d = omath::unity_engine::units_to_meters(units_d);
|
||||||
|
constexpr auto units_d_back = omath::unity_engine::meters_to_units(m_d);
|
||||||
|
EXPECT_DOUBLE_EQ(units_d_back, units_d);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_unity_engine, RoundTrip_UnitsKilometers)
|
||||||
|
{
|
||||||
|
constexpr float units_f = 100000.0f;
|
||||||
|
constexpr auto km_f = omath::unity_engine::units_to_kilometers(units_f);
|
||||||
|
constexpr auto units_f_back = omath::unity_engine::kilometers_to_units(km_f);
|
||||||
|
EXPECT_NEAR(units_f_back, units_f, 1e-2f);
|
||||||
|
|
||||||
|
constexpr double units_d = -7654321.123;
|
||||||
|
constexpr auto km_d = omath::unity_engine::units_to_kilometers(units_d);
|
||||||
|
constexpr auto units_d_back = omath::unity_engine::kilometers_to_units(km_d);
|
||||||
|
EXPECT_NEAR(units_d_back, units_d, 1e-6);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_unity_engine, ConversionChainConsistency)
|
||||||
|
{
|
||||||
|
constexpr double units = 424242.42;
|
||||||
|
|
||||||
|
constexpr auto cm_direct = omath::unity_engine::units_to_centimeters(units);
|
||||||
|
constexpr auto cm_via_units = units / 100.0;
|
||||||
|
EXPECT_NEAR(cm_direct, cm_via_units, 1e-12);
|
||||||
|
|
||||||
|
constexpr auto km_direct = omath::unity_engine::units_to_kilometers(units);
|
||||||
|
constexpr auto km_via_meters = omath::unity_engine::units_to_meters(units) / 1000.0;
|
||||||
|
EXPECT_NEAR(km_direct, km_via_meters, 1e-12);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_unity_engine, SupportsFloatAndDouble)
|
||||||
|
{
|
||||||
|
static_assert(std::is_same_v<decltype(omath::unity_engine::units_to_centimeters(1.0f)), float>);
|
||||||
|
static_assert(std::is_same_v<decltype(omath::unity_engine::units_to_centimeters(1.0)), double>);
|
||||||
|
static_assert(std::is_same_v<decltype(omath::unity_engine::meters_to_units(1.0f)), float>);
|
||||||
|
static_assert(std::is_same_v<decltype(omath::unity_engine::kilometers_to_units(1.0)), double>);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_unity_engine, ConstexprConversions)
|
||||||
|
{
|
||||||
|
constexpr double units = 1000.0;
|
||||||
|
constexpr double cm = omath::unity_engine::units_to_centimeters(units);
|
||||||
|
constexpr double m = omath::unity_engine::units_to_meters(units);
|
||||||
|
constexpr double km = omath::unity_engine::units_to_kilometers(units);
|
||||||
|
|
||||||
|
static_assert(cm == 10.0, "units_to_centimeters constexpr failed");
|
||||||
|
static_assert(m == 1000.0, "units_to_meters constexpr failed");
|
||||||
|
static_assert(km == 1.0, "units_to_kilometers constexpr failed");
|
||||||
|
}
|
||||||
|
|
||||||
TEST(unit_test_unity_engine, ForwardVector)
|
TEST(unit_test_unity_engine, ForwardVector)
|
||||||
{
|
{
|
||||||
const auto forward = omath::unity_engine::forward_vector({});
|
const auto forward = omath::unity_engine::forward_vector({});
|
||||||
|
|||||||
@@ -239,3 +239,126 @@ TEST(unit_test_unreal_engine, loook_at_random_z_axis)
|
|||||||
}
|
}
|
||||||
EXPECT_LE(failed_points, 100);
|
EXPECT_LE(failed_points, 100);
|
||||||
}
|
}
|
||||||
|
TEST(unit_test_unreal_engine, UnitsToCentimeters_BasicValues)
|
||||||
|
{
|
||||||
|
EXPECT_FLOAT_EQ(omath::unreal_engine::units_to_centimeters(0.0f), 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(omath::unreal_engine::units_to_centimeters(1.0f), 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(omath::unreal_engine::units_to_centimeters(250.0f), 250.0f);
|
||||||
|
EXPECT_FLOAT_EQ(omath::unreal_engine::units_to_centimeters(-42.5f), -42.5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_unreal_engine, UnitsToMeters_BasicValues)
|
||||||
|
{
|
||||||
|
EXPECT_NEAR(omath::unreal_engine::units_to_meters(0.0), 0.0, 1e-15);
|
||||||
|
EXPECT_NEAR(omath::unreal_engine::units_to_meters(1.0), 0.01, 1e-15);
|
||||||
|
EXPECT_NEAR(omath::unreal_engine::units_to_meters(100.0), 1.0, 1e-12);
|
||||||
|
EXPECT_NEAR(omath::unreal_engine::units_to_meters(-250.0), -2.5, 1e-12);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_unreal_engine, UnitsToKilometers_BasicValues)
|
||||||
|
{
|
||||||
|
EXPECT_NEAR(omath::unreal_engine::units_to_kilometers(0.0), 0.0, 1e-18);
|
||||||
|
EXPECT_NEAR(omath::unreal_engine::units_to_kilometers(1.0), 0.00001, 1e-18);
|
||||||
|
EXPECT_NEAR(omath::unreal_engine::units_to_kilometers(100000.0), 1.0, 1e-12);
|
||||||
|
EXPECT_NEAR(omath::unreal_engine::units_to_kilometers(-250000.0), -2.5, 1e-12);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_unreal_engine, CentimetersToUnits_BasicValues)
|
||||||
|
{
|
||||||
|
EXPECT_FLOAT_EQ(omath::unreal_engine::centimeters_to_units(0.0f), 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(omath::unreal_engine::centimeters_to_units(1.0f), 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(omath::unreal_engine::centimeters_to_units(250.0f), 250.0f);
|
||||||
|
EXPECT_FLOAT_EQ(omath::unreal_engine::centimeters_to_units(-42.5f), -42.5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_unreal_engine, MetersToUnits_BasicValues)
|
||||||
|
{
|
||||||
|
EXPECT_NEAR(omath::unreal_engine::meters_to_units(0.0), 0.0, 1e-12);
|
||||||
|
EXPECT_NEAR(omath::unreal_engine::meters_to_units(0.01), 1.0, 1e-12);
|
||||||
|
EXPECT_NEAR(omath::unreal_engine::meters_to_units(1.0), 100.0, 1e-9);
|
||||||
|
EXPECT_NEAR(omath::unreal_engine::meters_to_units(-2.5), -250.0, 1e-9);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_unreal_engine, KilometersToUnits_BasicValues)
|
||||||
|
{
|
||||||
|
EXPECT_NEAR(omath::unreal_engine::kilometers_to_units(0.0), 0.0, 1e-9);
|
||||||
|
EXPECT_NEAR(omath::unreal_engine::kilometers_to_units(0.00001), 1.0, 1e-9);
|
||||||
|
EXPECT_NEAR(omath::unreal_engine::kilometers_to_units(1.0), 100000.0, 1e-6);
|
||||||
|
EXPECT_NEAR(omath::unreal_engine::kilometers_to_units(-2.5), -250000.0, 1e-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_unreal_engine, RoundTrip_UnitsCentimeters)
|
||||||
|
{
|
||||||
|
constexpr float units_f = 12345.678f;
|
||||||
|
constexpr auto cm_f = omath::unreal_engine::units_to_centimeters(units_f);
|
||||||
|
constexpr auto units_f_back = omath::unreal_engine::centimeters_to_units(cm_f);
|
||||||
|
EXPECT_FLOAT_EQ(units_f_back, units_f);
|
||||||
|
|
||||||
|
constexpr double units_d = -987654.321;
|
||||||
|
constexpr auto cm_d = omath::unreal_engine::units_to_centimeters(units_d);
|
||||||
|
constexpr auto units_d_back = omath::unreal_engine::centimeters_to_units(cm_d);
|
||||||
|
EXPECT_DOUBLE_EQ(units_d_back, units_d);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_unreal_engine, RoundTrip_UnitsMeters)
|
||||||
|
{
|
||||||
|
constexpr float units_f = 5432.125f;
|
||||||
|
constexpr auto m_f = omath::unreal_engine::units_to_meters(units_f);
|
||||||
|
constexpr auto units_f_back = omath::unreal_engine::meters_to_units(m_f);
|
||||||
|
EXPECT_NEAR(units_f_back, units_f, 1e-3f);
|
||||||
|
|
||||||
|
constexpr double units_d = -123456.789;
|
||||||
|
constexpr auto m_d = omath::unreal_engine::units_to_meters(units_d);
|
||||||
|
constexpr auto units_d_back = omath::unreal_engine::meters_to_units(m_d);
|
||||||
|
EXPECT_NEAR(units_d_back, units_d, 1e-9);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_unreal_engine, RoundTrip_UnitsKilometers)
|
||||||
|
{
|
||||||
|
constexpr float units_f = 100000.0f;
|
||||||
|
constexpr auto km_f = omath::unreal_engine::units_to_kilometers(units_f);
|
||||||
|
constexpr auto units_f_back = omath::unreal_engine::kilometers_to_units(km_f);
|
||||||
|
EXPECT_NEAR(units_f_back, units_f, 1e-2f);
|
||||||
|
|
||||||
|
constexpr double units_d = -7654321.123;
|
||||||
|
constexpr auto km_d = omath::unreal_engine::units_to_kilometers(units_d);
|
||||||
|
constexpr auto units_d_back = omath::unreal_engine::kilometers_to_units(km_d);
|
||||||
|
EXPECT_NEAR(units_d_back, units_d, 1e-6);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_unreal_engine, ConversionChainConsistency)
|
||||||
|
{
|
||||||
|
constexpr double units = 424242.42;
|
||||||
|
|
||||||
|
constexpr auto cm_direct = omath::unreal_engine::units_to_centimeters(units);
|
||||||
|
constexpr auto cm_expected = units; // 1 uu == 1 cm
|
||||||
|
EXPECT_NEAR(cm_direct, cm_expected, 1e-12);
|
||||||
|
|
||||||
|
constexpr auto m_direct = omath::unreal_engine::units_to_meters(units);
|
||||||
|
constexpr auto m_via_cm = cm_direct / 100.0;
|
||||||
|
EXPECT_NEAR(m_direct, m_via_cm, 1e-12);
|
||||||
|
|
||||||
|
constexpr auto km_direct = omath::unreal_engine::units_to_kilometers(units);
|
||||||
|
constexpr auto km_via_m = m_direct / 1000.0;
|
||||||
|
EXPECT_NEAR(km_direct, km_via_m, 1e-15);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_unreal_engine, SupportsFloatAndDouble)
|
||||||
|
{
|
||||||
|
static_assert(std::is_same_v<decltype(omath::unreal_engine::units_to_centimeters(1.0f)), float>);
|
||||||
|
static_assert(std::is_same_v<decltype(omath::unreal_engine::units_to_centimeters(1.0)), double>);
|
||||||
|
static_assert(std::is_same_v<decltype(omath::unreal_engine::meters_to_units(1.0f)), float>);
|
||||||
|
static_assert(std::is_same_v<decltype(omath::unreal_engine::kilometers_to_units(1.0)), double>);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(unit_test_unreal_engine, ConstexprConversions)
|
||||||
|
{
|
||||||
|
constexpr double units = 100000.0;
|
||||||
|
constexpr double cm = omath::unreal_engine::units_to_centimeters(units);
|
||||||
|
constexpr double m = omath::unreal_engine::units_to_meters(units);
|
||||||
|
constexpr double km = omath::unreal_engine::units_to_kilometers(units);
|
||||||
|
|
||||||
|
static_assert(cm == 100000.0, "units_to_centimeters constexpr failed");
|
||||||
|
static_assert(m == 1000.0, "units_to_meters constexpr failed");
|
||||||
|
static_assert(km == 1.0, "units_to_kilometers constexpr failed");
|
||||||
|
}
|
||||||
@@ -47,7 +47,7 @@ namespace
|
|||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
struct TraceCase
|
struct TraceCase
|
||||||
{
|
{
|
||||||
Ray ray;
|
Ray<> ray;
|
||||||
bool expected_clear; // true => segment does NOT hit the triangle
|
bool expected_clear; // true => segment does NOT hit the triangle
|
||||||
friend std::ostream& operator<<(std::ostream& os, const TraceCase& tc)
|
friend std::ostream& operator<<(std::ostream& os, const TraceCase& tc)
|
||||||
{
|
{
|
||||||
@@ -66,7 +66,7 @@ namespace
|
|||||||
TEST_P(CanTraceLineParam, VariousRays)
|
TEST_P(CanTraceLineParam, VariousRays)
|
||||||
{
|
{
|
||||||
const auto& [ray, expected_clear] = GetParam();
|
const auto& [ray, expected_clear] = GetParam();
|
||||||
EXPECT_EQ(LineTracer::can_trace_line(ray, triangle), expected_clear);
|
EXPECT_EQ(LineTracer<>::can_trace_line(ray, triangle), expected_clear);
|
||||||
}
|
}
|
||||||
|
|
||||||
INSTANTIATE_TEST_SUITE_P(
|
INSTANTIATE_TEST_SUITE_P(
|
||||||
@@ -91,7 +91,7 @@ namespace
|
|||||||
constexpr Ray ray{{0.3f, 0.3f, -1.f}, {0.3f, 0.3f, 1.f}};
|
constexpr Ray ray{{0.3f, 0.3f, -1.f}, {0.3f, 0.3f, 1.f}};
|
||||||
constexpr Vec3 expected{0.3f, 0.3f, 0.f};
|
constexpr Vec3 expected{0.3f, 0.3f, 0.f};
|
||||||
|
|
||||||
const Vec3 hit = LineTracer::get_ray_hit_point(ray, triangle);
|
const Vec3 hit = LineTracer<>::get_ray_hit_point(ray, triangle);
|
||||||
ASSERT_FALSE(vec_equal(hit, ray.end));
|
ASSERT_FALSE(vec_equal(hit, ray.end));
|
||||||
EXPECT_TRUE(vec_equal(hit, expected));
|
EXPECT_TRUE(vec_equal(hit, expected));
|
||||||
}
|
}
|
||||||
@@ -106,7 +106,7 @@ namespace
|
|||||||
{1001.f, 1000.f, 1000.f},
|
{1001.f, 1000.f, 1000.f},
|
||||||
{1000.f, 1001.f, 1000.f}};
|
{1000.f, 1001.f, 1000.f}};
|
||||||
|
|
||||||
EXPECT_TRUE(LineTracer::can_trace_line(short_ray, distant));
|
EXPECT_TRUE(LineTracer<>::can_trace_line(short_ray, distant));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(unit_test_unity_engine, CantHit)
|
TEST(unit_test_unity_engine, CantHit)
|
||||||
@@ -115,13 +115,13 @@ namespace
|
|||||||
|
|
||||||
constexpr Ray ray{{}, {1.0, 0, 0}, false};
|
constexpr Ray ray{{}, {1.0, 0, 0}, false};
|
||||||
|
|
||||||
EXPECT_TRUE(omath::collision::LineTracer::can_trace_line(ray, triangle));
|
EXPECT_TRUE(omath::collision::LineTracer<>::can_trace_line(ray, triangle));
|
||||||
}
|
}
|
||||||
TEST(unit_test_unity_engine, CanHit)
|
TEST(unit_test_unity_engine, CanHit)
|
||||||
{
|
{
|
||||||
constexpr omath::Triangle<Vector3<float>> triangle{{2, 0, 0}, {2, 2, 0}, {2, 2, 2}};
|
constexpr omath::Triangle<Vector3<float>> triangle{{2, 0, 0}, {2, 2, 0}, {2, 2, 2}};
|
||||||
|
|
||||||
constexpr Ray ray{{}, {2.1, 0, 0}, false};
|
constexpr Ray ray{{}, {2.1, 0, 0}, false};
|
||||||
EXPECT_FALSE(omath::collision::LineTracer::can_trace_line(ray, triangle));
|
EXPECT_FALSE(omath::collision::LineTracer<>::can_trace_line(ray, triangle));
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ TEST(LineTracerTests, ParallelRayReturnsEnd)
|
|||||||
ray.end = Vector3<float>{1.f,1.f,1.f};
|
ray.end = Vector3<float>{1.f,1.f,1.f};
|
||||||
|
|
||||||
// For a ray parallel to the triangle plane the algorithm should return ray.end
|
// For a ray parallel to the triangle plane the algorithm should return ray.end
|
||||||
const auto hit = omath::collision::LineTracer::get_ray_hit_point(ray, tri);
|
const auto hit = omath::collision::LineTracer<>::get_ray_hit_point(ray, tri);
|
||||||
EXPECT_TRUE(hit == ray.end);
|
EXPECT_TRUE(hit == ray.end);
|
||||||
EXPECT_TRUE(omath::collision::LineTracer::can_trace_line(ray, tri));
|
EXPECT_TRUE(omath::collision::LineTracer<>::can_trace_line(ray, tri));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(LineTracerTests, MissesTriangleReturnsEnd)
|
TEST(LineTracerTests, MissesTriangleReturnsEnd)
|
||||||
@@ -27,7 +27,7 @@ TEST(LineTracerTests, MissesTriangleReturnsEnd)
|
|||||||
ray.start = Vector3<float>{2.f,2.f,-1.f};
|
ray.start = Vector3<float>{2.f,2.f,-1.f};
|
||||||
ray.end = Vector3<float>{2.f,2.f,1.f}; // passes above the triangle area
|
ray.end = Vector3<float>{2.f,2.f,1.f}; // passes above the triangle area
|
||||||
|
|
||||||
const auto hit = omath::collision::LineTracer::get_ray_hit_point(ray, tri);
|
const auto hit = omath::collision::LineTracer<>::get_ray_hit_point(ray, tri);
|
||||||
EXPECT_TRUE(hit == ray.end);
|
EXPECT_TRUE(hit == ray.end);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ TEST(LineTracerTests, HitTriangleReturnsPointInsideSegment)
|
|||||||
ray.start = Vector3<float>{0.25f,0.25f,-1.f};
|
ray.start = Vector3<float>{0.25f,0.25f,-1.f};
|
||||||
ray.end = Vector3<float>{0.25f,0.25f,1.f};
|
ray.end = Vector3<float>{0.25f,0.25f,1.f};
|
||||||
|
|
||||||
const auto hit = omath::collision::LineTracer::get_ray_hit_point(ray, tri);
|
const auto hit = omath::collision::LineTracer<>::get_ray_hit_point(ray, tri);
|
||||||
// Should return a point between start and end (z approximately 0)
|
// Should return a point between start and end (z approximately 0)
|
||||||
EXPECT_NE(hit, ray.end);
|
EXPECT_NE(hit, ray.end);
|
||||||
EXPECT_NEAR(hit.z, 0.f, 1e-4f);
|
EXPECT_NEAR(hit.z, 0.f, 1e-4f);
|
||||||
@@ -60,6 +60,6 @@ TEST(LineTracerTests, InfiniteLengthEarlyOut)
|
|||||||
|
|
||||||
// If t_hit <= epsilon the algorithm should return ray.end when infinite_length is true.
|
// If t_hit <= epsilon the algorithm should return ray.end when infinite_length is true.
|
||||||
// Using start on the triangle plane should produce t_hit <= epsilon.
|
// Using start on the triangle plane should produce t_hit <= epsilon.
|
||||||
const auto hit = omath::collision::LineTracer::get_ray_hit_point(ray, tri);
|
const auto hit = omath::collision::LineTracer<>::get_ray_hit_point(ray, tri);
|
||||||
EXPECT_TRUE(hit == ray.end);
|
EXPECT_TRUE(hit == ray.end);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ TEST(LineTracerExtra, MissParallel)
|
|||||||
{
|
{
|
||||||
constexpr Triangle<Vector3<float>> tri({0,0,0},{1,0,0},{0,1,0});
|
constexpr Triangle<Vector3<float>> tri({0,0,0},{1,0,0},{0,1,0});
|
||||||
constexpr Ray ray{ {0.3f,0.3f,1.f}, {0.3f,0.3f,2.f}, false }; // parallel above triangle
|
constexpr Ray ray{ {0.3f,0.3f,1.f}, {0.3f,0.3f,2.f}, false }; // parallel above triangle
|
||||||
const auto hit = LineTracer::get_ray_hit_point(ray, tri);
|
const auto hit = LineTracer<>::get_ray_hit_point(ray, tri);
|
||||||
EXPECT_EQ(hit, ray.end);
|
EXPECT_EQ(hit, ray.end);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ TEST(LineTracerExtra, HitCenter)
|
|||||||
{
|
{
|
||||||
constexpr Triangle<Vector3<float>> tri({0,0,0},{1,0,0},{0,1,0});
|
constexpr Triangle<Vector3<float>> tri({0,0,0},{1,0,0},{0,1,0});
|
||||||
constexpr Ray ray{ {0.3f,0.3f,-1.f}, {0.3f,0.3f,1.f}, false };
|
constexpr Ray ray{ {0.3f,0.3f,-1.f}, {0.3f,0.3f,1.f}, false };
|
||||||
const auto hit = LineTracer::get_ray_hit_point(ray, tri);
|
const auto hit = LineTracer<>::get_ray_hit_point(ray, tri);
|
||||||
ASSERT_FALSE(hit == ray.end);
|
ASSERT_FALSE(hit == ray.end);
|
||||||
EXPECT_NEAR(hit.x, 0.3f, 1e-6f);
|
EXPECT_NEAR(hit.x, 0.3f, 1e-6f);
|
||||||
EXPECT_NEAR(hit.y, 0.3f, 1e-6f);
|
EXPECT_NEAR(hit.y, 0.3f, 1e-6f);
|
||||||
@@ -30,7 +30,7 @@ TEST(LineTracerExtra, HitOnEdge)
|
|||||||
constexpr Triangle<Vector3<float>> tri({0,0,0},{1,0,0},{0,1,0});
|
constexpr Triangle<Vector3<float>> tri({0,0,0},{1,0,0},{0,1,0});
|
||||||
constexpr Ray ray{ {0.0f,0.0f,1.f}, {0.0f,0.0f,0.f}, false };
|
constexpr Ray ray{ {0.0f,0.0f,1.f}, {0.0f,0.0f,0.f}, false };
|
||||||
// hitting exact vertex/edge may be considered miss; ensure function handles without crash
|
// hitting exact vertex/edge may be considered miss; ensure function handles without crash
|
||||||
if (const auto hit = LineTracer::get_ray_hit_point(ray, tri); hit != ray.end)
|
if (const auto hit = LineTracer<>::get_ray_hit_point(ray, tri); hit != ray.end)
|
||||||
{
|
{
|
||||||
EXPECT_NEAR(hit.x, 0.0f, 1e-6f);
|
EXPECT_NEAR(hit.x, 0.0f, 1e-6f);
|
||||||
EXPECT_NEAR(hit.y, 0.0f, 1e-6f);
|
EXPECT_NEAR(hit.y, 0.0f, 1e-6f);
|
||||||
@@ -42,6 +42,6 @@ TEST(LineTracerExtra, InfiniteRayIgnoredIfBehind)
|
|||||||
constexpr Triangle<Vector3<float>> tri({0,0,0},{1,0,0},{0,1,0});
|
constexpr Triangle<Vector3<float>> tri({0,0,0},{1,0,0},{0,1,0});
|
||||||
// Ray pointing away but infinite_length true should be ignored
|
// Ray pointing away but infinite_length true should be ignored
|
||||||
constexpr Ray ray{ {0.5f,0.5f,-1.f}, {0.5f,0.5f,-2.f}, true };
|
constexpr Ray ray{ {0.5f,0.5f,-1.f}, {0.5f,0.5f,-2.f}, true };
|
||||||
const auto hit = LineTracer::get_ray_hit_point(ray, tri);
|
const auto hit = LineTracer<>::get_ray_hit_point(ray, tri);
|
||||||
EXPECT_EQ(hit, ray.end);
|
EXPECT_EQ(hit, ray.end);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ TEST(LineTracerMore, ParallelRayReturnsEnd)
|
|||||||
constexpr Triangle3 tri(Vector3<float>{0.f,0.f,0.f}, Vector3<float>{1.f,0.f,0.f}, Vector3<float>{0.f,1.f,0.f});
|
constexpr Triangle3 tri(Vector3<float>{0.f,0.f,0.f}, Vector3<float>{1.f,0.f,0.f}, Vector3<float>{0.f,1.f,0.f});
|
||||||
Ray ray; ray.start = {0.f,0.f,1.f}; ray.end = {1.f,0.f,1.f};
|
Ray ray; ray.start = {0.f,0.f,1.f}; ray.end = {1.f,0.f,1.f};
|
||||||
|
|
||||||
const auto hit = LineTracer::get_ray_hit_point(ray, tri);
|
const auto hit = LineTracer<>::get_ray_hit_point(ray, tri);
|
||||||
EXPECT_EQ(hit, ray.end);
|
EXPECT_EQ(hit, ray.end);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ TEST(LineTracerMore, UOutOfRangeReturnsEnd)
|
|||||||
constexpr Triangle3 tri(Vector3<float>{0.f,0.f,0.f}, Vector3<float>{1.f,0.f,0.f}, Vector3<float>{0.f,1.f,0.f});
|
constexpr Triangle3 tri(Vector3<float>{0.f,0.f,0.f}, Vector3<float>{1.f,0.f,0.f}, Vector3<float>{0.f,1.f,0.f});
|
||||||
Ray ray; ray.start = {-1.f,-1.f,-1.f}; ray.end = {-0.5f,-1.f,1.f};
|
Ray ray; ray.start = {-1.f,-1.f,-1.f}; ray.end = {-0.5f,-1.f,1.f};
|
||||||
|
|
||||||
const auto hit = LineTracer::get_ray_hit_point(ray, tri);
|
const auto hit = LineTracer<>::get_ray_hit_point(ray, tri);
|
||||||
EXPECT_EQ(hit, ray.end);
|
EXPECT_EQ(hit, ray.end);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ TEST(LineTracerMore, VOutOfRangeReturnsEnd)
|
|||||||
constexpr Triangle3 tri(Vector3<float>{0.f,0.f,0.f}, Vector3<float>{1.f,0.f,0.f}, Vector3<float>{0.f,1.f,0.f});
|
constexpr Triangle3 tri(Vector3<float>{0.f,0.f,0.f}, Vector3<float>{1.f,0.f,0.f}, Vector3<float>{0.f,1.f,0.f});
|
||||||
Ray ray; ray.start = {2.f,2.f,-1.f}; ray.end = {2.f,2.f,1.f};
|
Ray ray; ray.start = {2.f,2.f,-1.f}; ray.end = {2.f,2.f,1.f};
|
||||||
|
|
||||||
const auto hit = LineTracer::get_ray_hit_point(ray, tri);
|
const auto hit = LineTracer<>::get_ray_hit_point(ray, tri);
|
||||||
EXPECT_EQ(hit, ray.end);
|
EXPECT_EQ(hit, ray.end);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ TEST(LineTracerMore, THitTooSmallReturnsEnd)
|
|||||||
constexpr Triangle3 tri(Vector3<float>{0.f,0.f,0.f}, Vector3<float>{1.f,0.f,0.f}, Vector3<float>{0.f,1.f,0.f});
|
constexpr Triangle3 tri(Vector3<float>{0.f,0.f,0.f}, Vector3<float>{1.f,0.f,0.f}, Vector3<float>{0.f,1.f,0.f});
|
||||||
Ray ray; ray.start = {0.f,0.f,0.0000000001f}; ray.end = {0.f,0.f,1.f};
|
Ray ray; ray.start = {0.f,0.f,0.0000000001f}; ray.end = {0.f,0.f,1.f};
|
||||||
|
|
||||||
const auto hit = LineTracer::get_ray_hit_point(ray, tri);
|
const auto hit = LineTracer<>::get_ray_hit_point(ray, tri);
|
||||||
EXPECT_EQ(hit, ray.end);
|
EXPECT_EQ(hit, ray.end);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ TEST(LineTracerMore, THitGreaterThanOneReturnsEnd)
|
|||||||
// Choose a ray and compute t_hit locally to assert consistency
|
// Choose a ray and compute t_hit locally to assert consistency
|
||||||
Ray ray; ray.start = {0.f,0.f,-1.f}; ray.end = {0.f,0.f,-0.5f};
|
Ray ray; ray.start = {0.f,0.f,-1.f}; ray.end = {0.f,0.f,-0.5f};
|
||||||
|
|
||||||
const auto hit = LineTracer::get_ray_hit_point(ray, tri);
|
const auto hit = LineTracer<>::get_ray_hit_point(ray, tri);
|
||||||
|
|
||||||
constexpr float k_epsilon = std::numeric_limits<float>::epsilon();
|
constexpr float k_epsilon = std::numeric_limits<float>::epsilon();
|
||||||
constexpr auto side_a = tri.side_a_vector();
|
constexpr auto side_a = tri.side_a_vector();
|
||||||
@@ -87,7 +87,7 @@ TEST(LineTracerMore, InfiniteLengthWithSmallTHitReturnsEnd)
|
|||||||
// Create triangle slightly behind so t_hit <= eps
|
// Create triangle slightly behind so t_hit <= eps
|
||||||
tri = tri2;
|
tri = tri2;
|
||||||
|
|
||||||
const auto hit = LineTracer::get_ray_hit_point(ray, tri);
|
const auto hit = LineTracer<>::get_ray_hit_point(ray, tri);
|
||||||
EXPECT_EQ(hit, ray.end);
|
EXPECT_EQ(hit, ray.end);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@ TEST(LineTracerMore, SuccessfulHitReturnsPoint)
|
|||||||
constexpr Triangle3 tri(Vector3<float>{0.f,0.f,0.f}, Vector3<float>{1.f,0.f,0.f}, Vector3<float>{0.f,1.f,0.f});
|
constexpr Triangle3 tri(Vector3<float>{0.f,0.f,0.f}, Vector3<float>{1.f,0.f,0.f}, Vector3<float>{0.f,1.f,0.f});
|
||||||
Ray ray; ray.start = {0.1f,0.1f,-1.f}; ray.end = {0.1f,0.1f,1.f};
|
Ray ray; ray.start = {0.1f,0.1f,-1.f}; ray.end = {0.1f,0.1f,1.f};
|
||||||
|
|
||||||
const auto hit = LineTracer::get_ray_hit_point(ray, tri);
|
const auto hit = LineTracer<>::get_ray_hit_point(ray, tri);
|
||||||
EXPECT_NE(hit, ray.end);
|
EXPECT_NE(hit, ray.end);
|
||||||
// Hit should be on plane z=0 and near x=0.1,y=0.1
|
// Hit should be on plane z=0 and near x=0.1,y=0.1
|
||||||
EXPECT_NEAR(hit.z, 0.f, 1e-6f);
|
EXPECT_NEAR(hit.z, 0.f, 1e-6f);
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ TEST(LineTracerMore2, UGreaterThanOneReturnsEnd)
|
|||||||
// choose ray so barycentric u > 1
|
// choose ray so barycentric u > 1
|
||||||
Ray ray; ray.start = {2.f, -1.f, -1.f}; ray.end = {2.f, -1.f, 1.f};
|
Ray ray; ray.start = {2.f, -1.f, -1.f}; ray.end = {2.f, -1.f, 1.f};
|
||||||
|
|
||||||
const auto hit = LineTracer::get_ray_hit_point(ray, tri);
|
const auto hit = LineTracer<>::get_ray_hit_point(ray, tri);
|
||||||
EXPECT_EQ(hit, ray.end);
|
EXPECT_EQ(hit, ray.end);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ TEST(LineTracerMore2, VGreaterThanOneReturnsEnd)
|
|||||||
// choose ray so barycentric v > 1
|
// choose ray so barycentric v > 1
|
||||||
Ray ray; ray.start = {-1.f, 2.f, -1.f}; ray.end = {-1.f, 2.f, 1.f};
|
Ray ray; ray.start = {-1.f, 2.f, -1.f}; ray.end = {-1.f, 2.f, 1.f};
|
||||||
|
|
||||||
const auto hit = LineTracer::get_ray_hit_point(ray, tri);
|
const auto hit = LineTracer<>::get_ray_hit_point(ray, tri);
|
||||||
EXPECT_EQ(hit, ray.end);
|
EXPECT_EQ(hit, ray.end);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ TEST(LineTracerMore2, UPlusVGreaterThanOneReturnsEnd)
|
|||||||
// Ray aimed so u+v > 1 (outside triangle region)
|
// Ray aimed so u+v > 1 (outside triangle region)
|
||||||
Ray ray; ray.start = {1.f, 1.f, -1.f}; ray.end = {1.f, 1.f, 1.f};
|
Ray ray; ray.start = {1.f, 1.f, -1.f}; ray.end = {1.f, 1.f, 1.f};
|
||||||
|
|
||||||
const auto hit = LineTracer::get_ray_hit_point(ray, tri);
|
const auto hit = LineTracer<>::get_ray_hit_point(ray, tri);
|
||||||
EXPECT_EQ(hit, ray.end);
|
EXPECT_EQ(hit, ray.end);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,6 +52,6 @@ TEST(LineTracerMore2, ZeroLengthRayHandled)
|
|||||||
Ray ray; ray.start = {0.f,0.f,0.f}; ray.end = {0.f,0.f,0.f};
|
Ray ray; ray.start = {0.f,0.f,0.f}; ray.end = {0.f,0.f,0.f};
|
||||||
|
|
||||||
// Zero-length ray: direction length == 0; algorithm should handle without crash
|
// Zero-length ray: direction length == 0; algorithm should handle without crash
|
||||||
const auto hit = LineTracer::get_ray_hit_point(ray, tri);
|
const auto hit = LineTracer<>::get_ray_hit_point(ray, tri);
|
||||||
EXPECT_EQ(hit, ray.end);
|
EXPECT_EQ(hit, ray.end);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ namespace
|
|||||||
constexpr std::uint32_t lc_segment = 0x1;
|
constexpr std::uint32_t lc_segment = 0x1;
|
||||||
constexpr std::uint32_t lc_segment_64 = 0x19;
|
constexpr std::uint32_t lc_segment_64 = 0x19;
|
||||||
|
|
||||||
|
constexpr std::string_view segment_name = "__TEXT";
|
||||||
|
constexpr std::string_view section_name = "__text";
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
struct MachHeader64
|
struct MachHeader64
|
||||||
{
|
{
|
||||||
@@ -117,7 +119,6 @@ namespace
|
|||||||
constexpr std::size_t segment_size = sizeof(SegmentCommand64);
|
constexpr std::size_t segment_size = sizeof(SegmentCommand64);
|
||||||
constexpr std::size_t section_size = sizeof(Section64);
|
constexpr std::size_t section_size = sizeof(Section64);
|
||||||
constexpr std::size_t load_cmd_size = segment_size + section_size;
|
constexpr std::size_t load_cmd_size = segment_size + section_size;
|
||||||
|
|
||||||
// Section data will start after headers
|
// Section data will start after headers
|
||||||
const std::size_t section_offset = header_size + load_cmd_size;
|
const std::size_t section_offset = header_size + load_cmd_size;
|
||||||
|
|
||||||
@@ -138,7 +139,7 @@ namespace
|
|||||||
SegmentCommand64 segment{};
|
SegmentCommand64 segment{};
|
||||||
segment.cmd = lc_segment_64;
|
segment.cmd = lc_segment_64;
|
||||||
segment.cmdsize = static_cast<std::uint32_t>(load_cmd_size);
|
segment.cmdsize = static_cast<std::uint32_t>(load_cmd_size);
|
||||||
std::strncpy(segment.segname, "__TEXT", 16);
|
std::ranges::copy(segment_name, segment.segname);
|
||||||
segment.vmaddr = 0x100000000;
|
segment.vmaddr = 0x100000000;
|
||||||
segment.vmsize = section_bytes.size();
|
segment.vmsize = section_bytes.size();
|
||||||
segment.fileoff = section_offset;
|
segment.fileoff = section_offset;
|
||||||
@@ -152,8 +153,8 @@ namespace
|
|||||||
|
|
||||||
// Create section
|
// Create section
|
||||||
Section64 section{};
|
Section64 section{};
|
||||||
std::strncpy(section.sectname, "__text", 16);
|
std::ranges::copy(section_name, section.sectname);
|
||||||
std::strncpy(section.segname, "__TEXT", 16);
|
std::ranges::copy(segment_name, segment.segname);
|
||||||
section.addr = 0x100000000;
|
section.addr = 0x100000000;
|
||||||
section.size = section_bytes.size();
|
section.size = section_bytes.size();
|
||||||
section.offset = static_cast<std::uint32_t>(section_offset);
|
section.offset = static_cast<std::uint32_t>(section_offset);
|
||||||
@@ -188,7 +189,7 @@ namespace
|
|||||||
constexpr std::size_t load_cmd_size = segment_size + section_size;
|
constexpr std::size_t load_cmd_size = segment_size + section_size;
|
||||||
|
|
||||||
// Section data will start after headers
|
// Section data will start after headers
|
||||||
const std::size_t section_offset = header_size + load_cmd_size;
|
constexpr std::size_t section_offset = header_size + load_cmd_size;
|
||||||
|
|
||||||
// Create Mach-O header
|
// Create Mach-O header
|
||||||
MachHeader32 header{};
|
MachHeader32 header{};
|
||||||
@@ -206,7 +207,7 @@ namespace
|
|||||||
SegmentCommand32 segment{};
|
SegmentCommand32 segment{};
|
||||||
segment.cmd = lc_segment;
|
segment.cmd = lc_segment;
|
||||||
segment.cmdsize = static_cast<std::uint32_t>(load_cmd_size);
|
segment.cmdsize = static_cast<std::uint32_t>(load_cmd_size);
|
||||||
std::strncpy(segment.segname, "__TEXT", 16);
|
std::ranges::copy(segment_name, segment.segname);
|
||||||
segment.vmaddr = 0x1000;
|
segment.vmaddr = 0x1000;
|
||||||
segment.vmsize = static_cast<std::uint32_t>(section_bytes.size());
|
segment.vmsize = static_cast<std::uint32_t>(section_bytes.size());
|
||||||
segment.fileoff = static_cast<std::uint32_t>(section_offset);
|
segment.fileoff = static_cast<std::uint32_t>(section_offset);
|
||||||
@@ -220,8 +221,8 @@ namespace
|
|||||||
|
|
||||||
// Create section
|
// Create section
|
||||||
Section32 section{};
|
Section32 section{};
|
||||||
std::strncpy(section.sectname, "__text", 16);
|
std::ranges::copy(section_name, section.sectname);
|
||||||
std::strncpy(section.segname, "__TEXT", 16);
|
std::ranges::copy(segment_name, segment.segname);
|
||||||
section.addr = 0x1000;
|
section.addr = 0x1000;
|
||||||
section.size = static_cast<std::uint32_t>(section_bytes.size());
|
section.size = static_cast<std::uint32_t>(section_bytes.size());
|
||||||
section.offset = static_cast<std::uint32_t>(section_offset);
|
section.offset = static_cast<std::uint32_t>(section_offset);
|
||||||
|
|||||||
@@ -12,5 +12,5 @@ TEST(test, test)
|
|||||||
{0.f, 30.f, 0.f}, {}, omath::opengl_engine::k_abs_forward, omath::opengl_engine::k_abs_right);
|
{0.f, 30.f, 0.f}, {}, omath::opengl_engine::k_abs_forward, omath::opengl_engine::k_abs_right);
|
||||||
|
|
||||||
omath::collision::Ray ray{.start = {0, 0, 0}, .end = {-100, 0, 0}};
|
omath::collision::Ray ray{.start = {0, 0, 0}, .end = {-100, 0, 0}};
|
||||||
std::ignore = omath::collision::LineTracer::get_ray_hit_point(ray, result);
|
std::ignore = omath::collision::LineTracer<>::get_ray_hit_point(ray, result);
|
||||||
}
|
}
|
||||||
@@ -27,10 +27,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"examples": {
|
"examples": {
|
||||||
"description": "Build benchmarks",
|
"description": "Build examples",
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
"glfw3",
|
"glfw3",
|
||||||
"glew"
|
"glew",
|
||||||
|
"opengl"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"imgui": {
|
"imgui": {
|
||||||
|
|||||||
Reference in New Issue
Block a user