Update return type for viewport screen functions (#5803)

* update return type for viewport screen functions

Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com>

* add tests for AZ::Matrix3x4::CreateFromMatrix4x4 and add TransformPoint to Matrix3x4

Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com>

* update NDC -> Ndc

Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com>

* updates following review feedback

Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com>

* updates and improvements following PR feedback

Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com>

* add forward declaration of Matrix3x4 type

Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com>

* update where forward declarations are defined for Matrix3x4

Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com>
This commit is contained in:
Tom Hulton-Harrop
2021-11-24 09:17:43 +00:00
committed by GitHub
parent b196473465
commit 5bd751531d
20 changed files with 146 additions and 74 deletions
@@ -351,7 +351,8 @@ namespace AZ
->Method("CreateFromMatrix3x3AndTranslation", &Matrix3x4::CreateFromMatrix3x3AndTranslation)
->Method("CreateScale", &Matrix3x4::CreateScale)
->Method("CreateDiagonal", &Matrix3x4::CreateDiagonal)
->Method("CreateTranslation", &Matrix3x4::CreateTranslation);
->Method("CreateTranslation", &Matrix3x4::CreateTranslation)
->Method("UnsafeCreateFromMatrix4x4", &Matrix3x4::UnsafeCreateFromMatrix4x4);
}
}
@@ -90,6 +90,9 @@ namespace AZ
//! Constructs from a Matrix3x3 and a translation.
static Matrix3x4 CreateFromMatrix3x3AndTranslation(const Matrix3x3& matrix3x3, const Vector3& translation);
//! Constructs from a Matrix4x4.
static Matrix3x4 UnsafeCreateFromMatrix4x4(const Matrix4x4& matrix4x4);
//! Constructs from a Transform.
static Matrix3x4 CreateFromTransform(const Transform& transform);
@@ -227,7 +230,7 @@ namespace AZ
Matrix3x4& operator+=(const Matrix3x4& rhs);
//! @}
//! Operator for matrix-matrix substraction.
//! Operator for matrix-matrix subtraction.
//! @{
[[nodiscard]] Matrix3x4 operator-(const Matrix3x4& rhs) const;
Matrix3x4& operator-=(const Matrix3x4& rhs);
@@ -266,6 +269,9 @@ namespace AZ
//! Post-multiplies the matrix by a vector, using only the 3x3 part of the matrix.
[[nodiscard]] Vector3 TransformVector(const Vector3& rhs) const;
//! Post-multiplies the matrix by a point, using the rotation and translation part of the matrix.
[[nodiscard]] Vector3 TransformPoint(const Vector3& rhs) const;
//! Gets the result of transposing the 3x3 part of the matrix, setting the translation part to zero.
[[nodiscard]] Matrix3x4 GetTranspose() const;
@@ -203,6 +203,16 @@ namespace AZ
}
AZ_MATH_INLINE Matrix3x4 Matrix3x4::UnsafeCreateFromMatrix4x4(const Matrix4x4& matrix4x4)
{
Matrix3x4 result;
result.SetRow(0, matrix4x4.GetRow(0));
result.SetRow(1, matrix4x4.GetRow(1));
result.SetRow(2, matrix4x4.GetRow(2));
return result;
}
AZ_MATH_INLINE Matrix3x4 Matrix3x4::CreateScale(const Vector3& scale)
{
return CreateDiagonal(scale);
@@ -609,6 +619,12 @@ namespace AZ
}
AZ_MATH_INLINE Vector3 Matrix3x4::TransformPoint(const Vector3& rhs) const
{
return Multiply3x3(rhs) + GetTranslation();
}
AZ_MATH_INLINE Matrix3x4 Matrix3x4::GetTranspose() const
{
Matrix3x4 result;
@@ -33,6 +33,15 @@ namespace MathTestData
AZ::Matrix3x3::CreateScale(AZ::Vector3(0.7f, 1.3f, 0.9f))
};
static const AZ::Matrix4x4 Matrix4x4s[] = {
AZ::Matrix4x4::CreateIdentity(),
AZ::Matrix4x4::CreateFromQuaternionAndTranslation(AZ::Quaternion(-0.46f, 0.26f, -0.22f, 0.82f), AZ::Vector3(1.0f, 5.0f, 10.0f)),
AZ::Matrix4x4::CreateFromTransform(AZ::Transform::CreateFromMatrix3x3AndTranslation(
AZ::Matrix3x3::CreateScale(AZ::Vector3(1.0f, 2.0f, 3.0f)), AZ::Vector3(2.0f, 4.0f, 6.0f))),
AZ::Matrix4x4::CreateScale(AZ::Vector3(5.0f, 10.0f, 15.0f)),
AZ::Matrix4x4::CreateRotationZ(AZ::DegToRad(45.0f))
};
using AxisPair = AZStd::pair<AZ::Constants::Axis, AZ::Vector3>;
static const AxisPair Axes[] = {
{ AZ::Constants::Axis::XPositive, AZ::Vector3::CreateAxisX(1.0f) },
@@ -10,6 +10,7 @@
#include <AzCore/Math/Matrix3x4.h>
#include <AzCore/Math/Matrix3x3.h>
#include <AzCore/Math/Quaternion.h>
#include <AzCore/Math/VectorConversions.h>
#include <AZTestShared/Math/MathTestHelpers.h>
#include "MathTestData.h"
@@ -392,6 +393,32 @@ namespace UnitTest
INSTANTIATE_TEST_CASE_P(MATH_Matrix3x4, Matrix3x4CreateFromMatrix3x3Fixture, ::testing::ValuesIn(MathTestData::Matrix3x3s));
using Matrix3x4CreateFromMatrix4x4Fixture = ::testing::TestWithParam<AZ::Matrix4x4>;
TEST_P(Matrix3x4CreateFromMatrix4x4Fixture, UnsafeCreateFromMatrix4x4)
{
const AZ::Matrix4x4 matrix4x4 = GetParam();
const AZ::Matrix3x4 matrix3x4 = AZ::Matrix3x4::UnsafeCreateFromMatrix4x4(matrix4x4);
EXPECT_THAT(matrix3x4.GetTranslation(), IsClose(matrix4x4.GetTranslation()));
const AZ::Vector3 vector(2.3f, -0.6, 1.8f);
EXPECT_THAT(matrix3x4.TransformVector(vector), IsClose((matrix4x4 * AZ::Vector3ToVector4(vector, 0.0f)).GetAsVector3()));
const AZ::Vector3 point(12.3f, -5.6, 7.3f);
EXPECT_THAT(matrix3x4.TransformPoint(point), IsClose((matrix4x4 * AZ::Vector3ToVector4(point, 1.0f)).GetAsVector3()));
}
INSTANTIATE_TEST_CASE_P(MATH_Matrix3x4, Matrix3x4CreateFromMatrix4x4Fixture, ::testing::ValuesIn(MathTestData::Matrix4x4s));
TEST(MATH_Matrix3x4, TransformPoint)
{
const AZ::Matrix3x4 matrix3x4 = AZ::Matrix3x4::CreateFromMatrix3x3AndTranslation(
AZ::Matrix3x3::CreateRotationY(AZ::DegToRad(90.0f)), AZ::Vector3(5.0f, 0.0f, 0.0f));
const AZ::Vector3 result = matrix3x4.TransformPoint(AZ::Vector3(1.0f, 0.0f, 0.0f));
const AZ::Vector3 expected = AZ::Vector3(5.0f, 0.0f, -1.0f);
EXPECT_THAT(result, expected);
}
TEST(MATH_Matrix3x4, CreateScale)
{
const AZ::Vector3 scale(1.7f, 0.3f, 2.4f);
@@ -15,6 +15,7 @@
namespace AZ
{
class Matrix4x4;
class Matrix3x4;
class Transform;
class ReflectContext;
} // namespace AZ
@@ -32,6 +33,8 @@ namespace AzFramework
//! Gets the current camera's world to view matrix.
virtual const AZ::Matrix4x4& GetCameraViewMatrix() const = 0;
//! Gets the current camera's world to view matrix as a Matrix3x4.
virtual AZ::Matrix3x4 GetCameraViewMatrixAsMatrix3x4() const = 0;
//! Sets the current camera's world to view matrix.
virtual void SetCameraViewMatrix(const AZ::Matrix4x4& matrix) = 0;
//! Gets the current camera's projection (view to clip) matrix.
@@ -31,34 +31,31 @@ namespace AzFramework
// multiplication which must be used (see CameraTransformFromCameraView and CameraViewFromCameraTransform)
// note: coordinate system convention is right handed
// see Matrix4x4::CreateProjection for more details
static AZ::Matrix4x4 ZYCoordinateSystemConversion()
static AZ::Matrix3x4 ZYCoordinateSystemConversion()
{
// note: the below matrix is the result of these combined transformations
// pitch = AZ::Matrix4x4::CreateRotationX(AZ::DegToRad(-90.0f));
// yaw = AZ::Matrix4x4::CreateRotationZ(AZ::DegToRad(180.0f));
// conversion = pitch * yaw
return AZ::Matrix4x4::CreateFromColumns(
AZ::Vector4(-1.0f, 0.0f, 0.0f, 0.0f), AZ::Vector4(0.0f, 0.0f, 1.0f, 0.0f), AZ::Vector4(0.0f, 1.0f, 0.0f, 0.0f),
AZ::Vector4(0.0f, 0.0f, 0.0f, 1.0f));
return AZ::Matrix3x4::CreateFromColumns(
AZ::Vector3(-1.0f, 0.0f, 0.0f), AZ::Vector3(0.0f, 0.0f, 1.0f), AZ::Vector3(0.0f, 1.0f, 0.0f), AZ::Vector3(0.0f, 0.0f, 0.0f));
}
AZ::Matrix4x4 CameraTransform(const CameraState& cameraState)
AZ::Matrix3x4 CameraTransform(const CameraState& cameraState)
{
return AZ::Matrix4x4::CreateFromColumns(
AZ::Vector3ToVector4(cameraState.m_side), AZ::Vector3ToVector4(cameraState.m_forward), AZ::Vector3ToVector4(cameraState.m_up),
AZ::Vector3ToVector4(cameraState.m_position, 1.0f));
return AZ::Matrix3x4::CreateFromColumns(cameraState.m_side, cameraState.m_forward, cameraState.m_up, cameraState.m_position);
}
AZ::Matrix4x4 CameraView(const CameraState& cameraState)
AZ::Matrix3x4 CameraView(const CameraState& cameraState)
{
// ensure the camera is looking down positive z with the x axis pointing left
return ZYCoordinateSystemConversion() * CameraTransform(cameraState).GetInverseTransform();
return ZYCoordinateSystemConversion() * CameraTransform(cameraState).GetInverseFast();
}
AZ::Matrix4x4 InverseCameraView(const CameraState& cameraState)
AZ::Matrix3x4 InverseCameraView(const CameraState& cameraState)
{
// ensure the camera is looking down positive z with the x axis pointing left
return CameraView(cameraState).GetInverseTransform();
return CameraView(cameraState).GetInverseFast();
}
AZ::Matrix4x4 CameraProjection(const CameraState& cameraState)
@@ -72,14 +69,14 @@ namespace AzFramework
return CameraProjection(cameraState).GetInverseFull();
}
AZ::Matrix4x4 CameraTransformFromCameraView(const AZ::Matrix4x4& cameraView)
AZ::Matrix3x4 CameraTransformFromCameraView(const AZ::Matrix3x4& cameraView)
{
return (ZYCoordinateSystemConversion() * cameraView).GetInverseTransform();
return (ZYCoordinateSystemConversion() * cameraView).GetInverseFast();
}
AZ::Matrix4x4 CameraViewFromCameraTransform(const AZ::Matrix4x4& cameraTransform)
AZ::Matrix3x4 CameraViewFromCameraTransform(const AZ::Matrix3x4& cameraTransform)
{
return ZYCoordinateSystemConversion() * cameraTransform.GetInverseTransform();
return ZYCoordinateSystemConversion() * cameraTransform.GetInverseFast();
}
AZ::Frustum FrustumFromCameraState(const CameraState& cameraState)
@@ -91,16 +88,17 @@ namespace AzFramework
{
const auto worldFromView = AzFramework::CameraTransform(cameraState);
const auto cameraWorldTransform = AZ::Transform::CreateFromMatrix3x3AndTranslation(
AZ::Matrix3x3::CreateFromMatrix4x4(worldFromView), worldFromView.GetTranslation());
AZ::Matrix3x3::CreateFromMatrix3x4(worldFromView), worldFromView.GetTranslation());
return AZ::ViewFrustumAttributes(
cameraWorldTransform, AspectRatio(cameraState.m_viewportSize), cameraState.m_fovOrZoom, cameraState.m_nearClip,
cameraState.m_farClip);
}
AZ::Vector3 WorldToScreenNdc(const AZ::Vector3& worldPosition, const AZ::Matrix4x4& cameraView, const AZ::Matrix4x4& cameraProjection)
AZ::Vector3 WorldToScreenNdc(const AZ::Vector3& worldPosition, const AZ::Matrix3x4& cameraView, const AZ::Matrix4x4& cameraProjection)
{
// transform the world space position to clip space
const auto clipSpacePosition = cameraProjection * cameraView * AZ::Vector3ToVector4(worldPosition, 1.0f);
const auto clipSpacePosition =
cameraProjection * AZ::Vector3ToVector4(cameraView.TransformPoint(worldPosition), 1.0f);
// transform the clip space position to ndc space (perspective divide)
const auto ndcPosition = clipSpacePosition / clipSpacePosition.GetW();
// transform ndc space from <-1,1> to <0, 1> range
@@ -109,7 +107,7 @@ namespace AzFramework
ScreenPoint WorldToScreen(
const AZ::Vector3& worldPosition,
const AZ::Matrix4x4& cameraView,
const AZ::Matrix3x4& cameraView,
const AZ::Matrix4x4& cameraProjection,
const AZ::Vector2& viewportSize)
{
@@ -123,7 +121,7 @@ namespace AzFramework
}
AZ::Vector3 ScreenNdcToWorld(
const AZ::Vector2& normalizedScreenPosition, const AZ::Matrix4x4& inverseCameraView, const AZ::Matrix4x4& inverseCameraProjection)
const AZ::Vector2& normalizedScreenPosition, const AZ::Matrix3x4& inverseCameraView, const AZ::Matrix4x4& inverseCameraProjection)
{
// convert screen space coordinates from <0, 1> to <-1,1> range
const auto ndcPosition = normalizedScreenPosition * 2.0f - AZ::Vector2::CreateOne();
@@ -140,7 +138,7 @@ namespace AzFramework
AZ::Vector3 ScreenToWorld(
const ScreenPoint& screenPosition,
const AZ::Matrix4x4& inverseCameraView,
const AZ::Matrix3x4& inverseCameraView,
const AZ::Matrix4x4& inverseCameraProjection,
const AZ::Vector2& viewportSize)
{
@@ -16,6 +16,7 @@
namespace AZ
{
class Frustum;
class Matrix3x4;
class Matrix4x4;
struct ViewFrustumAttributes;
} // namespace AZ
@@ -43,7 +44,7 @@ namespace AzFramework
}
//! Projects a position in world space to screen space normalized device coordinates for the given camera.
AZ::Vector3 WorldToScreenNdc(const AZ::Vector3& worldPosition, const AZ::Matrix4x4& cameraView, const AZ::Matrix4x4& cameraProjection);
AZ::Vector3 WorldToScreenNdc(const AZ::Vector3& worldPosition, const AZ::Matrix3x4& cameraView, const AZ::Matrix4x4& cameraProjection);
//! Projects a position in world space to screen space for the given camera.
ScreenPoint WorldToScreen(const AZ::Vector3& worldPosition, const CameraState& cameraState);
@@ -52,7 +53,7 @@ namespace AzFramework
//! is called many times in a loop.
ScreenPoint WorldToScreen(
const AZ::Vector3& worldPosition,
const AZ::Matrix4x4& cameraView,
const AZ::Matrix3x4& cameraView,
const AZ::Matrix4x4& cameraProjection,
const AZ::Vector2& viewportSize);
@@ -64,14 +65,14 @@ namespace AzFramework
//! is called many times in a loop.
AZ::Vector3 ScreenToWorld(
const ScreenPoint& screenPosition,
const AZ::Matrix4x4& inverseCameraView,
const AZ::Matrix3x4& inverseCameraView,
const AZ::Matrix4x4& inverseCameraProjection,
const AZ::Vector2& viewportSize);
//! Unprojects a position in screen space normalized device coordinates to world space.
//! Note: The position returned will be on the near clip plane of the camera in world space.
AZ::Vector3 ScreenNdcToWorld(
const AZ::Vector2& ndcPosition, const AZ::Matrix4x4& inverseCameraView, const AZ::Matrix4x4& inverseCameraProjection);
const AZ::Vector2& ndcPosition, const AZ::Matrix3x4& inverseCameraView, const AZ::Matrix4x4& inverseCameraProjection);
//! Returns the camera projection for the current camera state.
AZ::Matrix4x4 CameraProjection(const CameraState& cameraState);
@@ -81,27 +82,27 @@ namespace AzFramework
//! Returns the camera view for the current camera state.
//! @note This is the 'v' in the MVP transform going from world space to view space (viewFromWorld).
AZ::Matrix4x4 CameraView(const CameraState& cameraState);
AZ::Matrix3x4 CameraView(const CameraState& cameraState);
//! Returns the inverse of the camera view for the current camera state.
//! @note This is the same as the CameraTransform but corrected for Z up.
AZ::Matrix4x4 InverseCameraView(const CameraState& cameraState);
AZ::Matrix3x4 InverseCameraView(const CameraState& cameraState);
//! Returns the camera transform for the current camera state.
//! @note This is the inverse of 'v' in the MVP transform going from view space to world space (worldFromView).
AZ::Matrix4x4 CameraTransform(const CameraState& cameraState);
AZ::Matrix3x4 CameraTransform(const CameraState& cameraState);
//! Takes a camera view (the world to camera space transform) and returns the
//! corresponding camera transform (the world position and orientation of the camera).
//! @note The parameter is the viewFromWorld transform (the 'v' in MVP) going from world space
//! to view space. The return value is worldFromView transform going from view space to world space.
AZ::Matrix4x4 CameraTransformFromCameraView(const AZ::Matrix4x4& cameraView);
AZ::Matrix3x4 CameraTransformFromCameraView(const AZ::Matrix3x4& cameraView);
//! Takes a camera transform (the world position and orientation of the camera) and
//! returns the corresponding camera view (to be used to transform from world to camera space).
//! @note The parameter is the worldFromView transform going from view space to world space. The
//! return value is viewFromWorld transform (the 'v' in MVP) going from view space to world space.
AZ::Matrix4x4 CameraViewFromCameraTransform(const AZ::Matrix4x4& cameraTransform);
AZ::Matrix3x4 CameraViewFromCameraTransform(const AZ::Matrix3x4& cameraTransform);
//! Returns a frustum representing the camera transform and view volume in world space.
AZ::Frustum FrustumFromCameraState(const CameraState& cameraState);
@@ -3497,7 +3497,7 @@ namespace AzToolsFramework
// get the editor cameras current orientation
const int viewportId = viewportInfo.m_viewportId;
const AzFramework::CameraState editorCameraState = GetCameraState(viewportId);
const AZ::Matrix3x3& editorCameraOrientation = AZ::Matrix3x3::CreateFromMatrix4x4(AzFramework::CameraTransform(editorCameraState));
const AZ::Matrix3x3& editorCameraOrientation = AZ::Matrix3x3::CreateFromMatrix3x4(AzFramework::CameraTransform(editorCameraState));
// create a gizmo camera transform about the origin matching the orientation of the editor camera
// (10 units back in the y axis to produce an orbit effect)