146 lines
6.0 KiB
C++
146 lines
6.0 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "HeadlessChaos.h"
|
|
#include "HeadlessChaosTestUtility.h"
|
|
#include "Chaos/Matrix.h"
|
|
#include "Chaos/Utilities.h"
|
|
#include "Chaos/AABB.h"
|
|
|
|
namespace ChaosTest
|
|
{
|
|
using namespace Chaos;
|
|
|
|
void TestBounds(const FAABB3& A, const FAABB3& B, const FReal Eps = 1.e-6)
|
|
{
|
|
EXPECT_NEAR(A.Min().X, B.Min().X, Eps);
|
|
EXPECT_NEAR(A.Min().Y, B.Min().Y, Eps);
|
|
EXPECT_NEAR(A.Min().Z, B.Min().Z, Eps);
|
|
EXPECT_NEAR(A.Max().X, B.Max().X, Eps);
|
|
EXPECT_NEAR(A.Max().Y, B.Max().Y, Eps);
|
|
EXPECT_NEAR(A.Max().Z, B.Max().Z, Eps);
|
|
}
|
|
|
|
// Transformed AABB by transforming all box verts
|
|
// Used for reference when comparing to current TAABB::TransformedAABB results
|
|
FAABB3 ReferenceTransformAABB(const FAABB3& AABB, const FRigidTransform3& Transform)
|
|
{
|
|
FVec3 Extents = AABB.Extents();
|
|
FAABB3 NewAABB = FAABB3::EmptyAABB();
|
|
NewAABB.GrowToInclude(Transform.TransformPosition(FVec3(AABB.Min())));
|
|
NewAABB.GrowToInclude(Transform.TransformPosition(FVec3(AABB.Max())));
|
|
|
|
for (int32 AxisIndex = 0; AxisIndex < 3; ++AxisIndex)
|
|
{
|
|
NewAABB.GrowToInclude(Transform.TransformPosition(FVec3(AABB.Min() + FVec3::AxisVector(AxisIndex) * Extents)));
|
|
NewAABB.GrowToInclude(Transform.TransformPosition(FVec3(AABB.Max() - FVec3::AxisVector(AxisIndex) * Extents)));
|
|
}
|
|
|
|
return NewAABB;
|
|
}
|
|
|
|
// Inverse Transformed AABB by transforming all box verts
|
|
// Used for reference when comparing to current TAABB::InverseTransformedAABB results
|
|
FAABB3 ReferenceInverseTransformAABB(const FAABB3& AABB, const FRigidTransform3& Transform)
|
|
{
|
|
FVec3 Extents = AABB.Extents();
|
|
FAABB3 NewAABB = FAABB3::EmptyAABB();
|
|
NewAABB.GrowToInclude(Transform.InverseTransformPosition(FVec3(AABB.Min())));
|
|
NewAABB.GrowToInclude(Transform.InverseTransformPosition(FVec3(AABB.Max())));
|
|
|
|
for (int32 AxisIndex = 0; AxisIndex < 3; ++AxisIndex)
|
|
{
|
|
NewAABB.GrowToInclude(Transform.InverseTransformPosition(FVec3(AABB.Min() + FVec3::AxisVector(AxisIndex) * Extents)));
|
|
NewAABB.GrowToInclude(Transform.InverseTransformPosition(FVec3(AABB.Max() - FVec3::AxisVector(AxisIndex) * Extents)));
|
|
}
|
|
|
|
return NewAABB;
|
|
}
|
|
|
|
// Check that identity transform does not affect an AABB
|
|
GTEST_TEST(AABBTests, TestTransformAABB_Unit)
|
|
{
|
|
const FAABB3 Bounds = FAABB3(FVec3(-1,-2,-3), FVec3(1,2,3));
|
|
const FRigidTransform3 Transform = FRigidTransform3::Identity;
|
|
|
|
const FAABB3 TransformedBounds = Bounds.TransformedAABB(Transform);
|
|
TestBounds(TransformedBounds, Bounds);
|
|
|
|
const FAABB3 InverseTransformedBounds = Bounds.InverseTransformedAABB(Transform);
|
|
TestBounds(InverseTransformedBounds, Bounds);
|
|
}
|
|
|
|
GTEST_TEST(AABBTests, TestTransformAABB_Translate)
|
|
{
|
|
const FAABB3 Bounds = FAABB3(FVec3(-3, -2, -1), FVec3(1, 2, 3));
|
|
|
|
const FVec3 Offset = FVec3(2);
|
|
const FRigidTransform3 Transform = FRigidTransform3(Offset, FRotation3::FromIdentity(), FVec3(1));
|
|
|
|
const FAABB3 TransformedBounds = Bounds.TransformedAABB(Transform);
|
|
TestBounds(TransformedBounds, FAABB3(Offset + Bounds.Min(), Offset + Bounds.Max()));
|
|
|
|
const FAABB3 InverseTransformedBounds = Bounds.InverseTransformedAABB(Transform);
|
|
TestBounds(InverseTransformedBounds, FAABB3(Bounds.Min() - Offset, Bounds.Max() - Offset));
|
|
}
|
|
|
|
GTEST_TEST(AABBTests, TestTransformAABB_Scale)
|
|
{
|
|
const FAABB3 Bounds = FAABB3(FVec3(-3, -2, -1), FVec3(1, 2, 3));
|
|
|
|
const FVec3 Scale = FVec3(2);
|
|
const FRigidTransform3 Transform = FRigidTransform3(FVec3(0), FRotation3::FromIdentity(), Scale);
|
|
|
|
const FAABB3 TransformedBounds = Bounds.TransformedAABB(Transform);
|
|
TestBounds(TransformedBounds, FAABB3(Scale * Bounds.Min(), Scale * Bounds.Max()));
|
|
|
|
const FAABB3 InverseTransformedBounds = Bounds.InverseTransformedAABB(Transform);
|
|
TestBounds(InverseTransformedBounds, FAABB3(Bounds.Min() / Scale, Bounds.Max() / Scale));
|
|
}
|
|
|
|
GTEST_TEST(AABBTests, TestTransformAABB_NegativeScale)
|
|
{
|
|
const FAABB3 Bounds = FAABB3(FVec3(-3, -2, -1), FVec3(1, 2, 3));
|
|
|
|
const FVec3 Scale = FVec3(-2);
|
|
const FRigidTransform3 Transform = FRigidTransform3(FVec3(0), FRotation3::FromIdentity(), Scale);
|
|
|
|
const FAABB3 TransformedBounds = Bounds.TransformedAABB(Transform);
|
|
TestBounds(TransformedBounds, FAABB3(Scale * Bounds.Max(), Scale * Bounds.Min()));
|
|
|
|
const FAABB3 InverseTransformedBounds = Bounds.InverseTransformedAABB(Transform);
|
|
TestBounds(InverseTransformedBounds, FAABB3(Bounds.Max() / Scale, Bounds.Min() / Scale));
|
|
}
|
|
|
|
GTEST_TEST(AABBTests, TestTransformAABB_ScaleRotateTranslate)
|
|
{
|
|
const FAABB3 Bounds = FAABB3(FVec3(-3, -2, -1), FVec3(1, 2, 3));
|
|
const FRigidTransform3 Transform = FRigidTransform3(FVec3(4,7,-3), FRotation3::FromAxisAngle(FVec3(4,-3,5).GetUnsafeNormal(), FMath::DegreesToRadians(36.5)), FVec3(1, -4, 17));
|
|
|
|
const FAABB3 TransformedBounds = Bounds.TransformedAABB(Transform);
|
|
TestBounds(TransformedBounds, ReferenceTransformAABB(Bounds, Transform));
|
|
|
|
const FAABB3 InverseTransformedBounds = Bounds.InverseTransformedAABB(Transform);
|
|
TestBounds(InverseTransformedBounds, ReferenceInverseTransformAABB(Bounds, Transform));
|
|
}
|
|
|
|
|
|
// A test that was failing for 8-wide ISPC architectures
|
|
GTEST_TEST(AABBTests, TestTransformAABB_ISPC8WideFail)
|
|
{
|
|
const FAABB3 AABB(FVec3(-51.1019897, -51.1019936, -51.1019974), FVec3(51.1019897, 51.1020012, 51.1019974));
|
|
const FRigidTransform3 Transform(FVec3(1.16415322e-10, 5.82076609e-11, -0.0681053028), FRotation3::FromElements(0.579225421, -0.644822955, 0.0343584977, 0.497514546));
|
|
|
|
const FAABB3 ExpectedAABB(FVec3(-79.1592407, -84.8343811, -87.7618637), FVec3(79.1592407, 84.8343811, 87.6256561));
|
|
|
|
const FAABB3 ResultAABB = AABB.TransformedAABB(Transform);
|
|
EXPECT_NEAR(ResultAABB.Min().X, ExpectedAABB.Min().X, KINDA_SMALL_NUMBER);
|
|
EXPECT_NEAR(ResultAABB.Min().Y, ExpectedAABB.Min().Y, KINDA_SMALL_NUMBER);
|
|
EXPECT_NEAR(ResultAABB.Min().Z, ExpectedAABB.Min().Z, KINDA_SMALL_NUMBER);
|
|
EXPECT_NEAR(ResultAABB.Max().X, ExpectedAABB.Max().X, KINDA_SMALL_NUMBER);
|
|
EXPECT_NEAR(ResultAABB.Max().Y, ExpectedAABB.Max().Y, KINDA_SMALL_NUMBER);
|
|
EXPECT_NEAR(ResultAABB.Max().Z, ExpectedAABB.Max().Z, KINDA_SMALL_NUMBER);
|
|
}
|
|
|
|
|
|
}
|