mirror of
https://github.com/orange-cpp/omath.git
synced 2026-04-20 07:23:27 +00:00
added new methods
This commit is contained in:
@@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
namespace omath::primitives
|
namespace omath::primitives
|
||||||
{
|
{
|
||||||
|
enum class UpAxis { X, Y, Z };
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
struct Aabb final
|
struct Aabb final
|
||||||
{
|
{
|
||||||
@@ -24,6 +26,37 @@ namespace omath::primitives
|
|||||||
{
|
{
|
||||||
return (max - min) / static_cast<Type>(2);
|
return (max - min) / static_cast<Type>(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<UpAxis Up = UpAxis::Y>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr Vector3<Type> top() const noexcept
|
||||||
|
{
|
||||||
|
const auto aabb_center = center();
|
||||||
|
if constexpr (Up == UpAxis::Z)
|
||||||
|
return {aabb_center.x, aabb_center.y, max.z};
|
||||||
|
else if constexpr (Up == UpAxis::X)
|
||||||
|
return {max.x, aabb_center.y, aabb_center.z};
|
||||||
|
else if constexpr (Up == UpAxis::Y)
|
||||||
|
return {aabb_center.x, max.y, aabb_center.z};
|
||||||
|
else
|
||||||
|
std::unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<UpAxis Up = UpAxis::Y>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr Vector3<Type> bottom() const noexcept
|
||||||
|
{
|
||||||
|
const auto aabb_center = center();
|
||||||
|
if constexpr (Up == UpAxis::Z)
|
||||||
|
return {aabb_center.x, aabb_center.y, min.z};
|
||||||
|
else if constexpr (Up == UpAxis::X)
|
||||||
|
return {min.x, aabb_center.y, aabb_center.z};
|
||||||
|
else if constexpr (Up == UpAxis::Y)
|
||||||
|
return {aabb_center.x, min.y, aabb_center.z};
|
||||||
|
else
|
||||||
|
std::unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr bool is_collide(const Aabb& other) const noexcept
|
constexpr bool is_collide(const Aabb& other) const noexcept
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ using Vec3 = omath::Vector3<float>;
|
|||||||
|
|
||||||
TEST(AabbTests, CenterOfSymmetricBox)
|
TEST(AabbTests, CenterOfSymmetricBox)
|
||||||
{
|
{
|
||||||
const AABB box{{-1.f, -1.f, -1.f}, {1.f, 1.f, 1.f}};
|
constexpr AABB box{{-1.f, -1.f, -1.f}, {1.f, 1.f, 1.f}};
|
||||||
const auto c = box.center();
|
constexpr auto c = box.center();
|
||||||
EXPECT_FLOAT_EQ(c.x, 0.f);
|
EXPECT_FLOAT_EQ(c.x, 0.f);
|
||||||
EXPECT_FLOAT_EQ(c.y, 0.f);
|
EXPECT_FLOAT_EQ(c.y, 0.f);
|
||||||
EXPECT_FLOAT_EQ(c.z, 0.f);
|
EXPECT_FLOAT_EQ(c.z, 0.f);
|
||||||
@@ -20,8 +20,8 @@ TEST(AabbTests, CenterOfSymmetricBox)
|
|||||||
|
|
||||||
TEST(AabbTests, CenterOfOffsetBox)
|
TEST(AabbTests, CenterOfOffsetBox)
|
||||||
{
|
{
|
||||||
const AABB box{{1.f, 2.f, 3.f}, {3.f, 6.f, 7.f}};
|
constexpr AABB box{{1.f, 2.f, 3.f}, {3.f, 6.f, 7.f}};
|
||||||
const auto c = box.center();
|
constexpr auto c = box.center();
|
||||||
EXPECT_FLOAT_EQ(c.x, 2.f);
|
EXPECT_FLOAT_EQ(c.x, 2.f);
|
||||||
EXPECT_FLOAT_EQ(c.y, 4.f);
|
EXPECT_FLOAT_EQ(c.y, 4.f);
|
||||||
EXPECT_FLOAT_EQ(c.z, 5.f);
|
EXPECT_FLOAT_EQ(c.z, 5.f);
|
||||||
@@ -29,8 +29,8 @@ TEST(AabbTests, CenterOfOffsetBox)
|
|||||||
|
|
||||||
TEST(AabbTests, CenterOfDegenerateBox)
|
TEST(AabbTests, CenterOfDegenerateBox)
|
||||||
{
|
{
|
||||||
const AABB box{{5.f, 5.f, 5.f}, {5.f, 5.f, 5.f}};
|
constexpr AABB box{{5.f, 5.f, 5.f}, {5.f, 5.f, 5.f}};
|
||||||
const auto c = box.center();
|
constexpr auto c = box.center();
|
||||||
EXPECT_FLOAT_EQ(c.x, 5.f);
|
EXPECT_FLOAT_EQ(c.x, 5.f);
|
||||||
EXPECT_FLOAT_EQ(c.y, 5.f);
|
EXPECT_FLOAT_EQ(c.y, 5.f);
|
||||||
EXPECT_FLOAT_EQ(c.z, 5.f);
|
EXPECT_FLOAT_EQ(c.z, 5.f);
|
||||||
@@ -40,8 +40,8 @@ TEST(AabbTests, CenterOfDegenerateBox)
|
|||||||
|
|
||||||
TEST(AabbTests, ExtentsOfSymmetricBox)
|
TEST(AabbTests, ExtentsOfSymmetricBox)
|
||||||
{
|
{
|
||||||
const AABB box{{-2.f, -3.f, -4.f}, {2.f, 3.f, 4.f}};
|
constexpr AABB box{{-2.f, -3.f, -4.f}, {2.f, 3.f, 4.f}};
|
||||||
const auto e = box.extents();
|
constexpr auto e = box.extents();
|
||||||
EXPECT_FLOAT_EQ(e.x, 2.f);
|
EXPECT_FLOAT_EQ(e.x, 2.f);
|
||||||
EXPECT_FLOAT_EQ(e.y, 3.f);
|
EXPECT_FLOAT_EQ(e.y, 3.f);
|
||||||
EXPECT_FLOAT_EQ(e.z, 4.f);
|
EXPECT_FLOAT_EQ(e.z, 4.f);
|
||||||
@@ -49,8 +49,8 @@ TEST(AabbTests, ExtentsOfSymmetricBox)
|
|||||||
|
|
||||||
TEST(AabbTests, ExtentsOfUnitBox)
|
TEST(AabbTests, ExtentsOfUnitBox)
|
||||||
{
|
{
|
||||||
const AABB box{{0.f, 0.f, 0.f}, {2.f, 2.f, 2.f}};
|
constexpr AABB box{{0.f, 0.f, 0.f}, {2.f, 2.f, 2.f}};
|
||||||
const auto e = box.extents();
|
constexpr auto e = box.extents();
|
||||||
EXPECT_FLOAT_EQ(e.x, 1.f);
|
EXPECT_FLOAT_EQ(e.x, 1.f);
|
||||||
EXPECT_FLOAT_EQ(e.y, 1.f);
|
EXPECT_FLOAT_EQ(e.y, 1.f);
|
||||||
EXPECT_FLOAT_EQ(e.z, 1.f);
|
EXPECT_FLOAT_EQ(e.z, 1.f);
|
||||||
@@ -58,86 +58,183 @@ TEST(AabbTests, ExtentsOfUnitBox)
|
|||||||
|
|
||||||
TEST(AabbTests, ExtentsOfDegenerateBox)
|
TEST(AabbTests, ExtentsOfDegenerateBox)
|
||||||
{
|
{
|
||||||
const AABB box{{3.f, 3.f, 3.f}, {3.f, 3.f, 3.f}};
|
constexpr AABB box{{3.f, 3.f, 3.f}, {3.f, 3.f, 3.f}};
|
||||||
const auto e = box.extents();
|
constexpr auto e = box.extents();
|
||||||
EXPECT_FLOAT_EQ(e.x, 0.f);
|
EXPECT_FLOAT_EQ(e.x, 0.f);
|
||||||
EXPECT_FLOAT_EQ(e.y, 0.f);
|
EXPECT_FLOAT_EQ(e.y, 0.f);
|
||||||
EXPECT_FLOAT_EQ(e.z, 0.f);
|
EXPECT_FLOAT_EQ(e.z, 0.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using UpAxis = omath::primitives::UpAxis;
|
||||||
|
|
||||||
|
// --- top() ---
|
||||||
|
|
||||||
|
TEST(AabbTests, TopYUpSymmetricBox)
|
||||||
|
{
|
||||||
|
constexpr AABB box{{-1.f, -2.f, -3.f}, {1.f, 2.f, 3.f}};
|
||||||
|
constexpr auto t = box.top<UpAxis::Y>();
|
||||||
|
EXPECT_FLOAT_EQ(t.x, 0.f);
|
||||||
|
EXPECT_FLOAT_EQ(t.y, 2.f);
|
||||||
|
EXPECT_FLOAT_EQ(t.z, 0.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(AabbTests, TopYUpOffsetBox)
|
||||||
|
{
|
||||||
|
constexpr AABB box{{1.f, 4.f, 2.f}, {3.f, 10.f, 6.f}};
|
||||||
|
constexpr auto t = box.top<UpAxis::Y>();
|
||||||
|
EXPECT_FLOAT_EQ(t.x, 2.f);
|
||||||
|
EXPECT_FLOAT_EQ(t.y, 10.f);
|
||||||
|
EXPECT_FLOAT_EQ(t.z, 4.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(AabbTests, TopZUpSymmetricBox)
|
||||||
|
{
|
||||||
|
constexpr AABB box{{-1.f, -2.f, -3.f}, {1.f, 2.f, 3.f}};
|
||||||
|
constexpr auto t = box.top<UpAxis::Z>();
|
||||||
|
EXPECT_FLOAT_EQ(t.x, 0.f);
|
||||||
|
EXPECT_FLOAT_EQ(t.y, 0.f);
|
||||||
|
EXPECT_FLOAT_EQ(t.z, 3.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(AabbTests, TopZUpOffsetBox)
|
||||||
|
{
|
||||||
|
constexpr AABB box{{1.f, 4.f, 2.f}, {3.f, 10.f, 6.f}};
|
||||||
|
constexpr auto t = box.top<UpAxis::Z>();
|
||||||
|
EXPECT_FLOAT_EQ(t.x, 2.f);
|
||||||
|
EXPECT_FLOAT_EQ(t.y, 7.f);
|
||||||
|
EXPECT_FLOAT_EQ(t.z, 6.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(AabbTests, TopDefaultIsYUp)
|
||||||
|
{
|
||||||
|
constexpr AABB box{{0.f, 0.f, 0.f}, {2.f, 4.f, 6.f}};
|
||||||
|
EXPECT_EQ(box.top(), box.top<UpAxis::Y>());
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- bottom() ---
|
||||||
|
|
||||||
|
TEST(AabbTests, BottomYUpSymmetricBox)
|
||||||
|
{
|
||||||
|
constexpr AABB box{{-1.f, -2.f, -3.f}, {1.f, 2.f, 3.f}};
|
||||||
|
constexpr auto b = box.bottom<UpAxis::Y>();
|
||||||
|
EXPECT_FLOAT_EQ(b.x, 0.f);
|
||||||
|
EXPECT_FLOAT_EQ(b.y, -2.f);
|
||||||
|
EXPECT_FLOAT_EQ(b.z, 0.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(AabbTests, BottomYUpOffsetBox)
|
||||||
|
{
|
||||||
|
constexpr AABB box{{1.f, 4.f, 2.f}, {3.f, 10.f, 6.f}};
|
||||||
|
constexpr auto b = box.bottom<UpAxis::Y>();
|
||||||
|
EXPECT_FLOAT_EQ(b.x, 2.f);
|
||||||
|
EXPECT_FLOAT_EQ(b.y, 4.f);
|
||||||
|
EXPECT_FLOAT_EQ(b.z, 4.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(AabbTests, BottomZUpSymmetricBox)
|
||||||
|
{
|
||||||
|
constexpr AABB box{{-1.f, -2.f, -3.f}, {1.f, 2.f, 3.f}};
|
||||||
|
constexpr auto b = box.bottom<UpAxis::Z>();
|
||||||
|
EXPECT_FLOAT_EQ(b.x, 0.f);
|
||||||
|
EXPECT_FLOAT_EQ(b.y, 0.f);
|
||||||
|
EXPECT_FLOAT_EQ(b.z, -3.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(AabbTests, BottomZUpOffsetBox)
|
||||||
|
{
|
||||||
|
constexpr AABB box{{1.f, 4.f, 2.f}, {3.f, 10.f, 6.f}};
|
||||||
|
constexpr auto b = box.bottom<UpAxis::Z>();
|
||||||
|
EXPECT_FLOAT_EQ(b.x, 2.f);
|
||||||
|
EXPECT_FLOAT_EQ(b.y, 7.f);
|
||||||
|
EXPECT_FLOAT_EQ(b.z, 2.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(AabbTests, BottomDefaultIsYUp)
|
||||||
|
{
|
||||||
|
constexpr AABB box{{0.f, 0.f, 0.f}, {2.f, 4.f, 6.f}};
|
||||||
|
EXPECT_EQ(box.bottom(), box.bottom<UpAxis::Y>());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(AabbTests, TopAndBottomAreSymmetric)
|
||||||
|
{
|
||||||
|
constexpr AABB box{{-1.f, -2.f, -3.f}, {1.f, 2.f, 3.f}};
|
||||||
|
EXPECT_FLOAT_EQ(box.top<UpAxis::Y>().y, -box.bottom<UpAxis::Y>().y);
|
||||||
|
EXPECT_FLOAT_EQ(box.top<UpAxis::Z>().z, -box.bottom<UpAxis::Z>().z);
|
||||||
|
}
|
||||||
|
|
||||||
// --- is_collide() ---
|
// --- is_collide() ---
|
||||||
|
|
||||||
TEST(AabbTests, OverlappingBoxesCollide)
|
TEST(AabbTests, OverlappingBoxesCollide)
|
||||||
{
|
{
|
||||||
const AABB a{{-1.f, -1.f, -1.f}, {1.f, 1.f, 1.f}};
|
constexpr AABB a{{-1.f, -1.f, -1.f}, {1.f, 1.f, 1.f}};
|
||||||
const AABB b{{0.f, 0.f, 0.f}, {2.f, 2.f, 2.f}};
|
constexpr AABB b{{0.f, 0.f, 0.f}, {2.f, 2.f, 2.f}};
|
||||||
EXPECT_TRUE(a.is_collide(b));
|
EXPECT_TRUE(a.is_collide(b));
|
||||||
EXPECT_TRUE(b.is_collide(a));
|
EXPECT_TRUE(b.is_collide(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AabbTests, SeparatedBoxesDoNotCollide)
|
TEST(AabbTests, SeparatedBoxesDoNotCollide)
|
||||||
{
|
{
|
||||||
const AABB a{{-1.f, -1.f, -1.f}, {1.f, 1.f, 1.f}};
|
constexpr AABB a{{-1.f, -1.f, -1.f}, {1.f, 1.f, 1.f}};
|
||||||
const AABB b{{2.f, 2.f, 2.f}, {4.f, 4.f, 4.f}};
|
constexpr AABB b{{2.f, 2.f, 2.f}, {4.f, 4.f, 4.f}};
|
||||||
EXPECT_FALSE(a.is_collide(b));
|
EXPECT_FALSE(a.is_collide(b));
|
||||||
EXPECT_FALSE(b.is_collide(a));
|
EXPECT_FALSE(b.is_collide(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AabbTests, TouchingFacesCollide)
|
TEST(AabbTests, TouchingFacesCollide)
|
||||||
{
|
{
|
||||||
const AABB a{{-1.f, -1.f, -1.f}, {1.f, 1.f, 1.f}};
|
constexpr AABB a{{-1.f, -1.f, -1.f}, {1.f, 1.f, 1.f}};
|
||||||
const AABB b{{1.f, -1.f, -1.f}, {3.f, 1.f, 1.f}};
|
constexpr AABB b{{1.f, -1.f, -1.f}, {3.f, 1.f, 1.f}};
|
||||||
EXPECT_TRUE(a.is_collide(b));
|
EXPECT_TRUE(a.is_collide(b));
|
||||||
EXPECT_TRUE(b.is_collide(a));
|
EXPECT_TRUE(b.is_collide(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AabbTests, ContainedBoxCollides)
|
TEST(AabbTests, ContainedBoxCollides)
|
||||||
{
|
{
|
||||||
const AABB outer{{-3.f, -3.f, -3.f}, {3.f, 3.f, 3.f}};
|
constexpr AABB outer{{-3.f, -3.f, -3.f}, {3.f, 3.f, 3.f}};
|
||||||
const AABB inner{{-1.f, -1.f, -1.f}, {1.f, 1.f, 1.f}};
|
constexpr AABB inner{{-1.f, -1.f, -1.f}, {1.f, 1.f, 1.f}};
|
||||||
EXPECT_TRUE(outer.is_collide(inner));
|
EXPECT_TRUE(outer.is_collide(inner));
|
||||||
EXPECT_TRUE(inner.is_collide(outer));
|
EXPECT_TRUE(inner.is_collide(outer));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AabbTests, SeparatedOnXAxisDoNotCollide)
|
TEST(AabbTests, SeparatedOnXAxisDoNotCollide)
|
||||||
{
|
{
|
||||||
const AABB a{{0.f, 0.f, 0.f}, {1.f, 1.f, 1.f}};
|
constexpr AABB a{{0.f, 0.f, 0.f}, {1.f, 1.f, 1.f}};
|
||||||
const AABB b{{2.f, 0.f, 0.f}, {3.f, 1.f, 1.f}};
|
constexpr AABB b{{2.f, 0.f, 0.f}, {3.f, 1.f, 1.f}};
|
||||||
EXPECT_FALSE(a.is_collide(b));
|
EXPECT_FALSE(a.is_collide(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AabbTests, SeparatedOnYAxisDoNotCollide)
|
TEST(AabbTests, SeparatedOnYAxisDoNotCollide)
|
||||||
{
|
{
|
||||||
const AABB a{{0.f, 0.f, 0.f}, {1.f, 1.f, 1.f}};
|
constexpr AABB a{{0.f, 0.f, 0.f}, {1.f, 1.f, 1.f}};
|
||||||
const AABB b{{0.f, 2.f, 0.f}, {1.f, 3.f, 1.f}};
|
constexpr AABB b{{0.f, 2.f, 0.f}, {1.f, 3.f, 1.f}};
|
||||||
EXPECT_FALSE(a.is_collide(b));
|
EXPECT_FALSE(a.is_collide(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AabbTests, SeparatedOnZAxisDoNotCollide)
|
TEST(AabbTests, SeparatedOnZAxisDoNotCollide)
|
||||||
{
|
{
|
||||||
const AABB a{{0.f, 0.f, 0.f}, {1.f, 1.f, 1.f}};
|
constexpr AABB a{{0.f, 0.f, 0.f}, {1.f, 1.f, 1.f}};
|
||||||
const AABB b{{0.f, 0.f, 2.f}, {1.f, 1.f, 3.f}};
|
constexpr AABB b{{0.f, 0.f, 2.f}, {1.f, 1.f, 3.f}};
|
||||||
EXPECT_FALSE(a.is_collide(b));
|
EXPECT_FALSE(a.is_collide(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AabbTests, IdenticalBoxesCollide)
|
TEST(AabbTests, IdenticalBoxesCollide)
|
||||||
{
|
{
|
||||||
const AABB a{{-1.f, -1.f, -1.f}, {1.f, 1.f, 1.f}};
|
constexpr AABB a{{-1.f, -1.f, -1.f}, {1.f, 1.f, 1.f}};
|
||||||
EXPECT_TRUE(a.is_collide(a));
|
EXPECT_TRUE(a.is_collide(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AabbTests, DegeneratePointBoxCollidesWhenInsideOther)
|
TEST(AabbTests, DegeneratePointBoxCollidesWhenInsideOther)
|
||||||
{
|
{
|
||||||
const AABB box{{-1.f, -1.f, -1.f}, {1.f, 1.f, 1.f}};
|
constexpr AABB box{{-1.f, -1.f, -1.f}, {1.f, 1.f, 1.f}};
|
||||||
const AABB point{{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}};
|
constexpr AABB point{{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}};
|
||||||
EXPECT_TRUE(box.is_collide(point));
|
EXPECT_TRUE(box.is_collide(point));
|
||||||
EXPECT_TRUE(point.is_collide(box));
|
EXPECT_TRUE(point.is_collide(box));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AabbTests, DegeneratePointBoxDoesNotCollideWhenOutside)
|
TEST(AabbTests, DegeneratePointBoxDoesNotCollideWhenOutside)
|
||||||
{
|
{
|
||||||
const AABB box{{-1.f, -1.f, -1.f}, {1.f, 1.f, 1.f}};
|
constexpr AABB box{{-1.f, -1.f, -1.f}, {1.f, 1.f, 1.f}};
|
||||||
const AABB point{{5.f, 0.f, 0.f}, {5.f, 0.f, 0.f}};
|
constexpr AABB point{{5.f, 0.f, 0.f}, {5.f, 0.f, 0.f}};
|
||||||
EXPECT_FALSE(box.is_collide(point));
|
EXPECT_FALSE(box.is_collide(point));
|
||||||
EXPECT_FALSE(point.is_collide(box));
|
EXPECT_FALSE(point.is_collide(box));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user