| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- /*
- * 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 <AzCore/UnitTest/TestTypes.h>
- #include <AzCore/Math/Transform.h>
- #include <AzFramework/Viewport/CameraState.h>
- #include <AZTestShared/Math/MathTestHelpers.h>
- #include <AzCore/Math/SimdMath.h>
- #include <AzCore/Math/MatrixUtils.h>
- #include <AzCore/Math/Matrix4x4.h>
- namespace UnitTest
- {
- class CameraStateFixture
- : public ::testing::Test
- {
- public:
- void SetUp() override
- {
- m_cameraState = AzFramework::CreateDefaultCamera(AZ::Transform::CreateIdentity(), AzFramework::ScreenSize(1024, 768));
- }
- AzFramework::CameraState m_cameraState;
- };
- class Translation
- : public CameraStateFixture
- , public ::testing::WithParamInterface<AZStd::tuple<float, float, float>>
- {
- };
- class Rotation
- : public CameraStateFixture
- , public ::testing::WithParamInterface<AZStd::tuple<float, float, float>>
- {
- };
- class WorldFromViewMatrix
- : public CameraStateFixture
- , public ::testing::WithParamInterface<AZStd::tuple<AZ::Vector3, AZ::Vector3, AzFramework::ScreenSize>>
- {
- };
- class PerspectiveMatrix
- : public CameraStateFixture
- , public ::testing::WithParamInterface<AZStd::tuple<float, float, float, float>>
- {
- };
- TEST_P(Translation, Permutation)
- {
- // Given a position
- const auto [x, y, z] = GetParam();
- const AZ::Vector3 expectedPosition(x, y, z);
- // Set the camera state's transform to the expected position
- AzFramework::SetCameraTransform(m_cameraState, AZ::Transform::CreateTranslation(expectedPosition));
- // Expect the camera state transform's position to be expected position
- EXPECT_THAT(m_cameraState.m_position, IsCloseTolerance(expectedPosition, 0.01f));
- // Expect the camera state transform's orientation to be identity
- EXPECT_THAT(m_cameraState.m_forward, IsCloseTolerance(AZ::Vector3::CreateAxisY(), 0.01f));
- EXPECT_THAT(m_cameraState.m_up, IsCloseTolerance(AZ::Vector3::CreateAxisZ(), 0.01f));
- EXPECT_THAT(m_cameraState.m_side, IsCloseTolerance(AZ::Vector3::CreateAxisX(), 0.01f));
- }
- INSTANTIATE_TEST_SUITE_P(
- CameraState,
- Translation,
- testing::Combine(
- testing::Values(0.0f, 1.0f),
- testing::Values(0.0f, 1.0f),
- testing::Values(0.0f, 1.0f))
- );
- TEST_P(Rotation, Permutation)
- {
- [[maybe_unused]] int expectedErrors = -1;
- AZ_TEST_START_TRACE_SUPPRESSION;
- // Given an orientation derived from the look at points
- const auto [x, y, z] = GetParam();
- const AZ::Vector3 from = AZ::Vector3::CreateZero();
- const AZ::Vector3 to = AZ::Vector3(x, y, z);
- const AZ::Transform expectedTransform = AZ::Transform::CreateLookAt(from, AZ::Vector3(x, y, z));
- // Set the camera's rotation to the expected orientation
- AzFramework::SetCameraTransform(m_cameraState, expectedTransform);
- // Expect the camera state transform's position to be identity
- EXPECT_THAT(m_cameraState.m_position, IsCloseTolerance(AZ::Vector3::CreateZero(), 0.01f));
- if (from.IsClose(to, 0.001f))
- {
- // Expect one error to be generated by AZ::Transform::CreateLookAt() due to from and to being the same position
- expectedErrors = 1;
- // If the look at points yield an invalid orientation, expect identity rotation basis vectors
- EXPECT_THAT(m_cameraState.m_forward, IsCloseTolerance(AZ::Vector3::CreateAxisY(), 0.01f));
- EXPECT_THAT(m_cameraState.m_up, IsCloseTolerance(AZ::Vector3::CreateAxisZ(), 0.01f));
- EXPECT_THAT(m_cameraState.m_side, IsCloseTolerance(AZ::Vector3::CreateAxisX(), 0.01f));
- }
- else
- {
- // Expect no errors to be generated by AZ::Transform::CreateLookAt()
- expectedErrors = 0;
- // If the look at points yield a valid orientation, expect the rotation basis vectors to be that of the orientation
- EXPECT_THAT(m_cameraState.m_forward, IsCloseTolerance(expectedTransform.GetBasisY(), 0.01f));
- EXPECT_THAT(m_cameraState.m_up, IsCloseTolerance(expectedTransform.GetBasisZ(), 0.01f));
- EXPECT_THAT(m_cameraState.m_side, IsCloseTolerance(expectedTransform.GetBasisX(), 0.01f));
- }
- AZ_TEST_STOP_TRACE_SUPPRESSION(expectedErrors);
- }
- INSTANTIATE_TEST_SUITE_P(
- CameraState,
- Rotation,
- testing::Combine(
- testing::Values(0.0f, 1.0f),
- testing::Values(0.0f, 1.0f),
- testing::Values(0.0f, 1.0f))
- );
- TEST_P(WorldFromViewMatrix, Permutation)
- {
- auto [translation, eulerRotation, viewportSize] = GetParam();
- // Quaternion::CreateFromEulerAnglesDegrees takes a non-const Vector3&
- AZ::Vector3 eulerRotationCopy = eulerRotation;
- AZ::Quaternion rotation = AZ::Quaternion::CreateFromEulerAnglesDegrees(eulerRotationCopy);
- AZ::Matrix4x4 worldFromView = AZ::Matrix4x4::CreateFromQuaternionAndTranslation(rotation, translation);
- m_cameraState = AzFramework::CreateCameraFromWorldFromViewMatrix(worldFromView, viewportSize);
- EXPECT_EQ(m_cameraState.m_viewportSize, viewportSize);
- EXPECT_THAT(m_cameraState.m_position, IsCloseTolerance(translation, 0.01f));
- // Translate back into a quaternion to safely compare rotations
- auto decomposedCameraStateRotation =
- AZ::Quaternion::CreateFromBasis(m_cameraState.m_side, m_cameraState.m_forward, m_cameraState.m_up);
- auto rotationDelta = 1.0f - decomposedCameraStateRotation.Dot(decomposedCameraStateRotation);
- EXPECT_NEAR(rotationDelta, 0.f, 0.01f);
- }
- INSTANTIATE_TEST_SUITE_P(
- CameraState,
- WorldFromViewMatrix,
- testing::Combine(
- testing::Values(AZ::Vector3{0.f, 0.f, 0.f}, AZ::Vector3{100.f, 0.f, 0.f}, AZ::Vector3{-5.f,10.f,-1.f}),
- testing::Values(AZ::Vector3{0.f, 0.f, 0.f}, AZ::Vector3{90.f, 0.f, 0.f}, AZ::Vector3{-45.f, -45.f, -45.f}),
- testing::Values(AzFramework::ScreenSize(100, 100))
- )
- );
- TEST_P(PerspectiveMatrix, Permutation)
- {
- auto [fovY, aspectRatio, nearClip, farClip] = GetParam();
- AZ::Matrix4x4 clipFromView;
- MakePerspectiveFovMatrixRH(clipFromView, fovY, aspectRatio, nearClip, farClip);
- AzFramework::SetCameraClippingVolumeFromPerspectiveFovMatrixRH(m_cameraState, clipFromView);
- EXPECT_NEAR(m_cameraState.m_nearClip, nearClip, 0.01f);
- EXPECT_NEAR(m_cameraState.m_farClip, farClip, 1.f);
- EXPECT_NEAR(m_cameraState.m_fovOrZoom, fovY, 0.01f);
- }
- INSTANTIATE_TEST_SUITE_P(
- CameraState,
- PerspectiveMatrix,
- testing::Combine(
- testing::Values(1.f, 0.5f, 2.f),
- testing::Values(1.f, 16.f / 9.f),
- testing::Values(1.f, 50.f),
- testing::Values(100.f, 10000.f)
- )
- );
- } // namespace UnitTest
|