Update to how entity space is treated in the viewport (#4263)
* first pass fixes for how entity space is handled in the viewport interaction model Signed-off-by: hultonha <hultonha@amazon.co.uk> * small updates to simplify space handling Signed-off-by: hultonha <hultonha@amazon.co.uk> * fix for influence group with one entity selected Signed-off-by: hultonha <hultonha@amazon.co.uk> * some tidy-up and fix for scale manipulator snapping Signed-off-by: hultonha <hultonha@amazon.co.uk> * couple of small fixes for scale manipulator Signed-off-by: hultonha <hultonha@amazon.co.uk> * small comment update Signed-off-by: hultonha <hultonha@amazon.co.uk> * fixes for integration test failures Signed-off-by: hultonha <hultonha@amazon.co.uk> * add test for rotation manipulator Signed-off-by: hultonha <hultonha@amazon.co.uk> * add test coverage for rotation manipulators Signed-off-by: hultonha <hultonha@amazon.co.uk> * add tests for translation manipulators and some other tidy-up changes Signed-off-by: hultonha <hultonha@amazon.co.uk> * add tests for translating a group of entities Signed-off-by: hultonha <hultonha@amazon.co.uk> * add some tests for scale manipulators Signed-off-by: hultonha <hultonha@amazon.co.uk> * some updates and formatting changes (clang-format) to ViewportScreen Signed-off-by: hultonha <hultonha@amazon.co.uk> * simplify usage of lround code Signed-off-by: hultonha <hultonha@amazon.co.uk> * update missed name updates Signed-off-by: hultonha <hultonha@amazon.co.uk> * update usage of WorldToScreenNdc Signed-off-by: hultonha <hultonha@amazon.co.uk> * updates following review feedback Signed-off-by: hultonha <hultonha@amazon.co.uk> * some more small tidy-up changes Signed-off-by: hultonha <hultonha@amazon.co.uk> * move static variables to be marked inline Signed-off-by: hultonha <hultonha@amazon.co.uk> * small formatting fixes Signed-off-by: hultonha <hultonha@amazon.co.uk>
This commit is contained in:
@@ -6,8 +6,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/Math/Matrix3x4.h>
|
||||
#include <AzCore/Math/Matrix3x3.h>
|
||||
#include <AzCore/Math/Matrix3x4.h>
|
||||
#include <AzCore/Math/Matrix4x4.h>
|
||||
#include <AzCore/Math/Transform.h>
|
||||
#include <AzCore/Math/VectorConversions.h>
|
||||
@@ -20,18 +20,17 @@
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
// transform a point from normalized device coordinates to world space, and then from world space back to normalized device coordinates
|
||||
AZ::Vector2 ScreenNDCToWorldToScreenNDC(
|
||||
const AZ::Vector2& ndcPoint, const AzFramework::CameraState& cameraState)
|
||||
// transform a point from normalized device coordinates to world space, and then from world space back to normalized device coordinates
|
||||
AZ::Vector2 ScreenNdcToWorldToScreenNdc(const AZ::Vector2& ndcPoint, const AzFramework::CameraState& cameraState)
|
||||
{
|
||||
const auto worldResult = AzFramework::ScreenNDCToWorld(ndcPoint, InverseCameraView(cameraState), InverseCameraProjection(cameraState));
|
||||
const auto ndcResult = AzFramework::WorldToScreenNDC(worldResult, CameraView(cameraState), CameraProjection(cameraState));
|
||||
const auto worldResult =
|
||||
AzFramework::ScreenNdcToWorld(ndcPoint, InverseCameraView(cameraState), InverseCameraProjection(cameraState));
|
||||
const auto ndcResult = AzFramework::WorldToScreenNdc(worldResult, CameraView(cameraState), CameraProjection(cameraState));
|
||||
return AZ::Vector3ToVector2(ndcResult);
|
||||
}
|
||||
|
||||
// transform a point from screen space to world space, and then from world space back to screen space
|
||||
AzFramework::ScreenPoint ScreenToWorldToScreen(
|
||||
const AzFramework::ScreenPoint& screenPoint, const AzFramework::CameraState& cameraState)
|
||||
AzFramework::ScreenPoint ScreenToWorldToScreen(const AzFramework::ScreenPoint& screenPoint, const AzFramework::CameraState& cameraState)
|
||||
{
|
||||
const auto worldResult = AzFramework::ScreenToWorld(screenPoint, cameraState);
|
||||
return AzFramework::WorldToScreen(worldResult, cameraState);
|
||||
@@ -47,25 +46,25 @@ namespace UnitTest
|
||||
|
||||
const auto cameraState = AzFramework::CreateIdentityDefaultCamera(cameraPosition, screenDimensions);
|
||||
{
|
||||
const auto expectedScreenPoint = ScreenPoint{600, 450};
|
||||
const auto expectedScreenPoint = ScreenPoint{ 600, 450 };
|
||||
const auto resultScreenPoint = ScreenToWorldToScreen(expectedScreenPoint, cameraState);
|
||||
EXPECT_EQ(resultScreenPoint, expectedScreenPoint);
|
||||
}
|
||||
|
||||
{
|
||||
const auto expectedScreenPoint = ScreenPoint{400, 300};
|
||||
const auto expectedScreenPoint = ScreenPoint{ 400, 300 };
|
||||
const auto resultScreenPoint = ScreenToWorldToScreen(expectedScreenPoint, cameraState);
|
||||
EXPECT_EQ(resultScreenPoint, expectedScreenPoint);
|
||||
}
|
||||
|
||||
{
|
||||
const auto expectedScreenPoint = ScreenPoint{0, 0};
|
||||
const auto expectedScreenPoint = ScreenPoint{ 0, 0 };
|
||||
const auto resultScreenPoint = ScreenToWorldToScreen(expectedScreenPoint, cameraState);
|
||||
EXPECT_EQ(resultScreenPoint, expectedScreenPoint);
|
||||
}
|
||||
|
||||
{
|
||||
const auto expectedScreenPoint = ScreenPoint{800, 600};
|
||||
const auto expectedScreenPoint = ScreenPoint{ 800, 600 };
|
||||
const auto resultScreenPoint = ScreenToWorldToScreen(expectedScreenPoint, cameraState);
|
||||
EXPECT_EQ(resultScreenPoint, expectedScreenPoint);
|
||||
}
|
||||
@@ -81,7 +80,7 @@ namespace UnitTest
|
||||
|
||||
const auto cameraState = AzFramework::CreateDefaultCamera(cameraTransform, screenDimensions);
|
||||
|
||||
const auto expectedScreenPoint = ScreenPoint{200, 300};
|
||||
const auto expectedScreenPoint = ScreenPoint{ 200, 300 };
|
||||
const auto resultScreenPoint = ScreenToWorldToScreen(expectedScreenPoint, cameraState);
|
||||
EXPECT_EQ(resultScreenPoint, expectedScreenPoint);
|
||||
}
|
||||
@@ -93,46 +92,46 @@ namespace UnitTest
|
||||
using AzFramework::ScreenPoint;
|
||||
|
||||
const auto screenDimensions = AZ::Vector2(800.0f, 600.0f);
|
||||
const auto cameraTransform = AZ::Transform::CreateTranslation(AZ::Vector3(10.0f, 0.0f, 0.0f)) *
|
||||
AZ::Transform::CreateRotationZ(AZ::DegToRad(-90.0f));
|
||||
const auto cameraTransform =
|
||||
AZ::Transform::CreateTranslation(AZ::Vector3(10.0f, 0.0f, 0.0f)) * AZ::Transform::CreateRotationZ(AZ::DegToRad(-90.0f));
|
||||
|
||||
const auto cameraState = AzFramework::CreateDefaultCamera(cameraTransform, screenDimensions);
|
||||
|
||||
const auto worldResult = AzFramework::ScreenToWorld(ScreenPoint{400, 300}, cameraState);
|
||||
const auto worldResult = AzFramework::ScreenToWorld(ScreenPoint{ 400, 300 }, cameraState);
|
||||
EXPECT_THAT(worldResult, IsClose(AZ::Vector3(10.1f, 0.0f, 0.0f)));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// NDC tests
|
||||
TEST(ViewportScreen, WorldToScreenNDCAndScreenNDCToWorldReturnsTheSameValueIdentityCameraOffsetFromOrigin)
|
||||
{
|
||||
using NdcPoint = AZ::Vector2;
|
||||
|
||||
|
||||
const auto screenDimensions = AZ::Vector2(800.0f, 600.0f);
|
||||
const auto cameraPosition = AZ::Vector3::CreateAxisY(-10.0f);
|
||||
|
||||
const auto cameraState = AzFramework::CreateIdentityDefaultCamera(cameraPosition, screenDimensions);
|
||||
{
|
||||
const auto expectedNdcPoint = NdcPoint{0.75f, 0.75f};
|
||||
const auto resultNdcPoint = ScreenNDCToWorldToScreenNDC(expectedNdcPoint, cameraState);
|
||||
const auto expectedNdcPoint = NdcPoint{ 0.75f, 0.75f };
|
||||
const auto resultNdcPoint = ScreenNdcToWorldToScreenNdc(expectedNdcPoint, cameraState);
|
||||
EXPECT_THAT(resultNdcPoint, IsClose(expectedNdcPoint));
|
||||
}
|
||||
|
||||
{
|
||||
const auto expectedNdcPoint = NdcPoint{0.5f, 0.5f};
|
||||
const auto resultNdcPoint = ScreenNDCToWorldToScreenNDC(expectedNdcPoint, cameraState);
|
||||
const auto expectedNdcPoint = NdcPoint{ 0.5f, 0.5f };
|
||||
const auto resultNdcPoint = ScreenNdcToWorldToScreenNdc(expectedNdcPoint, cameraState);
|
||||
EXPECT_THAT(resultNdcPoint, IsClose(expectedNdcPoint));
|
||||
}
|
||||
|
||||
{
|
||||
const auto expectedNdcPoint = NdcPoint{0.0f, 0.0f};
|
||||
const auto resultNdcPoint = ScreenNDCToWorldToScreenNDC(expectedNdcPoint, cameraState);
|
||||
const auto expectedNdcPoint = NdcPoint{ 0.0f, 0.0f };
|
||||
const auto resultNdcPoint = ScreenNdcToWorldToScreenNdc(expectedNdcPoint, cameraState);
|
||||
EXPECT_THAT(resultNdcPoint, IsClose(expectedNdcPoint));
|
||||
}
|
||||
|
||||
{
|
||||
const auto expectedNdcPoint = NdcPoint{1.0f, 1.0f};
|
||||
const auto resultNdcPoint = ScreenNDCToWorldToScreenNDC(expectedNdcPoint, cameraState);
|
||||
const auto expectedNdcPoint = NdcPoint{ 1.0f, 1.0f };
|
||||
const auto resultNdcPoint = ScreenNdcToWorldToScreenNdc(expectedNdcPoint, cameraState);
|
||||
EXPECT_THAT(resultNdcPoint, IsClose(expectedNdcPoint));
|
||||
}
|
||||
}
|
||||
@@ -147,8 +146,8 @@ namespace UnitTest
|
||||
|
||||
const auto cameraState = AzFramework::CreateDefaultCamera(cameraTransform, screenDimensions);
|
||||
|
||||
const auto expectedNdcPoint = NdcPoint{0.25f, 0.5f};
|
||||
const auto resultNdcPoint = ScreenNDCToWorldToScreenNDC(expectedNdcPoint, cameraState);
|
||||
const auto expectedNdcPoint = NdcPoint{ 0.25f, 0.5f };
|
||||
const auto resultNdcPoint = ScreenNdcToWorldToScreenNdc(expectedNdcPoint, cameraState);
|
||||
EXPECT_THAT(resultNdcPoint, IsClose(expectedNdcPoint));
|
||||
}
|
||||
|
||||
@@ -159,12 +158,13 @@ namespace UnitTest
|
||||
using NdcPoint = AZ::Vector2;
|
||||
|
||||
const auto screenDimensions = AZ::Vector2(800.0f, 600.0f);
|
||||
const auto cameraTransform = AZ::Transform::CreateTranslation(AZ::Vector3(10.0f, 0.0f, 0.0f)) *
|
||||
AZ::Transform::CreateRotationZ(AZ::DegToRad(-90.0f));
|
||||
const auto cameraTransform =
|
||||
AZ::Transform::CreateTranslation(AZ::Vector3(10.0f, 0.0f, 0.0f)) * AZ::Transform::CreateRotationZ(AZ::DegToRad(-90.0f));
|
||||
|
||||
const auto cameraState = AzFramework::CreateDefaultCamera(cameraTransform, screenDimensions);
|
||||
|
||||
const auto worldResult = AzFramework::ScreenNDCToWorld(NdcPoint{0.5f, 0.5f}, InverseCameraView(cameraState), InverseCameraProjection(cameraState));
|
||||
const auto worldResult =
|
||||
AzFramework::ScreenNdcToWorld(NdcPoint{ 0.5f, 0.5f }, InverseCameraView(cameraState), InverseCameraProjection(cameraState));
|
||||
EXPECT_THAT(worldResult, IsClose(AZ::Vector3(10.1f, 0.0f, 0.0f)));
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ namespace UnitTest
|
||||
using AzFramework::ScreenPoint;
|
||||
using AzFramework::ScreenVector;
|
||||
|
||||
const ScreenVector screenVector = ScreenPoint{100, 200} - ScreenPoint{10, 20};
|
||||
const ScreenVector screenVector = ScreenPoint{ 100, 200 } - ScreenPoint{ 10, 20 };
|
||||
EXPECT_EQ(screenVector, ScreenVector(90, 180));
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ namespace UnitTest
|
||||
using AzFramework::ScreenPoint;
|
||||
using AzFramework::ScreenVector;
|
||||
|
||||
const ScreenPoint screenPoint = ScreenPoint{100, 200} + ScreenVector{50, 25};
|
||||
const ScreenPoint screenPoint = ScreenPoint{ 100, 200 } + ScreenVector{ 50, 25 };
|
||||
EXPECT_EQ(screenPoint, ScreenPoint(150, 225));
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ namespace UnitTest
|
||||
using AzFramework::ScreenPoint;
|
||||
using AzFramework::ScreenVector;
|
||||
|
||||
const ScreenPoint screenPoint = ScreenPoint{120, 200} - ScreenVector{50, 20};
|
||||
const ScreenPoint screenPoint = ScreenPoint{ 120, 200 } - ScreenVector{ 50, 20 };
|
||||
EXPECT_EQ(screenPoint, ScreenPoint(70, 180));
|
||||
}
|
||||
|
||||
@@ -202,7 +202,7 @@ namespace UnitTest
|
||||
using AzFramework::ScreenPoint;
|
||||
using AzFramework::ScreenVector;
|
||||
|
||||
const ScreenVector screenVector = ScreenVector{100, 200} + ScreenVector{50, 25};
|
||||
const ScreenVector screenVector = ScreenVector{ 100, 200 } + ScreenVector{ 50, 25 };
|
||||
EXPECT_EQ(screenVector, ScreenVector(150, 225));
|
||||
}
|
||||
|
||||
@@ -211,7 +211,7 @@ namespace UnitTest
|
||||
using AzFramework::ScreenPoint;
|
||||
using AzFramework::ScreenVector;
|
||||
|
||||
const ScreenVector screenVector = ScreenVector{100, 200} - ScreenVector{50, 25};
|
||||
const ScreenVector screenVector = ScreenVector{ 100, 200 } - ScreenVector{ 50, 25 };
|
||||
EXPECT_EQ(screenVector, ScreenVector(50, 175));
|
||||
}
|
||||
|
||||
@@ -220,8 +220,8 @@ namespace UnitTest
|
||||
using AzFramework::ScreenPoint;
|
||||
using AzFramework::ScreenVector;
|
||||
|
||||
const ScreenPoint screenPoint = ScreenPoint{100, 200};
|
||||
const ScreenVector screenVector = ScreenVector{50, 25};
|
||||
const ScreenPoint screenPoint = ScreenPoint{ 100, 200 };
|
||||
const ScreenVector screenVector = ScreenVector{ 50, 25 };
|
||||
|
||||
const AZ::Vector2 fromScreenPoint = AzFramework::Vector2FromScreenPoint(screenPoint);
|
||||
const AZ::Vector2 fromScreenVector = AzFramework::Vector2FromScreenVector(screenVector);
|
||||
@@ -295,6 +295,58 @@ namespace UnitTest
|
||||
EXPECT_NEAR(AzFramework::ScreenVectorLength(ScreenVector(12, 15)), 19.20937f, 0.001f);
|
||||
}
|
||||
|
||||
TEST(ViewportScreen, ScreenVectorTransformedByScalarUpwards)
|
||||
{
|
||||
using AzFramework::ScreenVector;
|
||||
|
||||
auto screenVector = ScreenVector(5, 10);
|
||||
auto scaledScreenVector = screenVector * 2.0f;
|
||||
|
||||
EXPECT_EQ(scaledScreenVector, ScreenVector(10, 20));
|
||||
}
|
||||
|
||||
TEST(ViewportScreen, ScreenVectorTransformedByScalarWithRounding)
|
||||
{
|
||||
using AzFramework::ScreenVector;
|
||||
|
||||
auto screenVector = ScreenVector(1, 6);
|
||||
auto scaledScreenVector = screenVector * 0.1f;
|
||||
|
||||
// value less than 0.5 rounds down, greater than or equal to 0.5 rounds up
|
||||
EXPECT_EQ(scaledScreenVector, ScreenVector(0, 1));
|
||||
}
|
||||
|
||||
TEST(ViewportScreen, ScreenVectorTransformedByScalarWithRoundingAtHalfwayBoundary)
|
||||
{
|
||||
using AzFramework::ScreenVector;
|
||||
|
||||
auto screenVector = ScreenVector(5, 10);
|
||||
auto scaledScreenVector = screenVector * 0.1f;
|
||||
|
||||
// value less than 0.5 rounds down, greater than or equal to 0.5 rounds up
|
||||
EXPECT_EQ(scaledScreenVector, ScreenVector(1, 1));
|
||||
}
|
||||
|
||||
TEST(ViewportScreen, ScreenVectorTransformedByScalarDownwards)
|
||||
{
|
||||
using AzFramework::ScreenVector;
|
||||
|
||||
auto screenVector = ScreenVector(6, 12);
|
||||
auto scaledScreenVector = screenVector * 0.5f;
|
||||
|
||||
EXPECT_EQ(scaledScreenVector, ScreenVector(3, 6));
|
||||
}
|
||||
|
||||
TEST(ViewportScreen, ScreenVectorTransformedByScalarInplace)
|
||||
{
|
||||
using AzFramework::ScreenVector;
|
||||
|
||||
auto screenVector = ScreenVector(13, 37);
|
||||
screenVector *= 10.0f;
|
||||
|
||||
EXPECT_EQ(screenVector, ScreenVector(130, 370));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Other tests
|
||||
TEST(ViewportScreen, CanGetCameraTransformFromCameraViewAndBack)
|
||||
|
||||
Reference in New Issue
Block a user