documentation pass for modular viewport camera controller

Signed-off-by: hultonha <hultonha@amazon.co.uk>
monroegm-disable-blank-issue-2
hultonha 5 years ago
parent fa52124f9c
commit 86758fda35

@ -16,18 +16,21 @@
namespace AtomToolsFramework
{
class ModernViewportCameraControllerInstance;
class ModularViewportCameraControllerInstance;
//! Builder class to create and configure a ModularViewportCameraControllerInstance.
class ModularViewportCameraController
: public AzFramework::MultiViewportController<
ModernViewportCameraControllerInstance, AzFramework::ViewportControllerPriority::DispatchToAllPriorities>
ModularViewportCameraControllerInstance,
AzFramework::ViewportControllerPriority::DispatchToAllPriorities>
{
public:
using CameraListBuilder = AZStd::function<void(AzFramework::Cameras&)>;
using CameraPropsBuilder = AZStd::function<void(AzFramework::CameraProps&)>;
//! Sets the camera list builder callback used to populate new ModernViewportCameraControllerInstances
//! Sets the camera list builder callback used to populate new ModularViewportCameraControllerInstances
void SetCameraListBuilderCallback(const CameraListBuilder& builder);
//! Sets the camera props builder callback used to populate new ModernViewportCameraControllerInstances
//! Sets the camera props builder callback used to populate new ModularViewportCameraControllerInstances
void SetCameraPropsBuilderCallback(const CameraPropsBuilder& builder);
//! Sets up a camera list based on this controller's CameraListBuilderCallback
void SetupCameras(AzFramework::Cameras& cameras);
@ -35,18 +38,22 @@ namespace AtomToolsFramework
void SetupCameraProperies(AzFramework::CameraProps& cameraProps);
private:
CameraListBuilder m_cameraListBuilder;
CameraPropsBuilder m_cameraPropsBuilder;
CameraListBuilder
m_cameraListBuilder; //!< Builder to generate a list of CameraInputs to run in the ModularViewportCameraControllerInstance.
CameraPropsBuilder m_cameraPropsBuilder; //!< Builder to define custom camera properties to use for things such as rotate and
//!< translate interpolation.
};
class ModernViewportCameraControllerInstance final
: public AzFramework::MultiViewportControllerInstanceInterface<ModularViewportCameraController>,
public ModularViewportCameraControllerRequestBus::Handler,
private AzFramework::ViewportDebugDisplayEventBus::Handler
//! A customizable camera controller than can be configured to a run varying set of CameraInput instances.
//! The controller can also be animated from its current transform to a new translation and orientation.
class ModularViewportCameraControllerInstance final
: public AzFramework::MultiViewportControllerInstanceInterface<ModularViewportCameraController>
, public ModularViewportCameraControllerRequestBus::Handler
, private AzFramework::ViewportDebugDisplayEventBus::Handler
{
public:
explicit ModernViewportCameraControllerInstance(AzFramework::ViewportId viewportId, ModularViewportCameraController* controller);
~ModernViewportCameraControllerInstance() override;
explicit ModularViewportCameraControllerInstance(AzFramework::ViewportId viewportId, ModularViewportCameraController* controller);
~ModularViewportCameraControllerInstance() override;
// MultiViewportControllerInstanceInterface overrides ...
bool HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) override;
@ -60,25 +67,34 @@ namespace AtomToolsFramework
// AzFramework::ViewportDebugDisplayEventBus overrides ...
void DisplayViewport(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override;
//! The current mode the camera controller is in.
enum class CameraMode
{
Control,
Animation
Control, //!< The camera is being driven by user input.
Animation //!< The camera is being animated (interpolated) from one transform to another.
};
AzFramework::Camera m_camera;
AzFramework::Camera m_targetCamera;
AzFramework::CameraSystem m_cameraSystem;
AzFramework::CameraProps m_cameraProps;
//! Encapsulates an animation (interpolation) between two transforms.
struct CameraAnimation
{
AZ::Transform m_transformStart =
AZ::Transform::CreateIdentity(); //!< The transform of the camera at the start of the animation.
AZ::Transform m_transformEnd = AZ::Transform::CreateIdentity(); //!< The transform of the camera at the end of the animation.
float m_animationT = 0.0f; //!< The interpolation amount between the start and end transforms (in the range 0.0-1.0).
};
AZ::Transform m_transformStart = AZ::Transform::CreateIdentity();
AZ::Transform m_transformEnd = AZ::Transform::CreateIdentity();
float m_animationT = 0.0f;
CameraMode m_cameraMode = CameraMode::Control;
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::CameraSystem m_cameraSystem; //!< The camera system responsible for managing all CameraInputs.
AzFramework::CameraProps m_cameraProps; //!< Camera properties to control rotate and translate smoothness.
CameraAnimation m_cameraAnimation; //!< Camera animation state (used during CameraMode::Animation).
CameraMode m_cameraMode = CameraMode::Control; //!< The current mode the camera is operating in.
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;
bool m_updatingTransformInternally =
false; //!< Flag to prevent circular updates of the camera transform (while the viewport transform is being updated internally).
AZ::RPI::ViewportContext::MatrixChangedEvent::Handler
m_cameraViewMatrixChangeHandler; //!< Listen for camera view changes outside of the camera controller.
};
} // namespace AtomToolsFramework

