From 15afcc341d26e9e302cda9af966841a5940afd0f Mon Sep 17 00:00:00 2001 From: hultonha Date: Mon, 26 Apr 2021 19:46:57 +0100 Subject: [PATCH 1/8] fixes and updates to CameraInput --- .../AzFramework/Viewport/CameraInput.cpp | 44 +++++++++---------- .../AzFramework/Viewport/CameraInput.h | 6 +-- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp index ee49a95b23..1d0b440a9b 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp +++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp @@ -51,21 +51,21 @@ namespace AzFramework return nextCamera; } - void Cameras::AddCamera(AZStd::shared_ptr camera_input) + void Cameras::AddCamera(AZStd::shared_ptr cameraInput) { - m_idleCameraInputs.push_back(AZStd::move(camera_input)); + m_idleCameraInputs.push_back(AZStd::move(cameraInput)); } void Cameras::HandleEvents(const InputEvent& event) { - for (auto& camera_input : m_activeCameraInputs) + for (auto& cameraInput : m_activeCameraInputs) { - camera_input->HandleEvents(event); + cameraInput->HandleEvents(event); } - for (auto& camera_input : m_idleCameraInputs) + for (auto& cameraInput : m_idleCameraInputs) { - camera_input->HandleEvents(event); + cameraInput->HandleEvents(event); } } @@ -73,14 +73,14 @@ namespace AzFramework { for (int i = 0; i < m_idleCameraInputs.size();) { - auto& camera_input = m_idleCameraInputs[i]; - const bool can_begin = camera_input->Beginning() && + auto& cameraInput = m_idleCameraInputs[i]; + const bool canBegin = cameraInput->Beginning() && std::all_of(m_activeCameraInputs.cbegin(), m_activeCameraInputs.cend(), [](const auto& input) { return !input->Exclusive(); }) && - (!camera_input->Exclusive() || (camera_input->Exclusive() && m_activeCameraInputs.empty())); - if (can_begin) + (!cameraInput->Exclusive() || (cameraInput->Exclusive() && m_activeCameraInputs.empty())); + if (canBegin) { - m_activeCameraInputs.push_back(camera_input); + m_activeCameraInputs.push_back(cameraInput); using AZStd::swap; swap(m_idleCameraInputs[i], m_idleCameraInputs[m_idleCameraInputs.size() - 1]); m_idleCameraInputs.pop_back(); @@ -93,25 +93,25 @@ namespace AzFramework // accumulate Camera nextCamera = targetCamera; - for (auto& camera_input : m_activeCameraInputs) + for (auto& cameraInput : m_activeCameraInputs) { - nextCamera = camera_input->StepCamera(nextCamera, cursorDelta, scrollDelta, deltaTime); + nextCamera = cameraInput->StepCamera(nextCamera, cursorDelta, scrollDelta, deltaTime); } for (int i = 0; i < m_activeCameraInputs.size();) { - auto& camera_input = m_activeCameraInputs[i]; - if (camera_input->Ending()) + auto& cameraInput = m_activeCameraInputs[i]; + if (cameraInput->Ending()) { - camera_input->ClearActivation(); - m_idleCameraInputs.push_back(camera_input); + cameraInput->ClearActivation(); + m_idleCameraInputs.push_back(cameraInput); using AZStd::swap; swap(m_activeCameraInputs[i], m_activeCameraInputs[m_activeCameraInputs.size() - 1]); m_activeCameraInputs.pop_back(); } else { - camera_input->ContinueActivation(); + cameraInput->ContinueActivation(); i++; } } @@ -154,14 +154,14 @@ namespace AzFramework { Camera nextCamera = targetCamera; - nextCamera.m_pitch += float(cursorDelta.m_y) * m_props.m_rotateSpeed; - nextCamera.m_yaw += float(cursorDelta.m_x) * m_props.m_rotateSpeed; + nextCamera.m_pitch -= float(cursorDelta.m_y) * m_props.m_rotateSpeed; + nextCamera.m_yaw -= float(cursorDelta.m_x) * m_props.m_rotateSpeed; - auto clamp_rotation = [](const float angle) { return std::fmod(angle + AZ::Constants::TwoOverPi, AZ::Constants::TwoOverPi); }; + auto clamp_rotation = [](const float angle) { return std::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); }; nextCamera.m_yaw = clamp_rotation(nextCamera.m_yaw); // clamp pitch to be +-90 degrees - nextCamera.m_pitch = AZ::GetClamp(nextCamera.m_pitch, -AZ::Constants::Pi * 0.5f, AZ::Constants::Pi * 0.5f); + nextCamera.m_pitch = AZ::GetClamp(nextCamera.m_pitch, -AZ::Constants::HalfPi, AZ::Constants::HalfPi); return nextCamera; } diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h index 736e2404d9..2fee6dc706 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h +++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h @@ -51,8 +51,8 @@ namespace AzFramework inline AZ::Transform Camera::Transform() const { - return AZ::Transform::CreateTranslation(m_lookAt) * AZ::Transform::CreateRotationX(m_pitch) * - AZ::Transform::CreateRotationZ(m_yaw) * AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisZ(m_lookDist)); + return AZ::Transform::CreateTranslation(m_lookAt) * AZ::Transform::CreateRotationZ(m_yaw) * + AZ::Transform::CreateRotationX(m_pitch) * AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisZ(m_lookDist)); } inline AZ::Matrix3x3 Camera::Rotation() const @@ -308,7 +308,7 @@ namespace AzFramework enum class TranslationType { // clang-format off - Nil = 0, + Nil = 0, Forward = 1 << 0, Backward = 1 << 1, Left = 1 << 2, From c8983183776f89ffb7d1cbab6fcce9b4d9d3283d Mon Sep 17 00:00:00 2001 From: hultonha Date: Tue, 27 Apr 2021 10:30:07 +0100 Subject: [PATCH 2/8] updated camera changes --- .../AzFramework/Viewport/CameraInput.cpp | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp index 1d0b440a9b..33e11e84da 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp +++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp @@ -33,7 +33,7 @@ namespace AzFramework m_cameras.HandleEvents(event); } - Camera CameraSystem::StepCamera(const Camera& targetCamera, float deltaTime) + Camera CameraSystem::StepCamera(const Camera& targetCamera, const float deltaTime) { const auto cursorDelta = m_currentCursorPosition.has_value() && m_lastCursorPosition.has_value() ? m_currentCursorPosition.value() - m_lastCursorPosition.value() @@ -157,9 +157,9 @@ namespace AzFramework nextCamera.m_pitch -= float(cursorDelta.m_y) * m_props.m_rotateSpeed; nextCamera.m_yaw -= float(cursorDelta.m_x) * m_props.m_rotateSpeed; - auto clamp_rotation = [](const float angle) { return std::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); }; + const auto clampRotation = [](const float angle) { return std::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); }; - nextCamera.m_yaw = clamp_rotation(nextCamera.m_yaw); + nextCamera.m_yaw = clampRotation(nextCamera.m_yaw); // clamp pitch to be +-90 degrees nextCamera.m_pitch = AZ::GetClamp(nextCamera.m_pitch, -AZ::Constants::HalfPi, AZ::Constants::HalfPi); @@ -285,10 +285,10 @@ namespace AzFramework { Camera nextCamera = targetCamera; - const auto translation_basis = m_translationAxesFn(nextCamera); - const auto axisX = translation_basis.GetBasisX(); - const auto axisY = translation_basis.GetBasisY(); - const auto axisZ = translation_basis.GetBasisZ(); + const auto translationBasis = m_translationAxesFn(nextCamera); + const auto axisX = translationBasis.GetBasisX(); + const auto axisY = translationBasis.GetBasisY(); + const auto axisZ = translationBasis.GetBasisZ(); const float speed = [boost = m_boost, props = m_props]() { return props.m_translateSpeed * (boost ? props.m_boostMultiplier : 1.0f); @@ -366,7 +366,7 @@ namespace AzFramework } Camera OrbitCameraInput::StepCamera( - const Camera& targetCamera, const ScreenVector& cursorDelta, const float scrollDelta, float deltaTime) + const Camera& targetCamera, const ScreenVector& cursorDelta, const float scrollDelta, const float deltaTime) { Camera nextCamera = targetCamera; @@ -413,7 +413,7 @@ namespace AzFramework Camera OrbitDollyScrollCameraInput::StepCamera( const Camera& targetCamera, [[maybe_unused]] const ScreenVector& cursorDelta, const float scrollDelta, - [[maybe_unused]] float deltaTime) + [[maybe_unused]] const float deltaTime) { Camera nextCamera = targetCamera; nextCamera.m_lookDist = AZ::GetMin(nextCamera.m_lookDist + scrollDelta * m_props.m_dollySpeed, 0.0f); @@ -457,7 +457,7 @@ namespace AzFramework } Camera ScrollTranslationCameraInput::StepCamera( - const Camera& targetCamera, [[maybe_unused]] const ScreenVector& cursorDelta, float scrollDelta, + const Camera& targetCamera, [[maybe_unused]] const ScreenVector& cursorDelta, const float scrollDelta, [[maybe_unused]] const float deltaTime) { Camera nextCamera = targetCamera; @@ -477,25 +477,26 @@ namespace AzFramework const auto clamp_rotation = [](const float angle) { return std::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); }; // keep yaw in 0 - 360 range - float target_yaw = clamp_rotation(targetCamera.m_yaw); - const float current_yaw = clamp_rotation(currentCamera.m_yaw); + float targetYaw = clamp_rotation(targetCamera.m_yaw); + const float currentYaw = clamp_rotation(currentCamera.m_yaw); - auto sign = [](const float value) { return static_cast((0.0f < value) - (value < 0.0f)); }; + // return the sign of the float input (-1, 0, 1) + const auto sign = [](const float value) { return aznumeric_cast((0.0f < value) - (value < 0.0f)); }; // ensure smooth transition when moving across 0 - 360 boundary - const float yaw_delta = target_yaw - current_yaw; - if (std::abs(yaw_delta) >= AZ::Constants::Pi) + const float yawDelta = targetYaw - currentYaw; + if (std::abs(yawDelta) >= AZ::Constants::Pi) { - target_yaw -= AZ::Constants::TwoPi * sign(yaw_delta); + targetYaw -= AZ::Constants::TwoPi * sign(yawDelta); } Camera camera; - // note: the math for the lerp smoothing implementation for camera rotation and translation was inspired by this excellent + // note: the math for the lerp smoothing implementation for camera rotation and translation was inspired by this excellent // article by Scott Lembcke: https://www.gamasutra.com/blogs/ScottLembcke/20180404/316046/Improved_Lerp_Smoothing.php const float lookRate = std::exp2(props.m_lookSmoothness); const float lookT = std::exp2(-lookRate * deltaTime); camera.m_pitch = AZ::Lerp(targetCamera.m_pitch, currentCamera.m_pitch, lookT); - camera.m_yaw = AZ::Lerp(target_yaw, current_yaw, lookT); + camera.m_yaw = AZ::Lerp(targetYaw, currentYaw, lookT); const float moveRate = std::exp2(props.m_moveSmoothness); const float moveT = std::exp2(-moveRate * deltaTime); camera.m_lookDist = AZ::Lerp(targetCamera.m_lookDist, currentCamera.m_lookDist, moveT); From 1b946818a2c31e3de4019f8dce49dca5a33a133a Mon Sep 17 00:00:00 2001 From: hultonha Date: Tue, 27 Apr 2021 13:58:17 +0100 Subject: [PATCH 3/8] more tidy-up to CameraInput.cpp --- .../AzFramework/Viewport/CameraInput.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp index 33e11e84da..6bde8dac85 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp +++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp @@ -190,18 +190,18 @@ namespace AzFramework { Camera nextCamera = targetCamera; - const auto pan_axes = m_panAxesFn(nextCamera); + const auto panAxes = m_panAxesFn(nextCamera); - const auto delta_pan_x = float(cursorDelta.m_x) * pan_axes.m_horizontalAxis * m_props.m_panSpeed; - const auto delta_pan_y = float(cursorDelta.m_y) * pan_axes.m_verticalAxis * m_props.m_panSpeed; + const auto deltaPanX = float(cursorDelta.m_x) * panAxes.m_horizontalAxis * m_props.m_panSpeed; + const auto deltaPanY = float(cursorDelta.m_y) * panAxes.m_verticalAxis * m_props.m_panSpeed; const auto inv = [](const bool invert) { constexpr float Dir[] = {1.0f, -1.0f}; return Dir[static_cast(invert)]; }; - nextCamera.m_lookAt += delta_pan_x * inv(m_props.m_panInvertX); - nextCamera.m_lookAt += delta_pan_y * -inv(m_props.m_panInvertY); + nextCamera.m_lookAt += deltaPanX * inv(m_props.m_panInvertX); + nextCamera.m_lookAt += deltaPanY * -inv(m_props.m_panInvertY); return nextCamera; } @@ -344,10 +344,6 @@ namespace AzFramework { if (input->m_channelId == InputDeviceKeyboard::Key::ModifierAltL) { - if (input->m_state == InputChannel::State::Updated) - { - goto end; - } if (input->m_state == InputChannel::State::Began) { BeginActivation(); @@ -358,7 +354,7 @@ namespace AzFramework } } } - end: + if (Active()) { m_orbitCameras.HandleEvents(event); @@ -388,7 +384,6 @@ namespace AzFramework if (Active()) { - // todo: need to return nested cameras to idle state when ending nextCamera = m_orbitCameras.StepCamera(nextCamera, cursorDelta, scrollDelta, deltaTime); } From 64e06c30107acc5f87e92cf24f3003620e4aedf1 Mon Sep 17 00:00:00 2001 From: hultonha Date: Tue, 27 Apr 2021 19:40:45 +0100 Subject: [PATCH 4/8] more updates to camera code --- .../AzFramework/Viewport/CameraInput.cpp | 17 ++++-- .../AzFramework/Viewport/CameraInput.h | 10 ++-- Code/Sandbox/Editor/EditorViewportWidget.cpp | 9 ++- .../Editor/ModernViewportCameraController.cpp | 55 +++++++++++++++---- .../Editor/ModernViewportCameraController.h | 15 +++-- 5 files changed, 76 insertions(+), 30 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp index 6bde8dac85..984526e373 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp +++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp @@ -19,7 +19,7 @@ namespace AzFramework { - void CameraSystem::HandleEvents(const InputEvent& event) + bool CameraSystem::HandleEvents(const InputEvent& event) { if (const auto& cursor_motion = AZStd::get_if(&event)) { @@ -30,7 +30,7 @@ namespace AzFramework m_scrollDelta = scroll->m_delta; } - m_cameras.HandleEvents(event); + return m_cameras.HandleEvents(event); } Camera CameraSystem::StepCamera(const Camera& targetCamera, const float deltaTime) @@ -56,17 +56,21 @@ namespace AzFramework m_idleCameraInputs.push_back(AZStd::move(cameraInput)); } - void Cameras::HandleEvents(const InputEvent& event) + bool Cameras::HandleEvents(const InputEvent& event) { + bool handling = false; for (auto& cameraInput : m_activeCameraInputs) { cameraInput->HandleEvents(event); + handling = !cameraInput->Idle() || handling; } for (auto& cameraInput : m_idleCameraInputs) { cameraInput->HandleEvents(event); } + + return handling; } Camera Cameras::StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, const float deltaTime) @@ -504,6 +508,11 @@ namespace AzFramework const auto& inputChannelId = inputChannel.GetInputChannelId(); const auto& inputDeviceId = inputChannel.GetInputDevice().GetInputDeviceId(); + const bool wasMouseButton = + AZStd::any_of(InputDeviceMouse::Button::All.begin(), InputDeviceMouse::Button::All.end(), [inputChannelId](const auto& button) { + return button == inputChannelId; + }); + if (inputChannelId == InputDeviceMouse::SystemCursorPosition) { AZ::Vector2 systemCursorPositionNormalized = AZ::Vector2::CreateZero(); @@ -517,7 +526,7 @@ namespace AzFramework { return ScrollEvent{inputChannel.GetValue()}; } - else if (InputDeviceMouse::IsMouseDevice(inputDeviceId) || InputDeviceKeyboard::IsKeyboardDevice(inputDeviceId)) + else if ((InputDeviceMouse::IsMouseDevice(inputDeviceId) && wasMouseButton) || InputDeviceKeyboard::IsKeyboardDevice(inputDeviceId)) { return DiscreteInputEvent{inputChannelId, inputChannel.GetState()}; } diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h index 2fee6dc706..cbfe603c83 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h +++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h @@ -52,7 +52,7 @@ namespace AzFramework inline AZ::Transform Camera::Transform() const { return AZ::Transform::CreateTranslation(m_lookAt) * AZ::Transform::CreateRotationZ(m_yaw) * - AZ::Transform::CreateRotationX(m_pitch) * AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisZ(m_lookDist)); + AZ::Transform::CreateRotationX(m_pitch) * AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisY(m_lookDist)); } inline AZ::Matrix3x3 Camera::Rotation() const @@ -171,7 +171,7 @@ namespace AzFramework { public: void AddCamera(AZStd::shared_ptr cameraInput); - void HandleEvents(const InputEvent& event); + bool HandleEvents(const InputEvent& event); Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime); void Reset(); @@ -183,7 +183,7 @@ namespace AzFramework class CameraSystem { public: - void HandleEvents(const InputEvent& event); + bool HandleEvents(const InputEvent& event); Camera StepCamera(const Camera& targetCamera, float deltaTime); Cameras m_cameras; @@ -369,7 +369,7 @@ namespace AzFramework struct Props { - float m_dollySpeed = 0.2f; + float m_dollySpeed = 0.02f; } m_props; }; @@ -393,7 +393,7 @@ namespace AzFramework struct Props { - float m_translateSpeed = 0.2f; + float m_translateSpeed = 0.02f; } m_props; }; diff --git a/Code/Sandbox/Editor/EditorViewportWidget.cpp b/Code/Sandbox/Editor/EditorViewportWidget.cpp index 25588e85a7..6a32a6abb1 100644 --- a/Code/Sandbox/Editor/EditorViewportWidget.cpp +++ b/Code/Sandbox/Editor/EditorViewportWidget.cpp @@ -1633,8 +1633,8 @@ void EditorViewportWidget::keyPressEvent(QKeyEvent* event) QCoreApplication::sendEvent(GetIEditor()->GetEditorMainWindow(), event); } - // NOTE: we keep track of keypresses and releases explicitly because the OS/Qt will insert a slight delay between sending - // keyevents when the key is held down. This is standard, but makes responding to key events for game style input silly + // NOTE: we keep track of key presses and releases explicitly because the OS/Qt will insert a slight delay between sending + // key events when the key is held down. This is standard, but makes responding to key events for game style input silly // because we want the movement to be butter smooth. if (!event->isAutoRepeat()) { @@ -2428,7 +2428,10 @@ void EditorViewportWidget::SetDefaultCamera() return; } ResetToViewSourceType(ViewSourceType::None); - gEnv->p3DEngine->GetPostEffectBaseGroup()->SetParam("Dof_Active", 0.0f); + if (gEnv->p3DEngine) + { + gEnv->p3DEngine->GetPostEffectBaseGroup()->SetParam("Dof_Active", 0.0f); + } GetViewManager()->SetCameraObjectId(m_cameraObjectId); SetName(m_defaultViewName); SetViewTM(m_defaultViewTM); diff --git a/Code/Sandbox/Editor/ModernViewportCameraController.cpp b/Code/Sandbox/Editor/ModernViewportCameraController.cpp index 80bd9416f7..09fd5be2e9 100644 --- a/Code/Sandbox/Editor/ModernViewportCameraController.cpp +++ b/Code/Sandbox/Editor/ModernViewportCameraController.cpp @@ -14,9 +14,14 @@ #include #include +#include #include +#include #include #include +#include + +AZ_CVAR(bool, ed_newCameraSystemDebug, false, nullptr, AZ::ConsoleFunctorFlags::Null, "Enable debug drawing for the new camera system"); namespace SandboxEditor { @@ -37,8 +42,17 @@ namespace SandboxEditor return viewportContext; } + struct ModernViewportCameraControllerInstance::Impl + { + AzFramework::Camera m_camera; + AzFramework::Camera m_targetCamera; + AzFramework::SmoothProps m_smoothProps; + AzFramework::CameraSystem m_cameraSystem; + }; + ModernViewportCameraControllerInstance::ModernViewportCameraControllerInstance(const AzFramework::ViewportId viewportId) : MultiViewportControllerInstanceInterface(viewportId) + , m_impl(AZStd::make_unique()) { // LYN-2315 TODO - move setup out of constructor, pass cameras in auto firstPersonRotateCamera = AZStd::make_shared(AzFramework::InputDeviceMouse::Button::Right); @@ -58,21 +72,28 @@ namespace SandboxEditor orbitCamera->m_orbitCameras.AddCamera(orbitDollyMoveCamera); orbitCamera->m_orbitCameras.AddCamera(orbitPanCamera); - m_cameraSystem.m_cameras.AddCamera(firstPersonRotateCamera); - m_cameraSystem.m_cameras.AddCamera(firstPersonPanCamera); - m_cameraSystem.m_cameras.AddCamera(firstPersonTranslateCamera); - m_cameraSystem.m_cameras.AddCamera(firstPersonWheelCamera); - m_cameraSystem.m_cameras.AddCamera(orbitCamera); + m_impl->m_cameraSystem.m_cameras.AddCamera(firstPersonRotateCamera); + m_impl->m_cameraSystem.m_cameras.AddCamera(firstPersonPanCamera); + m_impl->m_cameraSystem.m_cameras.AddCamera(firstPersonTranslateCamera); + m_impl->m_cameraSystem.m_cameras.AddCamera(firstPersonWheelCamera); + m_impl->m_cameraSystem.m_cameras.AddCamera(orbitCamera); if (const auto viewportContext = RetrieveViewportContext(viewportId)) { // set position but not orientation - m_targetCamera.m_lookAt = viewportContext->GetCameraTransform().GetTranslation(); + m_impl->m_targetCamera.m_lookAt = viewportContext->GetCameraTransform().GetTranslation(); // LYN-2315 TODO https://www.geometrictools.com/Documentation/EulerAngles.pdf - m_camera = m_targetCamera; + m_impl->m_camera = m_impl->m_targetCamera; } + + AzFramework::ViewportDebugDisplayEventBus::Handler::BusConnect(AzToolsFramework::GetEntityContextId()); + } + + ModernViewportCameraControllerInstance::~ModernViewportCameraControllerInstance() + { + AzFramework::ViewportDebugDisplayEventBus::Handler::BusDisconnect(); } bool ModernViewportCameraControllerInstance::HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) @@ -80,18 +101,28 @@ namespace SandboxEditor AzFramework::WindowSize windowSize; AzFramework::WindowRequestBus::EventResult( windowSize, event.m_windowHandle, &AzFramework::WindowRequestBus::Events::GetClientAreaSize); - m_cameraSystem.HandleEvents(AzFramework::BuildInputEvent(event.m_inputChannel, windowSize)); - return true; // consume event + return m_impl->m_cameraSystem.HandleEvents(AzFramework::BuildInputEvent(event.m_inputChannel, windowSize)); } void ModernViewportCameraControllerInstance::UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event) { if (auto viewportContext = RetrieveViewportContext(GetViewportId())) { - m_targetCamera = m_cameraSystem.StepCamera(m_targetCamera, event.m_deltaTime.count()); - m_camera = AzFramework::SmoothCamera(m_camera, m_targetCamera, m_smoothProps, event.m_deltaTime.count()); + m_impl->m_targetCamera = m_impl->m_cameraSystem.StepCamera(m_impl->m_targetCamera, event.m_deltaTime.count()); + m_impl->m_camera = + AzFramework::SmoothCamera(m_impl->m_camera, m_impl->m_targetCamera, m_impl->m_smoothProps, event.m_deltaTime.count()); + + viewportContext->SetCameraTransform(m_impl->m_camera.Transform()); + } + } - viewportContext->SetCameraTransform(m_camera.Transform()); + void ModernViewportCameraControllerInstance::DisplayViewport( + [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) + { + if (ed_newCameraSystemDebug) + { + debugDisplay.SetColor(AZ::Colors::White); + debugDisplay.DrawWireSphere(m_impl->m_targetCamera.m_lookAt, 0.5f); } } } // namespace SandboxEditor diff --git a/Code/Sandbox/Editor/ModernViewportCameraController.h b/Code/Sandbox/Editor/ModernViewportCameraController.h index c65dbc8b8a..57fdd1cb55 100644 --- a/Code/Sandbox/Editor/ModernViewportCameraController.h +++ b/Code/Sandbox/Editor/ModernViewportCameraController.h @@ -12,25 +12,28 @@ #pragma once -#include +#include #include namespace SandboxEditor { - class ModernViewportCameraControllerInstance final : public AzFramework::MultiViewportControllerInstanceInterface + class ModernViewportCameraControllerInstance final : public AzFramework::MultiViewportControllerInstanceInterface, + private AzFramework::ViewportDebugDisplayEventBus::Handler { public: explicit ModernViewportCameraControllerInstance(AzFramework::ViewportId viewportId); + ~ModernViewportCameraControllerInstance(); // MultiViewportControllerInstanceInterface overrides ... bool HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) override; void UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event) override; + // AzFramework::ViewportDebugDisplayEventBus ... + void DisplayViewport(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override; + private: - AzFramework::Camera m_camera; - AzFramework::Camera m_targetCamera; - AzFramework::SmoothProps m_smoothProps; - AzFramework::CameraSystem m_cameraSystem; + struct Impl; + AZStd::unique_ptr m_impl; }; using ModernViewportCameraController = AzFramework::MultiViewportController; From 7d96fcdf1fe0bd8dbf19b1be00580019b786ddd4 Mon Sep 17 00:00:00 2001 From: hultonha Date: Thu, 29 Apr 2021 18:39:03 +0100 Subject: [PATCH 5/8] updates to fix camera behaviour --- .../AzFramework/Viewport/CameraInput.cpp | 11 ++++- .../AzFramework/Viewport/CameraInput.h | 19 +++++++- Code/Sandbox/Editor/CryEditDoc.cpp | 13 +++++- .../Editor/ModernViewportCameraController.cpp | 43 +++++++++---------- .../Editor/ModernViewportCameraController.h | 15 +++++-- 5 files changed, 69 insertions(+), 32 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp index 984526e373..6d8c019fec 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp +++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp @@ -12,11 +12,16 @@ #include "CameraInput.h" +#include #include #include #include #include +AZ_CVAR( + float, ed_newCameraSystemDefaultPlaneHeight, 34.0f, nullptr, AZ::ConsoleFunctorFlags::Null, + "What is the default height of the ground plane to do intersection tests against when orbiting"); + namespace AzFramework { bool CameraSystem::HandleEvents(const InputEvent& event) @@ -373,9 +378,11 @@ namespace AzFramework if (Beginning()) { float hit_distance = 0.0f; - if (AZ::Plane::CreateFromNormalAndPoint(AZ::Vector3::CreateAxisZ(), AZ::Vector3::CreateZero()) - .CastRay(targetCamera.Translation(), targetCamera.Rotation().GetBasisY() * m_props.m_maxOrbitDistance, hit_distance)) + if (AZ::Plane::CreateFromNormalAndPoint( + AZ::Vector3::CreateAxisZ(), AZ::Vector3::CreateAxisZ(ed_newCameraSystemDefaultPlaneHeight)) + .CastRay(targetCamera.Translation(), targetCamera.Rotation().GetBasisY(), hit_distance)) { + hit_distance = AZStd::min(hit_distance, m_props.m_maxOrbitDistance); nextCamera.m_lookDist = -hit_distance; nextCamera.m_lookAt = targetCamera.Translation() + targetCamera.Rotation().GetBasisY() * hit_distance; } diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h index cbfe603c83..3491453ff1 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h +++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h @@ -12,6 +12,7 @@ #pragma once +#include #include #include #include @@ -25,6 +26,22 @@ namespace AzFramework { struct WindowSize; + // to be moved + class ModernViewportCameraControllerRequests : public AZ::EBusTraits + { + public: + using BusIdType = AzFramework::ViewportId; ///< ViewportId - used to address requests to this EBus. + static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById; + static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; + + virtual void SetTargetCameraTransform(const AZ::Transform& transform) = 0; + + protected: + ~ModernViewportCameraControllerRequests() = default; + }; + + using ModernViewportCameraControllerRequestBus = AZ::EBus; + struct Camera { AZ::Vector3 m_lookAt = AZ::Vector3::CreateZero(); //!< Position of camera when m_lookDist is zero, @@ -411,7 +428,7 @@ namespace AzFramework struct Props { - float m_defaultOrbitDistance = 15.0f; + float m_defaultOrbitDistance = 60.0f; float m_maxOrbitDistance = 100.0f; } m_props; }; diff --git a/Code/Sandbox/Editor/CryEditDoc.cpp b/Code/Sandbox/Editor/CryEditDoc.cpp index 8819c8b382..00e5a3b85b 100644 --- a/Code/Sandbox/Editor/CryEditDoc.cpp +++ b/Code/Sandbox/Editor/CryEditDoc.cpp @@ -28,6 +28,7 @@ #include #include #include +#include // AzToolsFramework #include @@ -669,13 +670,21 @@ void CCryEditDoc::SerializeViewSettings(CXmlArchive& xmlAr) CViewport* pVP = GetIEditor()->GetViewManager()->GetView(i); + Matrix34 tm = Matrix34::CreateRotationXYZ(va); + tm.SetTranslation(vp); + if (pVP) { - Matrix34 tm = Matrix34::CreateRotationXYZ(va); - tm.SetTranslation(vp); pVP->SetViewTM(tm); } + if (auto viewportContext = AZ::Interface::Get()->GetDefaultViewportContext()) + { + AzFramework::ModernViewportCameraControllerRequestBus::Event( + viewportContext->GetId(), &AzFramework::ModernViewportCameraControllerRequestBus::Events::SetTargetCameraTransform, + LYTransformToAZTransform(tm)); + } + // Load grid. auto gridName = QString("Grid%1").arg(useOldViewFormat ? "" : QString::number(i)); XmlNodeRef gridNode = xmlAr.root->newChild(gridName.toUtf8().constData()); diff --git a/Code/Sandbox/Editor/ModernViewportCameraController.cpp b/Code/Sandbox/Editor/ModernViewportCameraController.cpp index 09fd5be2e9..f94f067a21 100644 --- a/Code/Sandbox/Editor/ModernViewportCameraController.cpp +++ b/Code/Sandbox/Editor/ModernViewportCameraController.cpp @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -42,17 +41,8 @@ namespace SandboxEditor return viewportContext; } - struct ModernViewportCameraControllerInstance::Impl - { - AzFramework::Camera m_camera; - AzFramework::Camera m_targetCamera; - AzFramework::SmoothProps m_smoothProps; - AzFramework::CameraSystem m_cameraSystem; - }; - ModernViewportCameraControllerInstance::ModernViewportCameraControllerInstance(const AzFramework::ViewportId viewportId) : MultiViewportControllerInstanceInterface(viewportId) - , m_impl(AZStd::make_unique()) { // LYN-2315 TODO - move setup out of constructor, pass cameras in auto firstPersonRotateCamera = AZStd::make_shared(AzFramework::InputDeviceMouse::Button::Right); @@ -72,27 +62,29 @@ namespace SandboxEditor orbitCamera->m_orbitCameras.AddCamera(orbitDollyMoveCamera); orbitCamera->m_orbitCameras.AddCamera(orbitPanCamera); - m_impl->m_cameraSystem.m_cameras.AddCamera(firstPersonRotateCamera); - m_impl->m_cameraSystem.m_cameras.AddCamera(firstPersonPanCamera); - m_impl->m_cameraSystem.m_cameras.AddCamera(firstPersonTranslateCamera); - m_impl->m_cameraSystem.m_cameras.AddCamera(firstPersonWheelCamera); - m_impl->m_cameraSystem.m_cameras.AddCamera(orbitCamera); + m_cameraSystem.m_cameras.AddCamera(firstPersonRotateCamera); + m_cameraSystem.m_cameras.AddCamera(firstPersonPanCamera); + m_cameraSystem.m_cameras.AddCamera(firstPersonTranslateCamera); + m_cameraSystem.m_cameras.AddCamera(firstPersonWheelCamera); + m_cameraSystem.m_cameras.AddCamera(orbitCamera); if (const auto viewportContext = RetrieveViewportContext(viewportId)) { // set position but not orientation - m_impl->m_targetCamera.m_lookAt = viewportContext->GetCameraTransform().GetTranslation(); + m_targetCamera.m_lookAt = viewportContext->GetCameraTransform().GetTranslation(); // LYN-2315 TODO https://www.geometrictools.com/Documentation/EulerAngles.pdf - m_impl->m_camera = m_impl->m_targetCamera; + m_camera = m_targetCamera; } AzFramework::ViewportDebugDisplayEventBus::Handler::BusConnect(AzToolsFramework::GetEntityContextId()); + AzFramework::ModernViewportCameraControllerRequestBus::Handler::BusConnect(viewportId); } ModernViewportCameraControllerInstance::~ModernViewportCameraControllerInstance() { + AzFramework::ModernViewportCameraControllerRequestBus::Handler::BusDisconnect(); AzFramework::ViewportDebugDisplayEventBus::Handler::BusDisconnect(); } @@ -101,18 +93,18 @@ namespace SandboxEditor AzFramework::WindowSize windowSize; AzFramework::WindowRequestBus::EventResult( windowSize, event.m_windowHandle, &AzFramework::WindowRequestBus::Events::GetClientAreaSize); - return m_impl->m_cameraSystem.HandleEvents(AzFramework::BuildInputEvent(event.m_inputChannel, windowSize)); + return m_cameraSystem.HandleEvents(AzFramework::BuildInputEvent(event.m_inputChannel, windowSize)); } void ModernViewportCameraControllerInstance::UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event) { if (auto viewportContext = RetrieveViewportContext(GetViewportId())) { - m_impl->m_targetCamera = m_impl->m_cameraSystem.StepCamera(m_impl->m_targetCamera, event.m_deltaTime.count()); - m_impl->m_camera = - AzFramework::SmoothCamera(m_impl->m_camera, m_impl->m_targetCamera, m_impl->m_smoothProps, event.m_deltaTime.count()); + m_targetCamera = m_cameraSystem.StepCamera(m_targetCamera, event.m_deltaTime.count()); + m_camera = + AzFramework::SmoothCamera(m_camera, m_targetCamera, m_smoothProps, event.m_deltaTime.count()); - viewportContext->SetCameraTransform(m_impl->m_camera.Transform()); + viewportContext->SetCameraTransform(m_camera.Transform()); } } @@ -122,7 +114,12 @@ namespace SandboxEditor if (ed_newCameraSystemDebug) { debugDisplay.SetColor(AZ::Colors::White); - debugDisplay.DrawWireSphere(m_impl->m_targetCamera.m_lookAt, 0.5f); + debugDisplay.DrawWireSphere(m_targetCamera.m_lookAt, 0.5f); } } + + void ModernViewportCameraControllerInstance::SetTargetCameraTransform(const AZ::Transform& transform) + { + m_targetCamera.m_lookAt = transform.GetTranslation(); + } } // namespace SandboxEditor diff --git a/Code/Sandbox/Editor/ModernViewportCameraController.h b/Code/Sandbox/Editor/ModernViewportCameraController.h index 57fdd1cb55..a3d4f8cea6 100644 --- a/Code/Sandbox/Editor/ModernViewportCameraController.h +++ b/Code/Sandbox/Editor/ModernViewportCameraController.h @@ -13,12 +13,14 @@ #pragma once #include +#include #include namespace SandboxEditor { class ModernViewportCameraControllerInstance final : public AzFramework::MultiViewportControllerInstanceInterface, - private AzFramework::ViewportDebugDisplayEventBus::Handler + private AzFramework::ViewportDebugDisplayEventBus::Handler, + private AzFramework::ModernViewportCameraControllerRequestBus::Handler { public: explicit ModernViewportCameraControllerInstance(AzFramework::ViewportId viewportId); @@ -28,12 +30,17 @@ namespace SandboxEditor bool HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) override; void UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event) override; - // AzFramework::ViewportDebugDisplayEventBus ... + // AzFramework::ViewportDebugDisplayEventBus overrides ... void DisplayViewport(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override; + // ModernViewportCameraControllerRequestBus overrides ... + void SetTargetCameraTransform(const AZ::Transform& transform) override; + private: - struct Impl; - AZStd::unique_ptr m_impl; + AzFramework::Camera m_camera; + AzFramework::Camera m_targetCamera; + AzFramework::SmoothProps m_smoothProps; + AzFramework::CameraSystem m_cameraSystem; }; using ModernViewportCameraController = AzFramework::MultiViewportController; From f01e64a023d709def3e9f584e8b2a74c54f615d3 Mon Sep 17 00:00:00 2001 From: hultonha Date: Fri, 30 Apr 2021 09:21:21 +0100 Subject: [PATCH 6/8] add missing includes --- Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h | 1 + Code/Sandbox/Editor/CryEditDoc.cpp | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h index 3491453ff1..4c076b887d 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h +++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h @@ -21,6 +21,7 @@ #include #include #include +#include namespace AzFramework { diff --git a/Code/Sandbox/Editor/CryEditDoc.cpp b/Code/Sandbox/Editor/CryEditDoc.cpp index 00e5a3b85b..ceea0d1c1e 100644 --- a/Code/Sandbox/Editor/CryEditDoc.cpp +++ b/Code/Sandbox/Editor/CryEditDoc.cpp @@ -30,6 +30,10 @@ #include #include +// Atom +#include +#include + // AzToolsFramework #include #include From 0a4d62eeed4453f50f6caf7e4e998b5f77321879 Mon Sep 17 00:00:00 2001 From: hultonha Date: Fri, 30 Apr 2021 10:56:40 +0100 Subject: [PATCH 7/8] update cvar description --- Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp index 6d8c019fec..62b8fb338b 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp +++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp @@ -20,7 +20,7 @@ AZ_CVAR( float, ed_newCameraSystemDefaultPlaneHeight, 34.0f, nullptr, AZ::ConsoleFunctorFlags::Null, - "What is the default height of the ground plane to do intersection tests against when orbiting"); + "The default height of the ground plane to do intersection tests against when orbiting"); namespace AzFramework { From fb46d11f6ca1aeb5a7f8ed115ef8c18dbff0c02c Mon Sep 17 00:00:00 2001 From: hultonha Date: Fri, 30 Apr 2021 14:52:14 +0100 Subject: [PATCH 8/8] add missing const --- .../Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp index 62b8fb338b..851522c701 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp +++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp @@ -78,7 +78,7 @@ namespace AzFramework return handling; } - Camera Cameras::StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, const float deltaTime) + Camera Cameras::StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, const float scrollDelta, const float deltaTime) { for (int i = 0; i < m_idleCameraInputs.size();) { @@ -87,6 +87,7 @@ namespace AzFramework std::all_of(m_activeCameraInputs.cbegin(), m_activeCameraInputs.cend(), [](const auto& input) { return !input->Exclusive(); }) && (!cameraInput->Exclusive() || (cameraInput->Exclusive() && m_activeCameraInputs.empty())); + if (canBegin) { m_activeCameraInputs.push_back(cameraInput);