Improve camera orbit behavior (#1060)

main
Tom Hulton-Harrop 5 years ago committed by GitHub
parent f2a7cd9a2d
commit cf08f4dab1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1233,7 +1233,7 @@ void EditorViewportWidget::SetViewportId(int id)
auto controller = AZStd::make_shared<AtomToolsFramework::ModularViewportCameraController>(); auto controller = AZStd::make_shared<AtomToolsFramework::ModularViewportCameraController>();
controller->SetCameraListBuilderCallback( controller->SetCameraListBuilderCallback(
[](AzFramework::Cameras& cameras) [id](AzFramework::Cameras& cameras)
{ {
auto firstPersonRotateCamera = AZStd::make_shared<AzFramework::RotateCameraInput>(AzFramework::CameraFreeLookButton); auto firstPersonRotateCamera = AZStd::make_shared<AzFramework::RotateCameraInput>(AzFramework::CameraFreeLookButton);
auto firstPersonPanCamera = auto firstPersonPanCamera =
@ -1243,17 +1243,17 @@ void EditorViewportWidget::SetViewportId(int id)
auto orbitCamera = AZStd::make_shared<AzFramework::OrbitCameraInput>(); auto orbitCamera = AZStd::make_shared<AzFramework::OrbitCameraInput>();
orbitCamera->SetLookAtFn( orbitCamera->SetLookAtFn(
[](const AZ::Vector3& position, const AZ::Vector3& direction) -> AZStd::optional<AZ::Vector3> [id](const AZ::Vector3& position, const AZ::Vector3& direction) -> AZStd::optional<AZ::Vector3>
{ {
AZStd::optional<AZ::Transform> manipulatorTransform; AZStd::optional<AZ::Vector3> lookAtAfterInterpolation;
AzToolsFramework::EditorTransformComponentSelectionRequestBus::EventResult( AtomToolsFramework::ModularViewportCameraControllerRequestBus::EventResult(
manipulatorTransform, AzToolsFramework::GetEntityContextId(), lookAtAfterInterpolation, id,
&AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::GetManipulatorTransform); &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::LookAtAfterInterpolation);
// initially attempt to use manipulator transform if one exists (there is a selection) // initially attempt to use the last set look at point after an interpolation has finished
if (manipulatorTransform) if (lookAtAfterInterpolation.has_value())
{ {
return manipulatorTransform->GetTranslation(); return *lookAtAfterInterpolation;
} }
const float RayDistance = 1000.0f; const float RayDistance = 1000.0f;

@ -1732,13 +1732,14 @@ void SandboxIntegrationManager::GoToEntitiesInViewports(const AzToolsFramework::
// compute new camera transform // compute new camera transform
const float fov = AzFramework::RetrieveFov(viewportContext->GetCameraProjectionMatrix()); const float fov = AzFramework::RetrieveFov(viewportContext->GetCameraProjectionMatrix());
const float fovScale = (1.0f / AZStd::tan(fov * 0.5f)); const float fovScale = (1.0f / AZStd::tan(fov * 0.5f));
const float distanceToTarget = selectionSize * fovScale * centerScale; const float distanceToLookAt = selectionSize * fovScale * centerScale;
const AZ::Transform nextCameraTransform = const AZ::Transform nextCameraTransform =
AZ::Transform::CreateLookAt(aabb.GetCenter() - (forward * distanceToTarget), aabb.GetCenter()); AZ::Transform::CreateLookAt(aabb.GetCenter() - (forward * distanceToLookAt), aabb.GetCenter());
AtomToolsFramework::ModularViewportCameraControllerRequestBus::Event( AtomToolsFramework::ModularViewportCameraControllerRequestBus::Event(
viewportContext->GetId(), viewportContext->GetId(),
&AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::InterpolateToTransform, nextCameraTransform); &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::InterpolateToTransform, nextCameraTransform,
distanceToLookAt);
} }
} }
} }

@ -51,7 +51,8 @@ namespace AtomToolsFramework
void UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event) override; void UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event) override;
// ModularViewportCameraControllerRequestBus overrides ... // ModularViewportCameraControllerRequestBus overrides ...
void InterpolateToTransform(const AZ::Transform& worldFromLocal) override; void InterpolateToTransform(const AZ::Transform& worldFromLocal, float lookAtDistance) override;
AZStd::optional<AZ::Vector3> LookAtAfterInterpolation() const override;
private: private:
// AzFramework::ViewportDebugDisplayEventBus overrides ... // AzFramework::ViewportDebugDisplayEventBus overrides ...
@ -71,6 +72,8 @@ namespace AtomToolsFramework
AZ::Transform m_transformEnd = AZ::Transform::CreateIdentity(); AZ::Transform m_transformEnd = AZ::Transform::CreateIdentity();
float m_animationT = 0.0f; float m_animationT = 0.0f;
CameraMode m_cameraMode = CameraMode::Control; CameraMode m_cameraMode = CameraMode::Control;
AZStd::optional<AZ::Vector3> m_lookAtAfterInterpolation; //!< The look at point after an interpolation has finished.
//!< Will be cleared when the view changes (camera looks away).
bool m_updatingTransform = false; bool m_updatingTransform = false;
AZ::RPI::ViewportContext::MatrixChangedEvent::Handler m_cameraViewMatrixChangeHandler; AZ::RPI::ViewportContext::MatrixChangedEvent::Handler m_cameraViewMatrixChangeHandler;

@ -32,7 +32,12 @@ namespace AtomToolsFramework
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
//! Begin a smooth transition of the camera to the requested transform. //! Begin a smooth transition of the camera to the requested transform.
virtual void InterpolateToTransform(const AZ::Transform& worldFromLocal) = 0; //! @param worldFromLocal The transform of where the camera should end up.
//! @param lookAtDistance The distance between the camera transform and the imagined look at point.
virtual void InterpolateToTransform(const AZ::Transform& worldFromLocal, float lookAtDistance) = 0;
//! Look at point after an interpolation has finished and no translation has occurred.
virtual AZStd::optional<AZ::Vector3> LookAtAfterInterpolation() const = 0;
protected: protected:
~ModularViewportCameraControllerRequests() = default; ~ModularViewportCameraControllerRequests() = default;

@ -140,6 +140,18 @@ namespace AtomToolsFramework
m_targetCamera = m_cameraSystem.StepCamera(m_targetCamera, event.m_deltaTime.count()); m_targetCamera = m_cameraSystem.StepCamera(m_targetCamera, event.m_deltaTime.count());
m_camera = AzFramework::SmoothCamera(m_camera, m_targetCamera, event.m_deltaTime.count()); m_camera = AzFramework::SmoothCamera(m_camera, m_targetCamera, event.m_deltaTime.count());
// if there has been an interpolation, only clear the look at point if it is no longer
// centered in the view (the camera has looked away from it)
if (m_lookAtAfterInterpolation.has_value())
{
if (const float lookDirection =
(*m_lookAtAfterInterpolation - m_camera.Translation()).GetNormalized().Dot(m_camera.Transform().GetBasisY());
!AZ::IsCloseMag(lookDirection, 1.0f, 0.001f))
{
m_lookAtAfterInterpolation = {};
}
}
viewportContext->SetCameraTransform(m_camera.Transform()); viewportContext->SetCameraTransform(m_camera.Transform());
} }
else if (m_cameraMode == CameraMode::Animation) else if (m_cameraMode == CameraMode::Animation)
@ -148,8 +160,8 @@ namespace AtomToolsFramework
{ {
return t * t * t * (t * (t * 6.0f - 15.0f) + 10.0f); return t * t * t * (t * (t * 6.0f - 15.0f) + 10.0f);
}; };
const float transitionT = smootherStepFn(m_animationT);
const float transitionT = smootherStepFn(m_animationT);
const AZ::Transform current = AZ::Transform::CreateFromQuaternionAndTranslation( const AZ::Transform current = AZ::Transform::CreateFromQuaternionAndTranslation(
m_transformStart.GetRotation().Slerp(m_transformEnd.GetRotation(), transitionT), m_transformStart.GetRotation().Slerp(m_transformEnd.GetRotation(), transitionT),
m_transformStart.GetTranslation().Lerp(m_transformEnd.GetTranslation(), transitionT)); m_transformStart.GetTranslation().Lerp(m_transformEnd.GetTranslation(), transitionT));
@ -185,11 +197,17 @@ namespace AtomToolsFramework
} }
} }
void ModernViewportCameraControllerInstance::InterpolateToTransform(const AZ::Transform& worldFromLocal) void ModernViewportCameraControllerInstance::InterpolateToTransform(const AZ::Transform& worldFromLocal, const float lookAtDistance)
{ {
m_animationT = 0.0f; m_animationT = 0.0f;
m_cameraMode = CameraMode::Animation; m_cameraMode = CameraMode::Animation;
m_transformStart = m_camera.Transform(); m_transformStart = m_camera.Transform();
m_transformEnd = worldFromLocal; m_transformEnd = worldFromLocal;
m_lookAtAfterInterpolation = m_transformEnd.GetTranslation() + m_transformEnd.GetBasisY() * lookAtDistance;
}
AZStd::optional<AZ::Vector3> ModernViewportCameraControllerInstance::LookAtAfterInterpolation() const
{
return m_lookAtAfterInterpolation;
} }
} // namespace AtomToolsFramework } // namespace AtomToolsFramework

Loading…
Cancel
Save