Fix for camera roll behavior when in 'Be this camera' mode (#5658)
* fix for camera roll behavior when in 'Be this camera' mode Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * updates for camera tests Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * fix for failing unit test - require default function Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
155fe77f5d
commit
a6164ca2cd
+11
-11
@@ -113,14 +113,14 @@ namespace AtomToolsFramework
|
||||
|
||||
// ModularViewportCameraControllerRequestBus overrides ...
|
||||
void InterpolateToTransform(const AZ::Transform& worldFromLocal) override;
|
||||
AZ::Transform GetReferenceFrame() const override;
|
||||
void SetReferenceFrame(const AZ::Transform& worldFromLocal) override;
|
||||
void ClearReferenceFrame() override;
|
||||
void StartTrackingTransform(const AZ::Transform& worldFromLocal) override;
|
||||
void StopTrackingTransform() override;
|
||||
bool IsTrackingTransform() const override;
|
||||
|
||||
private:
|
||||
//! Update the reference frame after a change has been made to the camera
|
||||
//! view without updating the internal camera via user input.
|
||||
void RefreshReferenceFrame();
|
||||
//! Combine the current camera transform with any potential roll from the tracked
|
||||
//! transform (this is usually zero).
|
||||
AZ::Transform CombinedCameraTransform() const;
|
||||
|
||||
//! The current mode the camera controller is in.
|
||||
enum class CameraMode
|
||||
@@ -141,21 +141,21 @@ namespace AtomToolsFramework
|
||||
AzFramework::Camera m_camera; //!< The current camera state (pitch/yaw/position/look-distance).
|
||||
AzFramework::Camera m_targetCamera; //!< The target (next) camera state that m_camera is catching up to.
|
||||
AzFramework::Camera m_previousCamera; //!< The state of the camera from the previous frame.
|
||||
AZStd::optional<AzFramework::Camera> m_storedCamera; //!< A potentially stored camera for when a custom reference frame is set.
|
||||
AZStd::optional<AzFramework::Camera> m_storedCamera; //!< A potentially stored camera for when a transform is being tracked.
|
||||
AzFramework::CameraSystem m_cameraSystem; //!< The camera system responsible for managing all CameraInputs.
|
||||
AzFramework::CameraProps m_cameraProps; //!< Camera properties to control rotate and translate smoothness.
|
||||
CameraControllerPriorityFn m_priorityFn; //!< Controls at what priority the camera controller should respond to events.
|
||||
|
||||
CameraAnimation m_cameraAnimation; //!< Camera animation state (used during CameraMode::Animation).
|
||||
CameraMode m_cameraMode = CameraMode::Control; //!< The current mode the camera is operating in.
|
||||
//! An additional reference frame the camera can operate in (identity has no effect).
|
||||
AZ::Transform m_referenceFrameOverride = AZ::Transform::CreateIdentity();
|
||||
//! Flag to prevent circular updates of the camera transform (while the viewport transform is being updated internally).
|
||||
bool m_updatingTransformInternally = false;
|
||||
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;
|
||||
//! The current instance of the modular camera viewport context.
|
||||
AZStd::unique_ptr<ModularCameraViewportContext> m_modularCameraViewportContext;
|
||||
//! Flag to prevent circular updates of the camera transform (while the viewport transform is being updated internally).
|
||||
bool m_updatingTransformInternally = false;
|
||||
};
|
||||
|
||||
//! Placeholder implementation for ModularCameraViewportContext (useful for verifying the interface).
|
||||
|
||||
+8
-7
@@ -31,15 +31,16 @@ namespace AtomToolsFramework
|
||||
//! @param worldFromLocal The transform of where the camera should end up.
|
||||
virtual void InterpolateToTransform(const AZ::Transform& worldFromLocal) = 0;
|
||||
|
||||
//! Return the current reference frame.
|
||||
//! @note If a reference frame has not been set or a frame has been cleared, this is just the identity.
|
||||
virtual AZ::Transform GetReferenceFrame() const = 0;
|
||||
//! Start tracking a transform.
|
||||
//! Store the current camera transform and move to the next camera transform.
|
||||
virtual void StartTrackingTransform(const AZ::Transform& worldFromLocal) = 0;
|
||||
|
||||
//! Set a new reference frame other than the identity for the camera controller.
|
||||
virtual void SetReferenceFrame(const AZ::Transform& worldFromLocal) = 0;
|
||||
//! Stop tracking the set transform.
|
||||
//! The previously stored camera transform is restored.
|
||||
virtual void StopTrackingTransform() = 0;
|
||||
|
||||
//! Clear the current reference frame to restore the identity.
|
||||
virtual void ClearReferenceFrame() = 0;
|
||||
//! Return if the tracking transform is set.
|
||||
virtual bool IsTrackingTransform() const = 0;
|
||||
|
||||
protected:
|
||||
~ModularViewportCameraControllerRequests() = default;
|
||||
|
||||
+26
-29
@@ -12,6 +12,7 @@
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/Math/Color.h>
|
||||
#include <AzCore/std/math.h>
|
||||
#include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
|
||||
#include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h>
|
||||
#include <AzFramework/Viewport/ScreenGeometry.h>
|
||||
@@ -175,16 +176,12 @@ namespace AtomToolsFramework
|
||||
// ignore these updates if the camera is being updated internally
|
||||
if (!m_updatingTransformInternally)
|
||||
{
|
||||
if (m_storedCamera.has_value())
|
||||
{
|
||||
// if an external change occurs ensure we update the stored reference frame if one is set
|
||||
RefreshReferenceFrame();
|
||||
return;
|
||||
}
|
||||
|
||||
m_previousCamera = m_targetCamera;
|
||||
UpdateCameraFromTransform(m_targetCamera, m_modularCameraViewportContext->GetCameraTransform());
|
||||
m_camera = m_targetCamera;
|
||||
|
||||
const AZ::Transform transform = m_modularCameraViewportContext->GetCameraTransform();
|
||||
const AZ::Vector3 eulerAngles = AzFramework::EulerAngles(AZ::Matrix3x3::CreateFromTransform(transform));
|
||||
UpdateCameraFromTranslationAndRotation(m_targetCamera, transform.GetTranslation(), eulerAngles);
|
||||
m_targetRoll = eulerAngles.GetY();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -227,7 +224,9 @@ namespace AtomToolsFramework
|
||||
{
|
||||
m_targetCamera = m_cameraSystem.StepCamera(m_targetCamera, event.m_deltaTime.count());
|
||||
m_camera = AzFramework::SmoothCamera(m_camera, m_targetCamera, m_cameraProps, event.m_deltaTime.count());
|
||||
m_modularCameraViewportContext->SetCameraTransform(m_referenceFrameOverride * m_camera.Transform());
|
||||
m_roll = AzFramework::SmoothValue(m_targetRoll, m_roll, m_cameraProps.m_rotateSmoothnessFn(), event.m_deltaTime.count());
|
||||
|
||||
m_modularCameraViewportContext->SetCameraTransform(CombinedCameraTransform());
|
||||
}
|
||||
else if (m_cameraMode == CameraMode::Animation)
|
||||
{
|
||||
@@ -250,6 +249,7 @@ namespace AtomToolsFramework
|
||||
m_camera.m_yaw = eulerAngles.GetZ();
|
||||
m_camera.m_pivot = current.GetTranslation();
|
||||
m_camera.m_offset = AZ::Vector3::CreateZero();
|
||||
m_targetRoll = eulerAngles.GetY();
|
||||
m_targetCamera = m_camera;
|
||||
|
||||
m_modularCameraViewportContext->SetCameraTransform(current);
|
||||
@@ -257,7 +257,6 @@ namespace AtomToolsFramework
|
||||
if (animationTime >= 1.0f)
|
||||
{
|
||||
m_cameraMode = CameraMode::Control;
|
||||
RefreshReferenceFrame();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,45 +266,38 @@ namespace AtomToolsFramework
|
||||
void ModularViewportCameraControllerInstance::InterpolateToTransform(const AZ::Transform& worldFromLocal)
|
||||
{
|
||||
m_cameraMode = CameraMode::Animation;
|
||||
m_cameraAnimation = CameraAnimation{ m_referenceFrameOverride * m_camera.Transform(), worldFromLocal, 0.0f };
|
||||
m_cameraAnimation = CameraAnimation{ CombinedCameraTransform(), worldFromLocal, 0.0f };
|
||||
}
|
||||
|
||||
AZ::Transform ModularViewportCameraControllerInstance::GetReferenceFrame() const
|
||||
{
|
||||
return m_referenceFrameOverride;
|
||||
}
|
||||
|
||||
void ModularViewportCameraControllerInstance::SetReferenceFrame(const AZ::Transform& worldFromLocal)
|
||||
void ModularViewportCameraControllerInstance::StartTrackingTransform(const AZ::Transform& worldFromLocal)
|
||||
{
|
||||
if (!m_storedCamera.has_value())
|
||||
{
|
||||
m_storedCamera = m_previousCamera;
|
||||
}
|
||||
|
||||
m_referenceFrameOverride = worldFromLocal;
|
||||
m_targetCamera.m_pitch = 0.0f;
|
||||
m_targetCamera.m_yaw = 0.0f;
|
||||
const auto angles = AzFramework::EulerAngles(AZ::Matrix3x3::CreateFromQuaternion(worldFromLocal.GetRotation()));
|
||||
m_targetCamera.m_pitch = angles.GetX();
|
||||
m_targetCamera.m_yaw = angles.GetZ();
|
||||
m_targetCamera.m_offset = AZ::Vector3::CreateZero();
|
||||
m_targetCamera.m_pivot = AZ::Vector3::CreateZero();
|
||||
m_camera = m_targetCamera;
|
||||
m_targetCamera.m_pivot = worldFromLocal.GetTranslation();
|
||||
m_targetRoll = angles.GetY();
|
||||
}
|
||||
|
||||
void ModularViewportCameraControllerInstance::ClearReferenceFrame()
|
||||
void ModularViewportCameraControllerInstance::StopTrackingTransform()
|
||||
{
|
||||
m_referenceFrameOverride = AZ::Transform::CreateIdentity();
|
||||
|
||||
if (m_storedCamera.has_value())
|
||||
{
|
||||
m_targetCamera = m_storedCamera.value();
|
||||
m_camera = m_targetCamera;
|
||||
m_targetRoll = 0.0f;
|
||||
}
|
||||
|
||||
m_storedCamera.reset();
|
||||
}
|
||||
|
||||
void ModularViewportCameraControllerInstance::RefreshReferenceFrame()
|
||||
bool ModularViewportCameraControllerInstance::IsTrackingTransform() const
|
||||
{
|
||||
m_referenceFrameOverride = m_modularCameraViewportContext->GetCameraTransform() * m_camera.Transform().GetInverse();
|
||||
return m_storedCamera.has_value();
|
||||
}
|
||||
|
||||
AZ::Transform PlaceholderModularCameraViewportContextImpl::GetCameraTransform() const
|
||||
@@ -324,4 +316,9 @@ namespace AtomToolsFramework
|
||||
{
|
||||
handler.Connect(m_viewMatrixChangedEvent);
|
||||
}
|
||||
|
||||
AZ::Transform ModularViewportCameraControllerInstance::CombinedCameraTransform() const
|
||||
{
|
||||
return m_camera.Transform() * AZ::Transform::CreateFromMatrix3x3(AZ::Matrix3x3::CreateRotationY(m_targetRoll));
|
||||
}
|
||||
} // namespace AtomToolsFramework
|
||||
|
||||
Reference in New Issue
Block a user