diff --git a/Code/Framework/AzCore/AzCore/Math/Matrix3x4.cpp b/Code/Framework/AzCore/AzCore/Math/Matrix3x4.cpp index 6d79c4c068..78da9e76d2 100644 --- a/Code/Framework/AzCore/AzCore/Math/Matrix3x4.cpp +++ b/Code/Framework/AzCore/AzCore/Math/Matrix3x4.cpp @@ -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); } } diff --git a/Code/Framework/AzCore/AzCore/Math/Matrix3x4.h b/Code/Framework/AzCore/AzCore/Math/Matrix3x4.h index 60a88df686..25653627ea 100644 --- a/Code/Framework/AzCore/AzCore/Math/Matrix3x4.h +++ b/Code/Framework/AzCore/AzCore/Math/Matrix3x4.h @@ -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; diff --git a/Code/Framework/AzCore/AzCore/Math/Matrix3x4.inl b/Code/Framework/AzCore/AzCore/Math/Matrix3x4.inl index 2f127221ab..d1367cd26c 100644 --- a/Code/Framework/AzCore/AzCore/Math/Matrix3x4.inl +++ b/Code/Framework/AzCore/AzCore/Math/Matrix3x4.inl @@ -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; diff --git a/Code/Framework/AzCore/Tests/Math/MathTestData.h b/Code/Framework/AzCore/Tests/Math/MathTestData.h index f87ab8f448..72a98e835d 100644 --- a/Code/Framework/AzCore/Tests/Math/MathTestData.h +++ b/Code/Framework/AzCore/Tests/Math/MathTestData.h @@ -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; static const AxisPair Axes[] = { { AZ::Constants::Axis::XPositive, AZ::Vector3::CreateAxisX(1.0f) }, diff --git a/Code/Framework/AzCore/Tests/Math/Matrix3x4Tests.cpp b/Code/Framework/AzCore/Tests/Math/Matrix3x4Tests.cpp index 8f8f8ca1e9..20d1107757 100644 --- a/Code/Framework/AzCore/Tests/Math/Matrix3x4Tests.cpp +++ b/Code/Framework/AzCore/Tests/Math/Matrix3x4Tests.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include "MathTestData.h" @@ -392,6 +393,32 @@ namespace UnitTest INSTANTIATE_TEST_CASE_P(MATH_Matrix3x4, Matrix3x4CreateFromMatrix3x3Fixture, ::testing::ValuesIn(MathTestData::Matrix3x3s)); + using Matrix3x4CreateFromMatrix4x4Fixture = ::testing::TestWithParam; + + 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); diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/ViewportBus.h b/Code/Framework/AzFramework/AzFramework/Viewport/ViewportBus.h index 131ecc0c57..f53b84a63f 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/ViewportBus.h +++ b/Code/Framework/AzFramework/AzFramework/Viewport/ViewportBus.h @@ -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. diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/ViewportScreen.cpp b/Code/Framework/AzFramework/AzFramework/Viewport/ViewportScreen.cpp index 87eee53fbd..a23b306546 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/ViewportScreen.cpp +++ b/Code/Framework/AzFramework/AzFramework/Viewport/ViewportScreen.cpp @@ -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) { diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/ViewportScreen.h b/Code/Framework/AzFramework/AzFramework/Viewport/ViewportScreen.h index 8a6c0249b2..9cd88e1c0c 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/ViewportScreen.h +++ b/Code/Framework/AzFramework/AzFramework/Viewport/ViewportScreen.h @@ -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); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp index d0318ee181..d3540f8c09 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp @@ -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) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Base.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Base.h index a88c640c19..6f93b0d247 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Base.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Base.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -24,6 +25,8 @@ AZ_DECLARE_BUDGET(RPI); namespace AZ { + class Matrix4x4; + namespace RHI { class ShaderResourceGroup; @@ -52,6 +55,8 @@ namespace AZ using ViewportContextPtr = AZStd::shared_ptr; using ConstViewportContextPtr = AZStd::shared_ptr; + using MatrixChangedEvent = Event; + //! The name used to identify a View within in a Scene. //! Note that the same View could have different tags in different RenderPipelines. using PipelineViewTag = AZ::Name; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/View.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/View.h index eb3592944d..92b9ad695a 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/View.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/View.h @@ -94,6 +94,9 @@ namespace AZ const AZ::Matrix4x4& GetWorldToClipMatrix() const; const AZ::Matrix4x4& GetClipToWorldMatrix() const; + AZ::Matrix3x4 GetWorldToViewMatrixAsMatrix3x4() const; + AZ::Matrix3x4 GetViewToWorldMatrixAsMatrix3x4() const; + //! Get the camera's world transform, converted from the viewToWorld matrix's native y-up to z-up AZ::Transform GetCameraTransform() const; @@ -120,7 +123,6 @@ namespace AZ //! Update View's SRG values and compile. This should only be called once per frame before execute command lists. void UpdateSrg(); - using MatrixChangedEvent = AZ::Event; //! Notifies consumers when the world to view matrix has changed. void ConnectWorldToViewMatrixChangedHandler(MatrixChangedEvent::Handler& handler); //! Notifies consumers when the world to clip matrix has changed. diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContext.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContext.h index 966e6b3016..92cfc720da 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContext.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContext.h @@ -13,7 +13,6 @@ #include #include #include -#include namespace AZ { @@ -98,7 +97,6 @@ namespace AZ //! Alternatively, connect to ViewportContextNotificationsBus and listen to ViewportContextNotifications::OnViewportDpiScalingChanged. void ConnectDpiScalingFactorChangedHandler(ScalarChangedEvent::Handler& handler); - using MatrixChangedEvent = AZ::Event; //! Notifies consumers when the view matrix has changed. void ConnectViewMatrixChangedHandler(MatrixChangedEvent::Handler& handler); //! Notifies consumers when the projection matrix has changed. @@ -121,17 +119,12 @@ namespace AZ void ConnectAboutToBeDestroyedHandler(ViewportIdEvent::Handler& handler); // ViewportRequestBus interface overrides... - //! Gets the current camera's view matrix. const AZ::Matrix4x4& GetCameraViewMatrix() const override; - //! Sets the current camera's view matrix. + AZ::Matrix3x4 GetCameraViewMatrixAsMatrix3x4() const override; void SetCameraViewMatrix(const AZ::Matrix4x4& matrix) override; - //! Gets the current camera's projection matrix. const AZ::Matrix4x4& GetCameraProjectionMatrix() const override; - //! Sets the current camera's projection matrix. void SetCameraProjectionMatrix(const AZ::Matrix4x4& matrix) override; - //! Convenience method, gets the AZ::Transform corresponding to this camera's view matrix. AZ::Transform GetCameraTransform() const override; - //! Convenience method, sets the camera's view matrix from this AZ::Transform. void SetCameraTransform(const AZ::Transform& transform) override; private: diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp index 4ad8dae41c..a5c67b6210 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp @@ -216,6 +216,16 @@ namespace AZ return m_viewToWorldMatrix; } + AZ::Matrix3x4 View::GetWorldToViewMatrixAsMatrix3x4() const + { + return AZ::Matrix3x4::UnsafeCreateFromMatrix4x4(m_worldToViewMatrix); + } + + AZ::Matrix3x4 View::GetViewToWorldMatrixAsMatrix3x4() const + { + return AZ::Matrix3x4::UnsafeCreateFromMatrix4x4(m_viewToWorldMatrix); + } + const AZ::Matrix4x4& View::GetViewToClipMatrix() const { return m_viewToClipMatrix; @@ -267,12 +277,12 @@ namespace AZ passWithDrawListTag->SortDrawList(drawList); } - void View::ConnectWorldToViewMatrixChangedHandler(View::MatrixChangedEvent::Handler& handler) + void View::ConnectWorldToViewMatrixChangedHandler(MatrixChangedEvent::Handler& handler) { handler.Connect(m_onWorldToViewMatrixChange); } - void View::ConnectWorldToClipMatrixChangedHandler(View::MatrixChangedEvent::Handler& handler) + void View::ConnectWorldToClipMatrixChangedHandler(MatrixChangedEvent::Handler& handler) { handler.Connect(m_onWorldToClipMatrixChange); } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/ViewportContext.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/ViewportContext.cpp index 77114e5cf5..1013d35285 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/ViewportContext.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/ViewportContext.cpp @@ -36,12 +36,12 @@ namespace AZ AzFramework::WindowNotificationBus::Handler::BusConnect(nativeWindow); AzFramework::ViewportRequestBus::Handler::BusConnect(id); - m_onProjectionMatrixChangedHandler = ViewportContext::MatrixChangedEvent::Handler([this](const AZ::Matrix4x4& matrix) + m_onProjectionMatrixChangedHandler = MatrixChangedEvent::Handler([this](const AZ::Matrix4x4& matrix) { m_projectionMatrixChangedEvent.Signal(matrix); }); - m_onViewMatrixChangedHandler = ViewportContext::MatrixChangedEvent::Handler([this](const AZ::Matrix4x4& matrix) + m_onViewMatrixChangedHandler = MatrixChangedEvent::Handler([this](const AZ::Matrix4x4& matrix) { m_viewMatrixChangedEvent.Signal(matrix); }); @@ -203,6 +203,11 @@ namespace AZ return GetDefaultView()->GetWorldToViewMatrix(); } + AZ::Matrix3x4 ViewportContext::GetCameraViewMatrixAsMatrix3x4() const + { + return GetDefaultView()->GetWorldToViewMatrixAsMatrix3x4(); + } + void ViewportContext::SetCameraViewMatrix(const AZ::Matrix4x4& matrix) { GetDefaultView()->SetWorldToViewMatrix(matrix); diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/ModularViewportCameraController.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/ModularViewportCameraController.h index 45c5394fd8..c54ffc812b 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/ModularViewportCameraController.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/ModularViewportCameraController.h @@ -26,7 +26,7 @@ namespace AtomToolsFramework virtual AZ::Transform GetCameraTransform() const = 0; virtual void SetCameraTransform(const AZ::Transform& transform) = 0; - virtual void ConnectViewMatrixChangedHandler(AZ::RPI::ViewportContext::MatrixChangedEvent::Handler& handler) = 0; + virtual void ConnectViewMatrixChangedHandler(AZ::RPI::MatrixChangedEvent::Handler& handler) = 0; }; //! A function object to represent returning a camera controller priority. @@ -91,7 +91,7 @@ namespace AtomToolsFramework // ModularCameraViewportContext overrides ... AZ::Transform GetCameraTransform() const override; void SetCameraTransform(const AZ::Transform& transform) override; - void ConnectViewMatrixChangedHandler(AZ::RPI::ViewportContext::MatrixChangedEvent::Handler& handler) override; + void ConnectViewMatrixChangedHandler(AZ::RPI::MatrixChangedEvent::Handler& handler) override; private: AzFramework::ViewportId m_viewportId; @@ -152,7 +152,7 @@ namespace AtomToolsFramework float m_roll = 0.0f; //!< The current amount of roll to be applied to the camera. float m_targetRoll = 0.0f; //!< The target amount of roll to be applied to the camera (current will move towards this). //! Listen for camera view changes outside of the camera controller. - AZ::RPI::ViewportContext::MatrixChangedEvent::Handler m_cameraViewMatrixChangeHandler; + AZ::RPI::MatrixChangedEvent::Handler m_cameraViewMatrixChangeHandler; //! The current instance of the modular camera viewport context. AZStd::unique_ptr m_modularCameraViewportContext; //! Flag to prevent circular updates of the camera transform (while the viewport transform is being updated internally). @@ -165,10 +165,10 @@ namespace AtomToolsFramework public: AZ::Transform GetCameraTransform() const override; void SetCameraTransform(const AZ::Transform& transform) override; - void ConnectViewMatrixChangedHandler(AZ::RPI::ViewportContext::MatrixChangedEvent::Handler& handler) override; + void ConnectViewMatrixChangedHandler(AZ::RPI::MatrixChangedEvent::Handler& handler) override; private: AZ::Transform m_cameraTransform = AZ::Transform::CreateIdentity(); - AZ::RPI::ViewportContext::MatrixChangedEvent m_viewMatrixChangedEvent; + AZ::RPI::MatrixChangedEvent m_viewMatrixChangedEvent; }; } // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/ModularViewportCameraController.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/ModularViewportCameraController.cpp index 179ccd9fd8..12e16c3dfa 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/ModularViewportCameraController.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/ModularViewportCameraController.cpp @@ -86,7 +86,7 @@ namespace AtomToolsFramework } } - void ModularCameraViewportContextImpl::ConnectViewMatrixChangedHandler(AZ::RPI::ViewportContext::MatrixChangedEvent::Handler& handler) + void ModularCameraViewportContextImpl::ConnectViewMatrixChangedHandler(AZ::RPI::MatrixChangedEvent::Handler& handler) { if (auto viewportContext = RetrieveViewportContext(m_viewportId)) { @@ -185,7 +185,7 @@ namespace AtomToolsFramework } }; - m_cameraViewMatrixChangeHandler = AZ::RPI::ViewportContext::MatrixChangedEvent::Handler(handleCameraChange); + m_cameraViewMatrixChangeHandler = AZ::RPI::MatrixChangedEvent::Handler(handleCameraChange); m_modularCameraViewportContext->ConnectViewMatrixChangedHandler(m_cameraViewMatrixChangeHandler); ModularViewportCameraControllerRequestBus::Handler::BusConnect(viewportId); @@ -323,11 +323,11 @@ namespace AtomToolsFramework void PlaceholderModularCameraViewportContextImpl::SetCameraTransform(const AZ::Transform& transform) { m_cameraTransform = transform; - m_viewMatrixChangedEvent.Signal(AzFramework::CameraViewFromCameraTransform(Matrix4x4FromTransform(transform))); + m_viewMatrixChangedEvent.Signal( + AZ::Matrix4x4::CreateFromMatrix3x4(AzFramework::CameraViewFromCameraTransform(AZ::Matrix3x4::CreateFromTransform(transform)))); } - void PlaceholderModularCameraViewportContextImpl::ConnectViewMatrixChangedHandler( - AZ::RPI::ViewportContext::MatrixChangedEvent::Handler& handler) + void PlaceholderModularCameraViewportContextImpl::ConnectViewMatrixChangedHandler(AZ::RPI::MatrixChangedEvent::Handler& handler) { handler.Connect(m_viewMatrixChangedEvent); } diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Tests/ViewportInteractionImplTests.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Tests/ViewportInteractionImplTests.cpp index 2dfe4f7c29..19c55d7473 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Tests/ViewportInteractionImplTests.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Tests/ViewportInteractionImplTests.cpp @@ -198,9 +198,7 @@ namespace UnitTest AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::EventResult( cameraState, TestViewportId, &AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Events::GetCameraState); - const auto cameraMatrix = AzFramework::CameraTransform(cameraState); - const auto cameraTransform = AZ::Matrix3x4::CreateFromMatrix3x3AndTranslation( - AZ::Matrix3x3::CreateFromMatrix4x4(cameraMatrix), cameraMatrix.GetTranslation()); + const auto cameraTransform = AzFramework::CameraTransform(cameraState); // Then // camera transform matches that of the secondary view diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp index 86b3011836..67df30fa7b 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp +++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp @@ -1726,15 +1726,13 @@ void AZ::FFont::DrawScreenAlignedText3d( { return; } - AZ::Vector3 positionNDC = AzFramework::WorldToScreenNdc( - params.m_position, - currentView->GetWorldToViewMatrix(), - currentView->GetViewToClipMatrix() - ); - // Text behind the camera shouldn't get rendered. WorldToScreenNDC returns values in the range 0 - 1, so Z < 0.5 is behind the screen + const AZ::Vector3 positionNdc = AzFramework::WorldToScreenNdc( + params.m_position, currentView->GetWorldToViewMatrixAsMatrix3x4(), currentView->GetViewToClipMatrix()); + + // Text behind the camera shouldn't get rendered. WorldToScreenNdc returns values in the range 0 - 1, so Z < 0.5 is behind the screen // and >= 0.5 is in front of the screen. - if (positionNDC.GetZ() < 0.5f) + if (positionNdc.GetZ() < 0.5f) { return; } @@ -1744,9 +1742,9 @@ void AZ::FFont::DrawScreenAlignedText3d( DrawStringUInternal( *internalParams.m_viewport, internalParams.m_viewportContext, - positionNDC.GetX() * internalParams.m_viewport->GetWidth(), - (1.0f - positionNDC.GetY()) * internalParams.m_viewport->GetHeight(), - positionNDC.GetZ(), // Z + positionNdc.GetX() * internalParams.m_viewport->GetWidth(), + (1.0f - positionNdc.GetY()) * internalParams.m_viewport->GetHeight(), + positionNdc.GetZ(), // Z text.data(), params.m_multiline, internalParams.m_ctx diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.cpp b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.cpp index c0ca2fe993..38679432ea 100644 --- a/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.cpp +++ b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.cpp @@ -174,9 +174,9 @@ namespace AZ::Render { // Calculate our screen space position using the viewport size // We want this instead of RenderViewportWidget::WorldToScreen which works in QWidget virtual coordinate space - AzFramework::ScreenPoint position = AzFramework::WorldToScreen( - drawParameters.m_position, viewportContext->GetCameraViewMatrix(), viewportContext->GetCameraProjectionMatrix(), - viewportSize); + const AzFramework::ScreenPoint position = AzFramework::WorldToScreen( + drawParameters.m_position, viewportContext->GetCameraViewMatrixAsMatrix3x4(), + viewportContext->GetCameraProjectionMatrix(), viewportSize); screenPosition.SetX(aznumeric_cast(position.m_x)); screenPosition.SetY(aznumeric_cast(position.m_y)); } diff --git a/Gems/Camera/Code/Source/CameraEditorSystemComponent.cpp b/Gems/Camera/Code/Source/CameraEditorSystemComponent.cpp index fe49d1737a..d2f7469c58 100644 --- a/Gems/Camera/Code/Source/CameraEditorSystemComponent.cpp +++ b/Gems/Camera/Code/Source/CameraEditorSystemComponent.cpp @@ -113,7 +113,7 @@ namespace Camera // Set transform to that of the viewport, otherwise default to Identity matrix and 60 degree FOV const auto worldFromView = AzFramework::CameraTransform(cameraState); const auto cameraTransform = AZ::Transform::CreateFromMatrix3x3AndTranslation( - AZ::Matrix3x3::CreateFromMatrix4x4(worldFromView), worldFromView.GetTranslation()); + AZ::Matrix3x3::CreateFromMatrix3x4(worldFromView), worldFromView.GetTranslation()); AZ::TransformBus::Event(newEntityId, &AZ::TransformInterface::SetWorldTM, cameraTransform); CameraRequestBus::Event(newEntityId, &CameraComponentRequests::SetFov, AZ::RadToDeg(cameraState.m_fovOrZoom)); undoBatch.MarkEntityDirty(newEntityId);