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.
195 lines
7.6 KiB
C++
195 lines
7.6 KiB
C++
/*
|
|
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
|
* its licensors.
|
|
*
|
|
* For complete copyright and license terms please see the LICENSE at the root of this
|
|
* distribution (the "License"). All use of this software is governed by the License,
|
|
* or, if provided, by the license below or the license accompanying this file. Do not
|
|
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
*
|
|
*/
|
|
|
|
#include <AzCore/Math/Quaternion.h>
|
|
#include <AzCore/Math/Spline.h>
|
|
#include <AzCore/Serialization/SerializeContext.h>
|
|
#include <AzTest/AzTest.h>
|
|
#include <AzToolsFramework/Picking/Manipulators/ManipulatorBounds.h>
|
|
#include <AzCore/UnitTest/TestTypes.h>
|
|
|
|
namespace UnitTest
|
|
{
|
|
const float g_epsilon = 1e-4f;
|
|
|
|
using namespace AzToolsFramework::Picking;
|
|
|
|
TEST(ManipulatorBounds, Sphere)
|
|
{
|
|
ManipulatorBoundSphere manipulatorBoundSphere(RegisteredBoundId{});
|
|
manipulatorBoundSphere.m_center = AZ::Vector3::CreateZero();
|
|
manipulatorBoundSphere.m_radius = 2.0f;
|
|
|
|
float intersectionDistance;
|
|
bool intersection = manipulatorBoundSphere.IntersectRay(
|
|
AZ::Vector3::CreateAxisY(10.0f), -AZ::Vector3::CreateAxisY(), intersectionDistance);
|
|
|
|
EXPECT_NEAR(intersectionDistance, 8.0f, g_epsilon);
|
|
EXPECT_TRUE(intersection);
|
|
}
|
|
|
|
TEST(ManipulatorBounds, Box)
|
|
{
|
|
ManipulatorBoundBox manipulatorBoundBox(RegisteredBoundId{});
|
|
manipulatorBoundBox.m_center = AZ::Vector3::CreateZero();
|
|
manipulatorBoundBox.m_halfExtents = AZ::Vector3(1.0f);
|
|
manipulatorBoundBox.m_axis1 = AZ::Vector3::CreateAxisX();
|
|
manipulatorBoundBox.m_axis2 = AZ::Vector3::CreateAxisY();
|
|
manipulatorBoundBox.m_axis3 = AZ::Vector3::CreateAxisZ();
|
|
|
|
float intersectionDistance;
|
|
bool intersection = manipulatorBoundBox.IntersectRay(
|
|
AZ::Vector3::CreateAxisY(10.0f), -AZ::Vector3::CreateAxisY(), intersectionDistance);
|
|
|
|
EXPECT_NEAR(intersectionDistance, 9.0f, g_epsilon);
|
|
EXPECT_TRUE(intersection);
|
|
}
|
|
|
|
TEST(ManipulatorBounds, Cylinder)
|
|
{
|
|
ManipulatorBoundCylinder manipulatorCylinder(RegisteredBoundId{});
|
|
manipulatorCylinder.m_base = AZ::Vector3::CreateAxisZ(-5.0f);
|
|
manipulatorCylinder.m_axis = AZ::Vector3::CreateAxisZ();
|
|
manipulatorCylinder.m_height = 10.0f;
|
|
manipulatorCylinder.m_radius = 2.0f;
|
|
|
|
float intersectionDistance;
|
|
bool intersection = manipulatorCylinder.IntersectRay(
|
|
AZ::Vector3::CreateAxisY(10.0f), -AZ::Vector3::CreateAxisY(), intersectionDistance);
|
|
|
|
EXPECT_NEAR(intersectionDistance, 8.0f, g_epsilon);
|
|
EXPECT_TRUE(intersection);
|
|
}
|
|
|
|
TEST(ManipulatorBounds, Cone)
|
|
{
|
|
ManipulatorBoundCone manipulatorCone(RegisteredBoundId{});
|
|
manipulatorCone.m_apexPosition = AZ::Vector3::CreateAxisZ(-5.0f);
|
|
manipulatorCone.m_height = 10.0f;
|
|
manipulatorCone.m_dir = AZ::Vector3::CreateAxisZ();
|
|
manipulatorCone.m_radius = 4.0f;
|
|
|
|
float intersectionDistance;
|
|
bool intersection = manipulatorCone.IntersectRay(
|
|
AZ::Vector3::CreateAxisY(10.0f), -AZ::Vector3::CreateAxisY(), intersectionDistance);
|
|
|
|
EXPECT_NEAR(intersectionDistance, 8.0f, g_epsilon);
|
|
EXPECT_TRUE(intersection);
|
|
}
|
|
|
|
TEST(ManipulatorBounds, Quad)
|
|
{
|
|
ManipulatorBoundQuad manipulatorQuad(RegisteredBoundId{});
|
|
manipulatorQuad.m_corner1 = AZ::Vector3(-1.0f, 0.0f, 1.0f);
|
|
manipulatorQuad.m_corner2 = AZ::Vector3(1.0f, 0.0f, 1.0f);
|
|
manipulatorQuad.m_corner3 = AZ::Vector3(1.0f, 0.0f, -1.0f);
|
|
manipulatorQuad.m_corner4 = AZ::Vector3(-1.0f, 0.0f, -1.0f);
|
|
|
|
float intersectionDistance;
|
|
bool intersection = manipulatorQuad.IntersectRay(
|
|
AZ::Vector3::CreateAxisY(10.0f), -AZ::Vector3::CreateAxisY(), intersectionDistance);
|
|
|
|
EXPECT_NEAR(intersectionDistance, 10.0f, g_epsilon);
|
|
EXPECT_TRUE(intersection);
|
|
}
|
|
|
|
TEST(ManipulatorBounds, Torus)
|
|
{
|
|
ManipulatorBoundTorus manipulatorTorus(RegisteredBoundId{});
|
|
manipulatorTorus.m_axis = AZ::Vector3::CreateAxisY();
|
|
manipulatorTorus.m_center = AZ::Vector3::CreateZero();
|
|
manipulatorTorus.m_majorRadius = 5.0f;
|
|
manipulatorTorus.m_minorRadius = 0.5f;
|
|
|
|
float _;
|
|
bool intersectionCenter = manipulatorTorus.IntersectRay(
|
|
AZ::Vector3::CreateAxisY(10.0f), -AZ::Vector3::CreateAxisY(), _);
|
|
|
|
// miss - through center
|
|
EXPECT_TRUE(!intersectionCenter);
|
|
|
|
float intersectionDistance;
|
|
bool intersectionOutside = manipulatorTorus.IntersectRay(
|
|
AZ::Vector3(5.0f, 10.0f, 0.0f), -AZ::Vector3::CreateAxisY(), intersectionDistance);
|
|
|
|
EXPECT_NEAR(intersectionDistance, 9.5f, g_epsilon);
|
|
EXPECT_TRUE(intersectionOutside);
|
|
}
|
|
|
|
TEST(ManipulatorBounds, RayIntersectsTorusAtAcuteAngle)
|
|
{
|
|
// torus approximation is side-on to ray
|
|
ManipulatorBoundTorus manipulatorTorus(RegisteredBoundId{});
|
|
manipulatorTorus.m_axis = AZ::Vector3::CreateAxisX();
|
|
manipulatorTorus.m_center = AZ::Vector3::CreateZero();
|
|
manipulatorTorus.m_majorRadius = 5.0f;
|
|
manipulatorTorus.m_minorRadius = 0.5f;
|
|
|
|
// calculation used to orientate the ray to hit
|
|
// the inside edge of the cylinder
|
|
//
|
|
// tan @ = opp / adj
|
|
// tan @ = 0.5 / 5.0 = 0.1
|
|
// @ = atan(0.1) = 5.71 degrees
|
|
//
|
|
// tan 5.71 = x / 15
|
|
// x = 15 * tan 5.71 = ~1.5
|
|
|
|
const AZ::Vector3 orientatedPickRay =
|
|
AZ::Quaternion::CreateRotationZ(AZ::DegToRad(5.7f)).TransformVector(-AZ::Vector3::CreateAxisY());
|
|
|
|
float _;
|
|
bool intersection = manipulatorTorus.IntersectRay(
|
|
AZ::Vector3(-1.5f, 10.0f, 0.0f), orientatedPickRay, _);
|
|
|
|
// ensure we get a valid intersection (even if the first hit
|
|
// might have happened in the 'hollow' part of the cylinder)
|
|
EXPECT_TRUE(intersection);
|
|
}
|
|
|
|
TEST(ManipulatorBounds, Line)
|
|
{
|
|
ManipulatorBoundLineSegment manipulatorLine(RegisteredBoundId{});
|
|
manipulatorLine.m_worldStart = AZ::Vector3(-5.0f, 0.0f, 0.0f);
|
|
manipulatorLine.m_worldEnd = AZ::Vector3(5.0f, 0.0f, 0.0f);
|
|
manipulatorLine.m_width = 0.2f;
|
|
|
|
float intersectionDistance;
|
|
bool intersection = manipulatorLine.IntersectRay(
|
|
AZ::Vector3::CreateAxisY(10.0f), -AZ::Vector3::CreateAxisY(), intersectionDistance);
|
|
|
|
EXPECT_NEAR(intersectionDistance, 10.0f, g_epsilon);
|
|
EXPECT_TRUE(intersection);
|
|
}
|
|
|
|
TEST(ManipulatorBounds, Spline)
|
|
{
|
|
AZStd::shared_ptr<AZ::BezierSpline> bezierSpline = AZStd::make_shared<AZ::BezierSpline>();
|
|
bezierSpline->m_vertexContainer.AddVertex(AZ::Vector3(-10.0f, 0.0f, 0.0f));
|
|
bezierSpline->m_vertexContainer.AddVertex(AZ::Vector3(-5.0f, 0.0f, 0.0f));
|
|
bezierSpline->m_vertexContainer.AddVertex(AZ::Vector3(5.0f, 0.0f, 0.0f));
|
|
bezierSpline->m_vertexContainer.AddVertex(AZ::Vector3(10.0f, 0.0f, 0.0f));
|
|
|
|
ManipulatorBoundSpline manipulatorSpline(RegisteredBoundId{});
|
|
manipulatorSpline.m_spline = bezierSpline;
|
|
manipulatorSpline.m_transform = AZ::Transform::CreateIdentity();
|
|
manipulatorSpline.m_width = 0.2f;
|
|
|
|
float intersectionDistance;
|
|
bool intersection = manipulatorSpline.IntersectRay(
|
|
AZ::Vector3::CreateAxisY(10.0f), -AZ::Vector3::CreateAxisY(), intersectionDistance);
|
|
|
|
EXPECT_NEAR(intersectionDistance, 10.0f, g_epsilon);
|
|
EXPECT_TRUE(intersection);
|
|
}
|
|
} // namespace UnitTest
|