Improve camera orbit behavior (#1060)
This commit is contained in:
committed by
GitHub
parent
f2a7cd9a2d
commit
cf08f4dab1
@@ -1233,7 +1233,7 @@ void EditorViewportWidget::SetViewportId(int id)
|
||||
|
||||
auto controller = AZStd::make_shared<AtomToolsFramework::ModularViewportCameraController>();
|
||||
controller->SetCameraListBuilderCallback(
|
||||
[](AzFramework::Cameras& cameras)
|
||||
[id](AzFramework::Cameras& cameras)
|
||||
{
|
||||
auto firstPersonRotateCamera = AZStd::make_shared<AzFramework::RotateCameraInput>(AzFramework::CameraFreeLookButton);
|
||||
auto firstPersonPanCamera =
|
||||
@@ -1243,17 +1243,17 @@ void EditorViewportWidget::SetViewportId(int id)
|
||||
|
||||
auto orbitCamera = AZStd::make_shared<AzFramework::OrbitCameraInput>();
|
||||
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;
|
||||
AzToolsFramework::EditorTransformComponentSelectionRequestBus::EventResult(
|
||||
manipulatorTransform, AzToolsFramework::GetEntityContextId(),
|
||||
&AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::GetManipulatorTransform);
|
||||
AZStd::optional<AZ::Vector3> lookAtAfterInterpolation;
|
||||
AtomToolsFramework::ModularViewportCameraControllerRequestBus::EventResult(
|
||||
lookAtAfterInterpolation, id,
|
||||
&AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::LookAtAfterInterpolation);
|
||||
|
||||
// initially attempt to use manipulator transform if one exists (there is a selection)
|
||||
if (manipulatorTransform)
|
||||
// initially attempt to use the last set look at point after an interpolation has finished
|
||||
if (lookAtAfterInterpolation.has_value())
|
||||
{
|
||||
return manipulatorTransform->GetTranslation();
|
||||
return *lookAtAfterInterpolation;
|
||||
}
|
||||
|
||||
const float RayDistance = 1000.0f;
|
||||
|
||||
@@ -1732,13 +1732,14 @@ void SandboxIntegrationManager::GoToEntitiesInViewports(const AzToolsFramework::
|
||||
// compute new camera transform
|
||||
const float fov = AzFramework::RetrieveFov(viewportContext->GetCameraProjectionMatrix());
|
||||
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 =
|
||||
AZ::Transform::CreateLookAt(aabb.GetCenter() - (forward * distanceToTarget), aabb.GetCenter());
|
||||
AZ::Transform::CreateLookAt(aabb.GetCenter() - (forward * distanceToLookAt), aabb.GetCenter());
|
||||
|
||||
AtomToolsFramework::ModularViewportCameraControllerRequestBus::Event(
|
||||
viewportContext->GetId(),
|
||||
&AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::InterpolateToTransform, nextCameraTransform);
|
||||
&AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::InterpolateToTransform, nextCameraTransform,
|
||||
distanceToLookAt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -51,7 +51,8 @@ namespace AtomToolsFramework
|
||||
void UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event) override;
|
||||
|
||||
// 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:
|
||||
// AzFramework::ViewportDebugDisplayEventBus overrides ...
|
||||
@@ -71,6 +72,8 @@ namespace AtomToolsFramework
|
||||
AZ::Transform m_transformEnd = AZ::Transform::CreateIdentity();
|
||||
float m_animationT = 0.0f;
|
||||
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;
|
||||
|
||||
AZ::RPI::ViewportContext::MatrixChangedEvent::Handler m_cameraViewMatrixChangeHandler;
|
||||
|
||||
+6
-1
@@ -32,7 +32,12 @@ namespace AtomToolsFramework
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
|
||||
//! 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:
|
||||
~ModularViewportCameraControllerRequests() = default;
|
||||
|
||||
+20
-2
@@ -140,6 +140,18 @@ namespace AtomToolsFramework
|
||||
m_targetCamera = m_cameraSystem.StepCamera(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());
|
||||
}
|
||||
else if (m_cameraMode == CameraMode::Animation)
|
||||
@@ -148,8 +160,8 @@ namespace AtomToolsFramework
|
||||
{
|
||||
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(
|
||||
m_transformStart.GetRotation().Slerp(m_transformEnd.GetRotation(), 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_cameraMode = CameraMode::Animation;
|
||||
m_transformStart = m_camera.Transform();
|
||||
m_transformEnd = worldFromLocal;
|
||||
m_lookAtAfterInterpolation = m_transformEnd.GetTranslation() + m_transformEnd.GetBasisY() * lookAtDistance;
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::Vector3> ModernViewportCameraControllerInstance::LookAtAfterInterpolation() const
|
||||
{
|
||||
return m_lookAtAfterInterpolation;
|
||||
}
|
||||
} // namespace AtomToolsFramework
|
||||
|
||||
Reference in New Issue
Block a user