You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
851 lines
35 KiB
C++
851 lines
35 KiB
C++
/*
|
|
* Copyright (c) Contributors to the Open 3D Engine Project.
|
|
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
*
|
|
*/
|
|
|
|
#include <AzTest/AzTest.h>
|
|
|
|
#include <AzCore/Component/ComponentApplication.h>
|
|
#include <AzCore/Math/Matrix3x3.h>
|
|
#include <AzCore/Math/VertexContainerInterface.h>
|
|
#include <AzFramework/Components/TransformComponent.h>
|
|
#include <AzFramework/Components/NonUniformScaleComponent.h>
|
|
#include <Shape/PolygonPrismShapeComponent.h>
|
|
#include <AzCore/UnitTest/TestTypes.h>
|
|
#include <AZTestShared/Math/MathTestHelpers.h>
|
|
|
|
namespace UnitTest
|
|
{
|
|
class PolygonPrismShapeTest
|
|
: public AllocatorsFixture
|
|
{
|
|
AZStd::unique_ptr<AZ::SerializeContext> m_serializeContext;
|
|
AZStd::unique_ptr<AZ::ComponentDescriptor> m_transformComponentDescriptor;
|
|
AZStd::unique_ptr<AZ::ComponentDescriptor> m_polygonPrismShapeComponentDescriptor;
|
|
AZStd::unique_ptr<AZ::ComponentDescriptor> m_nonUniformScaleComponentDescriptor;
|
|
|
|
public:
|
|
void SetUp() override
|
|
{
|
|
AllocatorsFixture::SetUp();
|
|
m_serializeContext = AZStd::make_unique<AZ::SerializeContext>();
|
|
|
|
m_transformComponentDescriptor = AZStd::unique_ptr<AZ::ComponentDescriptor>(AzFramework::TransformComponent::CreateDescriptor());
|
|
m_transformComponentDescriptor->Reflect(&(*m_serializeContext));
|
|
m_polygonPrismShapeComponentDescriptor = AZStd::unique_ptr<AZ::ComponentDescriptor>(LmbrCentral::PolygonPrismShapeComponent::CreateDescriptor());
|
|
m_polygonPrismShapeComponentDescriptor->Reflect(&(*m_serializeContext));
|
|
m_nonUniformScaleComponentDescriptor = AZStd::unique_ptr<AZ::ComponentDescriptor>(AzFramework::NonUniformScaleComponent::CreateDescriptor());
|
|
m_nonUniformScaleComponentDescriptor->Reflect(&(*m_serializeContext));
|
|
}
|
|
|
|
void TearDown() override
|
|
{
|
|
m_transformComponentDescriptor.reset();
|
|
m_polygonPrismShapeComponentDescriptor.reset();
|
|
m_nonUniformScaleComponentDescriptor.reset();
|
|
m_serializeContext.reset();
|
|
AllocatorsFixture::TearDown();
|
|
}
|
|
};
|
|
|
|
void CreatePolygonPrism(
|
|
const AZ::Transform& transform, const float height, const AZStd::vector<AZ::Vector2>& vertices, AZ::Entity& entity)
|
|
{
|
|
entity.CreateComponent<LmbrCentral::PolygonPrismShapeComponent>();
|
|
entity.CreateComponent<AzFramework::TransformComponent>();
|
|
|
|
entity.Init();
|
|
entity.Activate();
|
|
|
|
AZ::TransformBus::Event(entity.GetId(), &AZ::TransformBus::Events::SetWorldTM, transform);
|
|
|
|
LmbrCentral::PolygonPrismShapeComponentRequestBus::Event(entity.GetId(), &LmbrCentral::PolygonPrismShapeComponentRequests::SetHeight, height);
|
|
LmbrCentral::PolygonPrismShapeComponentRequestBus::Event(entity.GetId(), &LmbrCentral::PolygonPrismShapeComponentRequests::SetVertices, vertices);
|
|
}
|
|
|
|
void CreatePolygonPrismWithNonUniformScale(
|
|
const AZ::Transform& transform, const float height, const AZStd::vector<AZ::Vector2>& vertices,
|
|
const AZ::Vector3& nonUniformScale, AZ::Entity& entity)
|
|
{
|
|
entity.CreateComponent<LmbrCentral::PolygonPrismShapeComponent>();
|
|
entity.CreateComponent<AzFramework::TransformComponent>();
|
|
entity.CreateComponent<AzFramework::NonUniformScaleComponent>();
|
|
|
|
entity.Init();
|
|
entity.Activate();
|
|
|
|
AZ::TransformBus::Event(entity.GetId(), &AZ::TransformBus::Events::SetWorldTM, transform);
|
|
AZ::NonUniformScaleRequestBus::Event(entity.GetId(), &AZ::NonUniformScaleRequests::SetScale, nonUniformScale);
|
|
|
|
LmbrCentral::PolygonPrismShapeComponentRequestBus::Event(entity.GetId(), &LmbrCentral::PolygonPrismShapeComponentRequests::SetHeight, height);
|
|
LmbrCentral::PolygonPrismShapeComponentRequestBus::Event(entity.GetId(), &LmbrCentral::PolygonPrismShapeComponentRequests::SetVertices, vertices);
|
|
}
|
|
|
|
TEST_F(PolygonPrismShapeTest, PolygonShapeComponent_IsPointInside)
|
|
{
|
|
AZ::Entity entity;
|
|
CreatePolygonPrism(
|
|
AZ::Transform::CreateIdentity(), 10.0f,
|
|
AZStd::vector<AZ::Vector2>(
|
|
{
|
|
AZ::Vector2(0.0f, 0.0f),
|
|
AZ::Vector2(0.0f, 10.0f),
|
|
AZ::Vector2(10.0f, 10.0f),
|
|
AZ::Vector2(10.0f, 0.0f)
|
|
}),
|
|
entity);
|
|
|
|
// verify point inside returns true
|
|
{
|
|
bool inside;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(inside, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IsPointInside, AZ::Vector3(5.0f, 5.0f, 5.0f));
|
|
EXPECT_TRUE(inside);
|
|
}
|
|
|
|
// verify point outside return false
|
|
{
|
|
bool inside;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(inside, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IsPointInside, AZ::Vector3(5.0f, 5.0f, 20.0f));
|
|
EXPECT_TRUE(!inside);
|
|
}
|
|
|
|
// verify points at polygon edge return true
|
|
{
|
|
bool inside;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(inside, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IsPointInside, AZ::Vector3(0.0f, 0.0f, 0.0f));
|
|
EXPECT_TRUE(inside);
|
|
}
|
|
|
|
{
|
|
bool inside;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(inside, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IsPointInside, AZ::Vector3(0.0f, 10.0f, 0.0f));
|
|
EXPECT_TRUE(inside);
|
|
}
|
|
{
|
|
bool inside;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(inside, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IsPointInside, AZ::Vector3(10.0f, 10.0f, 0.0f));
|
|
EXPECT_TRUE(inside);
|
|
}
|
|
{
|
|
bool inside;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(inside, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IsPointInside, AZ::Vector3(10.0f, 0.0f, 0.0f));
|
|
EXPECT_TRUE(inside);
|
|
}
|
|
{
|
|
bool inside;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(inside, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IsPointInside, AZ::Vector3(5.0f, 10.0f, 0.0f));
|
|
EXPECT_TRUE(inside);
|
|
}
|
|
|
|
// verify point lies just inside
|
|
{
|
|
bool inside;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(inside, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IsPointInside, AZ::Vector3(5.0f, 9.5f, 0.0f));
|
|
EXPECT_TRUE(inside);
|
|
}
|
|
// verify point lies just outside
|
|
{
|
|
bool inside;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(inside, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IsPointInside, AZ::Vector3(5.0f, 10.1f, 0.0f));
|
|
EXPECT_FALSE(inside);
|
|
}
|
|
|
|
// note: the shape and positions/transforms were defined in the editor and replicated here - this
|
|
// gave a good way to create various test cases and replicate them here
|
|
AZ::TransformBus::Event(entity.GetId(), &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateFromMatrix3x3AndTranslation(AZ::Matrix3x3::CreateIdentity(), AZ::Vector3(497.0f, 595.0f, 32.0f)));
|
|
LmbrCentral::PolygonPrismShapeComponentRequestBus::Event(entity.GetId(), &LmbrCentral::PolygonPrismShapeComponentRequests::SetVertices,
|
|
AZStd::vector<AZ::Vector2>(
|
|
{
|
|
AZ::Vector2(0.0f, 9.0f),
|
|
AZ::Vector2(6.5f, 6.5f),
|
|
AZ::Vector2(9.0f, 0.0f),
|
|
AZ::Vector2(6.5f, -6.5f),
|
|
AZ::Vector2(0.0f, -9.0f),
|
|
AZ::Vector2(-6.5f, -6.5f),
|
|
AZ::Vector2(-9.0f, 0.0f),
|
|
AZ::Vector2(-6.5f, 6.5f)
|
|
}
|
|
));
|
|
|
|
// verify point inside aabb but not inside polygon returns false
|
|
{
|
|
bool inside;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(inside, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IsPointInside, AZ::Vector3(488.62f, 588.88f, 32.0f));
|
|
EXPECT_FALSE(inside);
|
|
}
|
|
|
|
// verify point inside aabb and inside polygon returns true - when intersecting two vertices
|
|
{
|
|
bool inside;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(inside, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IsPointInside, AZ::Vector3(496.62f, 595.0f, 32.0f));
|
|
EXPECT_TRUE(inside);
|
|
}
|
|
|
|
LmbrCentral::PolygonPrismShapeComponentRequestBus::Event(entity.GetId(), &LmbrCentral::PolygonPrismShapeComponentRequests::SetVertices,
|
|
AZStd::vector<AZ::Vector2>(
|
|
{
|
|
AZ::Vector2(0.0f, 0.0f),
|
|
AZ::Vector2(10.0f, 0.0f),
|
|
AZ::Vector2(5.0f, 10.0f)
|
|
}
|
|
));
|
|
|
|
{
|
|
bool inside;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(inside, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IsPointInside, AZ::Vector3(496.62f, 595.0f, 32.0f));
|
|
EXPECT_FALSE(inside);
|
|
}
|
|
|
|
LmbrCentral::PolygonPrismShapeComponentRequestBus::Event(entity.GetId(), &LmbrCentral::PolygonPrismShapeComponentRequests::SetVertices,
|
|
AZStd::vector<AZ::Vector2>(
|
|
{
|
|
AZ::Vector2(0.0f, 10.0f),
|
|
AZ::Vector2(10.0f, 10.0f),
|
|
AZ::Vector2(5.0f, 0.0f)
|
|
}
|
|
));
|
|
|
|
{
|
|
bool inside;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(inside, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IsPointInside, AZ::Vector3(496.62f, 595.0f, 32.0f));
|
|
EXPECT_FALSE(inside);
|
|
}
|
|
|
|
LmbrCentral::PolygonPrismShapeComponentRequestBus::Event(entity.GetId(), &LmbrCentral::PolygonPrismShapeComponentRequests::SetVertices,
|
|
AZStd::vector<AZ::Vector2>(
|
|
{
|
|
AZ::Vector2(0.0f, 0.0f),
|
|
AZ::Vector2(10.0f, 0.0f),
|
|
AZ::Vector2(5.0f, -10.0f)
|
|
}
|
|
));
|
|
|
|
{
|
|
bool inside;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(inside, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IsPointInside, AZ::Vector3(496.62f, 595.0f, 32.0f));
|
|
EXPECT_FALSE(inside);
|
|
}
|
|
{
|
|
bool inside;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(inside, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IsPointInside, AZ::Vector3(502.0f, 585.0f, 32.0f));
|
|
EXPECT_TRUE(inside);
|
|
}
|
|
{
|
|
bool inside;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(inside, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IsPointInside, AZ::Vector3(499.62f, 595.0f, 32.0f));
|
|
EXPECT_TRUE(inside);
|
|
}
|
|
|
|
// U shape
|
|
AZ::TransformBus::Event(entity.GetId(), &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateIdentity());
|
|
LmbrCentral::PolygonPrismShapeComponentRequestBus::Event(entity.GetId(), &LmbrCentral::PolygonPrismShapeComponentRequests::SetVertices,
|
|
AZStd::vector<AZ::Vector2>(
|
|
{
|
|
AZ::Vector2(0.0f, 0.0f),
|
|
AZ::Vector2(0.0f, 10.0f),
|
|
AZ::Vector2(5.0f, 10.0f),
|
|
AZ::Vector2(5.0f, 5.0f),
|
|
AZ::Vector2(10.0f, 5.0f),
|
|
AZ::Vector2(10.0f, 10.0f),
|
|
AZ::Vector2(15.0f, 15.0f),
|
|
AZ::Vector2(15.0f, 0.0f),
|
|
}
|
|
));
|
|
|
|
{
|
|
bool inside;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(inside, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IsPointInside, AZ::Vector3(7.5f, 7.5f, 0.0f));
|
|
EXPECT_FALSE(inside);
|
|
}
|
|
{
|
|
bool inside;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(inside, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IsPointInside, AZ::Vector3(12.5f, 7.5f, 0.0f));
|
|
EXPECT_TRUE(inside);
|
|
}
|
|
{
|
|
bool inside;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(inside, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IsPointInside, AZ::Vector3(12.5f, 7.5f, 12.0f));
|
|
EXPECT_FALSE(inside);
|
|
}
|
|
|
|
// check polygon prism with rotation
|
|
AZ::TransformBus::Event(entity.GetId(), &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateRotationX(AZ::DegToRad(45.0f)));
|
|
LmbrCentral::PolygonPrismShapeComponentRequestBus::Event(entity.GetId(), &LmbrCentral::PolygonPrismShapeComponentRequests::SetHeight, 10.0f);
|
|
LmbrCentral::PolygonPrismShapeComponentRequestBus::Event(entity.GetId(), &LmbrCentral::PolygonPrismShapeComponentRequests::SetVertices,
|
|
AZStd::vector<AZ::Vector2>(
|
|
{
|
|
AZ::Vector2(-5.0f, -5.0f),
|
|
AZ::Vector2(-5.0f, 5.0f),
|
|
AZ::Vector2(5.0f, 5.0f),
|
|
AZ::Vector2(5.0f, -5.0f)
|
|
}
|
|
));
|
|
|
|
// check below
|
|
{
|
|
bool inside;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(inside, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IsPointInside, AZ::Vector3(2.0f, 3.5f, 2.0f));
|
|
EXPECT_FALSE(inside);
|
|
}
|
|
{
|
|
bool inside;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(inside, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IsPointInside, AZ::Vector3(2.0f, -8.0f, -2.0f));
|
|
EXPECT_FALSE(inside);
|
|
}
|
|
// check above
|
|
{
|
|
bool inside;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(inside, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IsPointInside, AZ::Vector3(2.0f, -8.0f, 8.0f));
|
|
EXPECT_FALSE(inside);
|
|
}
|
|
{
|
|
bool inside;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(inside, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IsPointInside, AZ::Vector3(2.0f, 2.0f, 8.0f));
|
|
EXPECT_FALSE(inside);
|
|
}
|
|
// check inside
|
|
{
|
|
bool inside;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(inside, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IsPointInside, AZ::Vector3(2.0f, -3.0f, 8.0f));
|
|
EXPECT_TRUE(inside);
|
|
}
|
|
{
|
|
bool inside;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(inside, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IsPointInside, AZ::Vector3(2.0f, -3.0f, -2.0f));
|
|
EXPECT_TRUE(inside);
|
|
}
|
|
}
|
|
|
|
TEST_F(PolygonPrismShapeTest, PolygonShapeComponent_IsPointInsideWithNonUniformScale)
|
|
{
|
|
AZ::Entity entity;
|
|
AZ::Transform transform = AZ::Transform::CreateFromQuaternionAndTranslation(
|
|
AZ::Quaternion::CreateRotationY(AZ::DegToRad(45.0f)), AZ::Vector3(3.0f, 4.0f, 5.0f));
|
|
transform.MultiplyByUniformScale(1.5f);
|
|
const float height = 1.2f;
|
|
const AZ::Vector3 nonUniformScale(2.0f, 1.2f, 0.5f);
|
|
const AZStd::vector<AZ::Vector2> vertices =
|
|
{
|
|
AZ::Vector2(1.0f, -1.0f),
|
|
AZ::Vector2(2.0f, 0.0f),
|
|
AZ::Vector2(-2.0f, 1.0f),
|
|
AZ::Vector2(-1.0f, -1.0f)
|
|
};
|
|
|
|
CreatePolygonPrismWithNonUniformScale(transform, height, vertices, nonUniformScale, entity);
|
|
|
|
// several points which should be outside the prism
|
|
auto outsidePoints = {
|
|
AZ::Vector3(4.0f, 5.0f, 4.5f),
|
|
AZ::Vector3(1.0f, 1.0f, 7.5f),
|
|
AZ::Vector3(7.5f, 3.0f, 2.5f),
|
|
AZ::Vector3(-1.0, 6.0f, 11.0f),
|
|
AZ::Vector3(2.0f, 4.0f, 5.5f),
|
|
AZ::Vector3(4.0f, 3.5f, 5.5f)
|
|
};
|
|
|
|
// several points which should be just inside the prism
|
|
auto insidePoints = {
|
|
AZ::Vector3(0.0f, 5.5f, 9.0f),
|
|
AZ::Vector3(1.5f, 2.5f, 7.5f),
|
|
AZ::Vector3(5.5f, 2.5f, 3.75f),
|
|
AZ::Vector3(7.75f, 4.0f, 1.5f),
|
|
AZ::Vector3(2.5f, 3.0f, 5.6f),
|
|
AZ::Vector3(4.0f, 4.5f, 5.25f)
|
|
};
|
|
|
|
for (const auto& point : outsidePoints)
|
|
{
|
|
bool inside = true;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(inside, entity.GetId(),
|
|
&LmbrCentral::ShapeComponentRequests::IsPointInside, point);
|
|
EXPECT_FALSE(inside);
|
|
}
|
|
|
|
for (const auto& point : insidePoints)
|
|
{
|
|
bool inside = false;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(inside, entity.GetId(),
|
|
&LmbrCentral::ShapeComponentRequests::IsPointInside, point);
|
|
EXPECT_TRUE(inside);
|
|
}
|
|
}
|
|
|
|
TEST_F(PolygonPrismShapeTest, PolygonShapeComponent_DistanceFromPoint)
|
|
{
|
|
AZ::Entity entity;
|
|
CreatePolygonPrism(
|
|
AZ::Transform::CreateIdentity(),
|
|
10.0f, AZStd::vector<AZ::Vector2>(
|
|
{
|
|
AZ::Vector2(0.0f, 0.0f),
|
|
AZ::Vector2(0.0f, 10.0f),
|
|
AZ::Vector2(10.0f, 10.0f),
|
|
AZ::Vector2(10.0f, 0.0f)
|
|
}),
|
|
entity);
|
|
|
|
{
|
|
float distance;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(distance, entity.GetId(), &LmbrCentral::ShapeComponentRequests::DistanceFromPoint, AZ::Vector3(15.0f, 5.0f, 0.0f));
|
|
EXPECT_TRUE(AZ::IsCloseMag(distance, 5.0f));
|
|
}
|
|
|
|
{
|
|
float distance;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(distance, entity.GetId(), &LmbrCentral::ShapeComponentRequests::DistanceFromPoint, AZ::Vector3(5.0f, 5.0f, 5.0f));
|
|
EXPECT_TRUE(AZ::IsCloseMag(distance, 0.0f));
|
|
}
|
|
|
|
{
|
|
float distance;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(distance, entity.GetId(), &LmbrCentral::ShapeComponentRequests::DistanceFromPoint, AZ::Vector3(5.0f, 5.0f, 0.0f));
|
|
EXPECT_TRUE(AZ::IsCloseMag(distance, 0.0f));
|
|
}
|
|
|
|
{
|
|
float distance;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(distance, entity.GetId(), &LmbrCentral::ShapeComponentRequests::DistanceFromPoint, AZ::Vector3(1.0f, 1.0f, -1.0f));
|
|
EXPECT_TRUE(AZ::IsCloseMag(distance, 1.0f));
|
|
}
|
|
|
|
{
|
|
float distance;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(distance, entity.GetId(), &LmbrCentral::ShapeComponentRequests::DistanceFromPoint, AZ::Vector3(10.0f, 10.0f, 10.0f));
|
|
EXPECT_TRUE(AZ::IsCloseMag(distance, 0.0f));
|
|
}
|
|
|
|
{
|
|
float distance;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(distance, entity.GetId(), &LmbrCentral::ShapeComponentRequests::DistanceFromPoint, AZ::Vector3(5.0f, 5.0f, 15.0f));
|
|
EXPECT_TRUE(AZ::IsCloseMag(distance, 5.0f));
|
|
}
|
|
|
|
{
|
|
float distance;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(distance, entity.GetId(), &LmbrCentral::ShapeComponentRequests::DistanceFromPoint, AZ::Vector3(5.0f, 5.0f, -10.0f));
|
|
EXPECT_TRUE(AZ::IsCloseMag(distance, 10.0f));
|
|
}
|
|
|
|
{
|
|
float distance;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(distance, entity.GetId(), &LmbrCentral::ShapeComponentRequests::DistanceFromPoint, AZ::Vector3(5.0f, 13.0f, 14.0f));
|
|
EXPECT_TRUE(AZ::IsCloseMag(distance, 5.0f));
|
|
}
|
|
}
|
|
|
|
TEST_F(PolygonPrismShapeTest, PolygonShapeComponent_DistanceFromPointWithNonUniformScale)
|
|
{
|
|
AZ::Entity entity;
|
|
AZ::Transform transform = AZ::Transform::CreateFromQuaternionAndTranslation(
|
|
AZ::Quaternion::CreateRotationY(AZ::DegToRad(45.0f)), AZ::Vector3(3.0f, 4.0f, 5.0f));
|
|
transform.MultiplyByUniformScale(1.5f);
|
|
const float height = 1.2f;
|
|
const AZ::Vector3 nonUniformScale(2.0f, 1.2f, 0.5f);
|
|
const AZStd::vector<AZ::Vector2> vertices =
|
|
{
|
|
AZ::Vector2(1.0f, -1.0f),
|
|
AZ::Vector2(2.0f, 0.0f),
|
|
AZ::Vector2(-2.0f, 1.0f),
|
|
AZ::Vector2(-1.0f, -1.0f)
|
|
};
|
|
|
|
CreatePolygonPrismWithNonUniformScale(transform, height, vertices, nonUniformScale, entity);
|
|
|
|
float distance = AZ::Constants::FloatMax;
|
|
|
|
// a point which should be closest to one of the rectangular faces of the prism
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(distance, entity.GetId(),
|
|
&LmbrCentral::ShapeComponentRequests::DistanceFromPoint, AZ::Vector3(4.0f, 5.0f, 4.5f));
|
|
EXPECT_NEAR(distance, 0.2562f, 1e-3f);
|
|
|
|
// a point which should be closest to one of the edges connecting the two polygonal faces
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(distance, entity.GetId(),
|
|
&LmbrCentral::ShapeComponentRequests::DistanceFromPoint, AZ::Vector3(1.0f, 1.0f, 7.5f));
|
|
EXPECT_NEAR(distance, 1.2137f, 1e-3f);
|
|
|
|
// a point which should be closest to an edge of the top polygonal face
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(distance, entity.GetId(),
|
|
&LmbrCentral::ShapeComponentRequests::DistanceFromPoint, AZ::Vector3(7.5f, 3.0f, 2.5f));
|
|
EXPECT_NEAR(distance, 0.6041f, 1e-3f);
|
|
|
|
// a point which should be closest to a corner of the top polygonal face
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(distance, entity.GetId(),
|
|
&LmbrCentral::ShapeComponentRequests::DistanceFromPoint, AZ::Vector3(-1.0, 6.0f, 11.0f));
|
|
EXPECT_NEAR(distance, 1.2048f, 1e-3f);
|
|
|
|
// a point which should be closest to the bottom polygonal face
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(distance, entity.GetId(),
|
|
&LmbrCentral::ShapeComponentRequests::DistanceFromPoint, AZ::Vector3(2.0f, 4.0f, 5.5f));
|
|
EXPECT_NEAR(distance, 0.3536f, 1e-3f);
|
|
|
|
// a point which should be closest to the top polygonal face
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(distance, entity.GetId(),
|
|
&LmbrCentral::ShapeComponentRequests::DistanceFromPoint, AZ::Vector3(4.0f, 3.5f, 5.5f));
|
|
EXPECT_NEAR(distance, 0.1607f, 1e-3f);
|
|
|
|
// several points which should be just inside the prism
|
|
auto insidePoints = {
|
|
AZ::Vector3(0.0f, 5.5f, 9.0f),
|
|
AZ::Vector3(1.5f, 2.5f, 7.5f),
|
|
AZ::Vector3(5.5f, 2.5f, 3.75f),
|
|
AZ::Vector3(7.75f, 4.0f, 1.5f),
|
|
AZ::Vector3(2.5f, 3.0f, 5.6f),
|
|
AZ::Vector3(4.0f, 4.5f, 5.25f)
|
|
};
|
|
|
|
for (const auto& point : insidePoints)
|
|
{
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(distance, entity.GetId(),
|
|
&LmbrCentral::ShapeComponentRequests::DistanceFromPoint, AZ::Vector3(point));
|
|
EXPECT_NEAR(distance, 0.0f, 1e-3f);
|
|
}
|
|
}
|
|
|
|
// ccw
|
|
TEST_F(PolygonPrismShapeTest, GetRayIntersectPolygonPrismSuccess1)
|
|
{
|
|
AZ::Entity entity;
|
|
CreatePolygonPrism(
|
|
AZ::Transform::CreateIdentity(),
|
|
10.0f, AZStd::vector<AZ::Vector2>(
|
|
{
|
|
AZ::Vector2(0.0f, 0.0f),
|
|
AZ::Vector2(0.0f, 10.0f),
|
|
AZ::Vector2(10.0f, 10.0f),
|
|
AZ::Vector2(10.0f, 0.0f)
|
|
}),
|
|
entity);
|
|
|
|
bool rayHit = false;
|
|
float distance;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(
|
|
rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay,
|
|
AZ::Vector3(5.0f, 5.0f, 15.0f), AZ::Vector3(0.0f, 0.0f, -1.0f), distance);
|
|
|
|
EXPECT_TRUE(rayHit);
|
|
EXPECT_NEAR(distance, 5.0f, 1e-2f);
|
|
}
|
|
|
|
// cw
|
|
TEST_F(PolygonPrismShapeTest, GetRayIntersectPolygonPrismSuccess2)
|
|
{
|
|
AZ::Entity entity;
|
|
CreatePolygonPrism(
|
|
AZ::Transform::CreateIdentity(),
|
|
10.0f, AZStd::vector<AZ::Vector2>(
|
|
{
|
|
AZ::Vector2(0.0f, 0.0f),
|
|
AZ::Vector2(10.0f, 0.0f),
|
|
AZ::Vector2(10.0f, 10.0f),
|
|
AZ::Vector2(0.0f, 10.0f),
|
|
}),
|
|
entity);
|
|
|
|
bool rayHit = false;
|
|
float distance;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(
|
|
rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay,
|
|
AZ::Vector3(5.0f, 5.0f, 15.0f), AZ::Vector3(0.0f, 0.0f, -1.0f), distance);
|
|
|
|
EXPECT_TRUE(rayHit);
|
|
EXPECT_NEAR(distance, 5.0f, 1e-2f);
|
|
}
|
|
|
|
TEST_F(PolygonPrismShapeTest, GetRayIntersectPolygonPrismSuccess3)
|
|
{
|
|
AZ::Entity entity;
|
|
CreatePolygonPrism(
|
|
AZ::Transform::CreateFromQuaternionAndTranslation(
|
|
AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisX(), AZ::Constants::HalfPi),
|
|
AZ::Vector3(2.0f, 0.0f, 5.0f)),
|
|
2.0f,
|
|
AZStd::vector<AZ::Vector2>(
|
|
{
|
|
AZ::Vector2(1.0f, 0.0f),
|
|
AZ::Vector2(-1.0f, -2.0f),
|
|
AZ::Vector2(-4.0f, -2.0f),
|
|
AZ::Vector2(-6.0f, 0.0f),
|
|
AZ::Vector2(-4.0f, 2.0f),
|
|
AZ::Vector2(-1.0f, 2.0f)
|
|
}),
|
|
entity);
|
|
|
|
{
|
|
bool rayHit = false;
|
|
float distance;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(
|
|
rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay,
|
|
AZ::Vector3(0.0f, 5.0f, 5.0f), AZ::Vector3(0.0f, -1.0f, 0.0f), distance);
|
|
|
|
EXPECT_TRUE(rayHit);
|
|
EXPECT_NEAR(distance, 5.0f, 1e-2f);
|
|
}
|
|
|
|
{
|
|
bool rayHit = false;
|
|
float distance;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(
|
|
rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay,
|
|
AZ::Vector3(0.0f, -1.0f, 9.0f), AZ::Vector3(0.0f, 0.0f, -1.0f), distance);
|
|
|
|
EXPECT_TRUE(rayHit);
|
|
EXPECT_NEAR(distance, 2.0f, 1e-2f);
|
|
}
|
|
}
|
|
|
|
// transformed scaled
|
|
TEST_F(PolygonPrismShapeTest, GetRayIntersectPolygonPrismSuccess4)
|
|
{
|
|
AZ::Entity entity;
|
|
CreatePolygonPrism(
|
|
AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 15.0f, 40.0f)) *
|
|
AZ::Transform::CreateUniformScale(3.0f), 2.0f,
|
|
AZStd::vector<AZ::Vector2>(
|
|
{
|
|
AZ::Vector2(-2.0f, -2.0f),
|
|
AZ::Vector2(2.0f, -2.0f),
|
|
AZ::Vector2(2.0f, 2.0f),
|
|
AZ::Vector2(-2.0f, 2.0f)
|
|
}),
|
|
entity);
|
|
|
|
{
|
|
bool rayHit = false;
|
|
float distance;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(
|
|
rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay,
|
|
AZ::Vector3(5.0f, 15.0f, 51.0f), AZ::Vector3(0.0f, 0.0f, -1.0f), distance);
|
|
|
|
EXPECT_TRUE(rayHit);
|
|
EXPECT_NEAR(distance, 5.0f, 1e-2f);
|
|
}
|
|
|
|
{
|
|
bool rayHit = false;
|
|
float distance;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(
|
|
rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay,
|
|
AZ::Vector3(15.0f, 15.0f, 43.0f), AZ::Vector3(-1.0f, 0.0f, 0.0f), distance);
|
|
|
|
EXPECT_TRUE(rayHit);
|
|
EXPECT_NEAR(distance, 4.0f, 1e-2f);
|
|
}
|
|
}
|
|
|
|
TEST_F(PolygonPrismShapeTest, GetRayIntersectPolygonPrismFailure)
|
|
{
|
|
AZ::Entity entity;
|
|
CreatePolygonPrism(
|
|
AZ::Transform::CreateIdentity(),
|
|
1.0f, AZStd::vector<AZ::Vector2>(
|
|
{
|
|
AZ::Vector2(0.0f, 0.0f),
|
|
AZ::Vector2(0.0f, 10.0f),
|
|
AZ::Vector2(10.0f, 10.0f),
|
|
AZ::Vector2(10.0f, 0.0f)
|
|
}),
|
|
entity);
|
|
|
|
bool rayHit = false;
|
|
float distance;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(
|
|
rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay,
|
|
AZ::Vector3(-3.0f, -1.0f, 2.0f), AZ::Vector3(1.0f, 0.0f, 0.0f), distance);
|
|
|
|
EXPECT_FALSE(rayHit);
|
|
}
|
|
|
|
TEST_F(PolygonPrismShapeTest, GetRayIntersectWithNonUniformScale)
|
|
{
|
|
AZ::Entity entity;
|
|
AZ::Transform transform = AZ::Transform::CreateFromQuaternionAndTranslation(
|
|
AZ::Quaternion::CreateRotationY(AZ::DegToRad(60.0f)), AZ::Vector3(1.0f, 2.5f, -1.0f));
|
|
transform.MultiplyByUniformScale(2.0f);
|
|
const float height = 1.5f;
|
|
const AZ::Vector3 nonUniformScale(0.5f, 1.5f, 2.0f);
|
|
|
|
const AZStd::vector<AZ::Vector2> vertices = {
|
|
AZ::Vector2(0.0f, -2.0f),
|
|
AZ::Vector2(2.0f, 0.0f),
|
|
AZ::Vector2(-1.0f, 2.0f)
|
|
};
|
|
|
|
CreatePolygonPrismWithNonUniformScale(transform, height, vertices, nonUniformScale, entity);
|
|
|
|
// should hit one of the rectangular faces
|
|
bool rayHit = false;
|
|
AZ::Vector3 rayOrigin(3.0f, 3.0f, -3.0f);
|
|
AZ::Vector3 rayDirection = AZ::Vector3::CreateAxisZ();
|
|
float distance;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(
|
|
rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay,
|
|
rayOrigin, rayDirection, distance);
|
|
EXPECT_TRUE(rayHit);
|
|
EXPECT_NEAR(distance, 1.1340f, 1e-3f);
|
|
|
|
// should hit a different rectangular face
|
|
rayHit = false;
|
|
rayOrigin = AZ::Vector3(2.0f, 2.0f, -3.0f);
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(
|
|
rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay,
|
|
rayOrigin, rayDirection, distance);
|
|
EXPECT_TRUE(rayHit);
|
|
EXPECT_NEAR(distance, 0.4604f, 1e-3f);
|
|
|
|
// should hit one of the triangular end faces
|
|
rayHit = false;
|
|
rayOrigin = AZ::Vector3(1.0f, 1.0f, -3.0f);
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(
|
|
rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay,
|
|
rayOrigin, rayDirection, distance);
|
|
EXPECT_TRUE(rayHit);
|
|
EXPECT_NEAR(distance, 2.0f, 1e-3f);
|
|
|
|
// should miss the prism
|
|
rayHit = true;
|
|
rayOrigin = AZ::Vector3(0.0f, 0.0f, -3.0f);
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(
|
|
rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay,
|
|
rayOrigin, rayDirection, distance);
|
|
EXPECT_FALSE(rayHit);
|
|
}
|
|
|
|
TEST_F(PolygonPrismShapeTest, PolygonShapeComponent_GetAabb1)
|
|
{
|
|
AZ::Entity entity;
|
|
CreatePolygonPrism(
|
|
AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 5.0f, 5.0f)), 10.0f,
|
|
AZStd::vector<AZ::Vector2>(
|
|
{
|
|
AZ::Vector2(0.0f, 0.0f),
|
|
AZ::Vector2(0.0f, 10.0f),
|
|
AZ::Vector2(10.0f, 10.0f),
|
|
AZ::Vector2(10.0f, 0.0f)
|
|
}),
|
|
entity);
|
|
|
|
AZ::Aabb aabb;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(
|
|
aabb, entity.GetId(), &LmbrCentral::ShapeComponentRequests::GetEncompassingAabb);
|
|
|
|
EXPECT_TRUE(aabb.GetMin().IsClose(AZ::Vector3(5.0f, 5.0f, 5.0f)));
|
|
EXPECT_TRUE(aabb.GetMax().IsClose(AZ::Vector3(15.0f, 15.0f, 15.0f)));
|
|
}
|
|
|
|
TEST_F(PolygonPrismShapeTest, PolygonShapeComponent_GetAabb2)
|
|
{
|
|
AZ::Entity entity;
|
|
CreatePolygonPrism(
|
|
AZ::Transform::CreateFromQuaternionAndTranslation(
|
|
AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisX(), AZ::Constants::QuarterPi) *
|
|
AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisY(), AZ::Constants::QuarterPi),
|
|
AZ::Vector3(5.0f, 15.0f, 20.0f)), 5.0f,
|
|
AZStd::vector<AZ::Vector2>(
|
|
{
|
|
AZ::Vector2(-2.0f, -2.0f),
|
|
AZ::Vector2(2.0f, -2.0f),
|
|
AZ::Vector2(2.0f, 2.0f),
|
|
AZ::Vector2(-2.0f, 2.0f)
|
|
}),
|
|
entity);
|
|
|
|
AZ::Aabb aabb;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(
|
|
aabb, entity.GetId(), &LmbrCentral::ShapeComponentRequests::GetEncompassingAabb);
|
|
|
|
EXPECT_TRUE(aabb.GetMin().IsClose(AZ::Vector3(3.5857f, 10.08578f, 17.5857f)));
|
|
EXPECT_TRUE(aabb.GetMax().IsClose(AZ::Vector3(9.9497f, 17.41413f, 24.9142f)));
|
|
}
|
|
|
|
// transformed scaled
|
|
TEST_F(PolygonPrismShapeTest, PolygonShapeComponent_GetAabb3)
|
|
{
|
|
AZ::Entity entity;
|
|
CreatePolygonPrism(
|
|
AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 15.0f, 40.0f)) *
|
|
AZ::Transform::CreateUniformScale(3.0f), 1.5f,
|
|
AZStd::vector<AZ::Vector2>(
|
|
{
|
|
AZ::Vector2(-2.0f, -2.0f),
|
|
AZ::Vector2(2.0f, -2.0f),
|
|
AZ::Vector2(2.0f, 2.0f),
|
|
AZ::Vector2(-2.0f, 2.0f)
|
|
}),
|
|
entity);
|
|
|
|
AZ::Aabb aabb;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(
|
|
aabb, entity.GetId(), &LmbrCentral::ShapeComponentRequests::GetEncompassingAabb);
|
|
|
|
EXPECT_TRUE(aabb.GetMin().IsClose(AZ::Vector3(-1.0f, 9.0f, 40.0f)));
|
|
EXPECT_TRUE(aabb.GetMax().IsClose(AZ::Vector3(11.0f, 21.0f, 44.5f)));
|
|
}
|
|
|
|
TEST_F(PolygonPrismShapeTest, PolygonShapeComponent_GetAabbWithNonUniformScale)
|
|
{
|
|
AZ::Entity entity;
|
|
AZ::Transform transform = AZ::Transform::CreateFromQuaternionAndTranslation(
|
|
AZ::Quaternion::CreateRotationX(AZ::DegToRad(30.0f)), AZ::Vector3(2.0f, -5.0f, 3.0f));
|
|
transform.MultiplyByUniformScale(2.0f);
|
|
const float height = 1.2f;
|
|
const AZ::Vector3 nonUniformScale(1.5f, 0.8f, 2.0f);
|
|
const AZStd::vector<AZ::Vector2> vertices =
|
|
{
|
|
AZ::Vector2(-2.0f, -2.0f),
|
|
AZ::Vector2(1.0f, 0.0f),
|
|
AZ::Vector2(2.0f, 3.0f),
|
|
AZ::Vector2(-1.0f, 4.0f),
|
|
AZ::Vector2(-3.0f, 2.0f)
|
|
};
|
|
|
|
CreatePolygonPrismWithNonUniformScale(transform, height, vertices, nonUniformScale, entity);
|
|
|
|
AZ::Aabb aabb;
|
|
LmbrCentral::ShapeComponentRequestsBus::EventResult(
|
|
aabb, entity.GetId(), &LmbrCentral::ShapeComponentRequests::GetEncompassingAabb);
|
|
|
|
EXPECT_THAT(aabb.GetMin(), IsClose(AZ::Vector3(-7.0f, -10.171281f, 1.4f)));
|
|
EXPECT_THAT(aabb.GetMax(), IsClose(AZ::Vector3(8.0f, 0.542563f, 10.356922f)));
|
|
}
|
|
|
|
TEST_F(PolygonPrismShapeTest, CopyingPolygonPrismDoesNotAssertInEbusSystem)
|
|
{
|
|
AZ::EntityId testEntityId{ 42 };
|
|
LmbrCentral::PolygonPrismShape sourceShape;
|
|
sourceShape.Activate(testEntityId);
|
|
// The assignment shouldn't assert in the EBusEventHandler::BusConnect call
|
|
LmbrCentral::PolygonPrismShape targetShape;
|
|
AZ_TEST_START_TRACE_SUPPRESSION;
|
|
targetShape = sourceShape;
|
|
AZ_TEST_STOP_TRACE_SUPPRESSION(0);
|
|
// The copy constructor also should assert
|
|
AZ_TEST_START_TRACE_SUPPRESSION;
|
|
LmbrCentral::PolygonPrismShape copyShape(sourceShape);
|
|
AZ_TEST_STOP_TRACE_SUPPRESSION(0);
|
|
sourceShape.Deactivate();
|
|
}
|
|
|
|
TEST_F(AllocatorsFixture, PolygonPrismFilledMeshClearedWithLessThanThreeVertices)
|
|
{
|
|
// given
|
|
// invalid vertex data (less than three vertices)
|
|
const auto vertices = AZStd::vector<AZ::Vector2>{AZ::Vector2(0.0f, 0.0f), AZ::Vector2(1.0f, 0.0f)};
|
|
|
|
// fill polygon prism mesh with some initial triangle data (to ensure it's cleared)
|
|
LmbrCentral::PolygonPrismMesh polygonPrismMesh;
|
|
polygonPrismMesh.m_triangles = AZStd::vector<AZ::Vector3>{
|
|
AZ::Vector3(0.0f, 0.0f, 0.0f), AZ::Vector3(0.0f, 1.0f, 0.0f), AZ::Vector3(1.0f, 0.0f, 0.0f)};
|
|
|
|
// when
|
|
const AZ::Vector3 nonUniformScale = AZ::Vector3::CreateOne();
|
|
LmbrCentral::GeneratePolygonPrismMesh(vertices, 1.0f, nonUniformScale, polygonPrismMesh);
|
|
|
|
// then
|
|
EXPECT_TRUE(polygonPrismMesh.m_triangles.empty());
|
|
}
|
|
}
|