@ -84,7 +84,7 @@ namespace AtomToolsFramework
}
}
ModernViewportCameraControllerInstance::ModernViewportCameraControllerInstance(
ModularViewportCameraControllerInstance::ModularViewportCameraControllerInstance(
const AzFramework::ViewportId viewportId, ModularViewportCameraController* controller)
: MultiViewportControllerInstanceInterface<ModularViewportCameraController>(viewportId, controller)
{
@ -95,7 +95,8 @@ namespace AtomToolsFramework
{
auto handleCameraChange = [this, viewportContext](const AZ::Matrix4x4&)
{
if (!m_updatingTransform)
// ignore these updates if the camera is being updated internally
if (!m_updatingTransformInternally)
{
UpdateCameraFromTransform(m_targetCamera, viewportContext->GetCameraTransform());
m_camera = m_targetCamera;
@ -111,7 +112,7 @@ namespace AtomToolsFramework
ModularViewportCameraControllerRequestBus::Handler::BusConnect(viewportId);
}
ModernViewportCameraControllerInstance::~ModernViewportCameraControllerInstance()
ModularViewportCameraControllerInstance::~ModularViewportCameraControllerInstance()
{
ModularViewportCameraControllerRequestBus::Handler::BusDisconnect();
AzFramework::ViewportDebugDisplayEventBus::Handler::BusDisconnect();
@ -132,7 +133,7 @@ namespace AtomToolsFramework
return AzFramework::ViewportControllerPriority::Normal;
}
bool ModernViewportCameraControllerInstance::HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event)
bool ModularViewportCameraControllerInstance::HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event)
{
if (event.m_priority == GetPriority(m_cameraSystem))
{
@ -142,7 +143,7 @@ namespace AtomToolsFramework
return false;
}
void ModernViewportCameraControllerInstance::UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event)
void ModularViewportCameraControllerInstance::UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event)
{
// only update for a single priority (normal is the default)
if (event.m_priority != AzFramework::ViewportControllerPriority::Normal)
@ -152,7 +153,7 @@ namespace AtomToolsFramework
if (auto viewportContext = RetrieveViewportContext(GetViewportId()))
{
m_updatingTransform = true;
m_updatingTransformInternally = true;
if (m_cameraMode == CameraMode::Control)
{
@ -180,10 +181,12 @@ namespace AtomToolsFramework
return t * t * t * (t * (t * 6.0f - 15.0f) + 10.0f);
};
const float transitionT = smootherStepFn(m_animationT);
const auto& [transformStart, transformEnd, animationT] = m_cameraAnimation;
const float transitionT = smootherStepFn(animationT);
const AZ::Transform current = AZ::Transform::CreateFromQuaternionAndTranslation(
m_transformStart.GetRotation().Slerp(m_transformEnd.GetRotation(), transitionT),
m_transformStart.GetTranslation().Lerp(m_transformEnd.GetTranslation(), transitionT));
transformStart.GetRotation().Slerp(transformEnd.GetRotation(), transitionT),
transformStart.GetTranslation().Lerp(transformEnd.GetTranslation(), transitionT));
const AZ::Vector3 eulerAngles = AzFramework::EulerAngles(AZ::Matrix3x3::CreateFromTransform(current));
m_camera.m_pitch = eulerAngles.GetX();
@ -191,21 +194,21 @@ namespace AtomToolsFramework
m_camera.m_lookAt = current.GetTranslation();
m_targetCamera = m_camera;
if (m_animationT >= 1.0f)
if (animationT >= 1.0f)
{
m_cameraMode = CameraMode::Control;
}
m_animationT = AZ::GetClamp(m_animationT + event.m_deltaTime.count(), 0.0f, 1.0f);
m_cameraAnimation.m_animationT = AZ::GetClamp(animationT + event.m_deltaTime.count(), 0.0f, 1.0f);
viewportContext->SetCameraTransform(current);
}
m_updatingTransform = false;
m_updatingTransformInternally = false;
}
}
void ModernViewportCameraControllerInstance::DisplayViewport(
void ModularViewportCameraControllerInstance::DisplayViewport(
[[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay)
{
if (const float alpha = AZStd::min(-m_camera.m_lookDist / 5.0f, 1.0f); alpha > AZ::Constants::FloatEpsilon)
@ -216,16 +219,14 @@ namespace AtomToolsFramework
}
}
void ModernViewportCameraControllerInstance::InterpolateToTransform(const AZ::Transform& worldFromLocal, const float lookAtDistance)
void ModularViewportCameraControllerInstance::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;
m_cameraAnimation = CameraAnimation{ m_camera.Transform(), worldFromLocal, 0.0f };
m_lookAtAfterInterpolation = worldFromLocal.GetTranslation() + worldFromLocal.GetBasisY() * lookAtDistance;
}
AZStd::optional<AZ::Vector3> ModernViewportCameraControllerInstance::LookAtAfterInterpolation() const
AZStd::optional<AZ::Vector3> ModularViewportCameraControllerInstance::LookAtAfterInterpolation() const
{
return m_lookAtAfterInterpolation;
}

Loading…
Cancel
Save