Fixes for viewport selection issues (#5494)
* improvements to editor selection in the viewport Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * fix issue with being able to select icons that are not showing for entities inside entity containers Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * update comment after review feedback Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * updates to viewport picking code to simplify the api Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * add test to replicate near clip intersection issue Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * small tidy-up changes Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * updates to how we perform world to screen and screen to world calculations, added test coverage and some tidy-up Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * add some more tests for ViewportInteractionImpl Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * minor tweaks before PR feedback Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * fix typo in fix Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * fix for manipulator test framework tests Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * updates to RPI::View and RenderPipeline after review feedback from VickyAtAZ Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * add constexpr to ScreenPoint, ScreenVector and ScreenSize initializing constructors Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * add PrintTo functions for Screen* types Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * downgrade error to warning temporarily Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * check incoming view is null Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * remove pragma optimize off Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
ef16207ac5
commit
e34ea3bcaa
@@ -75,7 +75,11 @@ namespace AtomToolsFramework
|
||||
m_defaultCamera = AZ::RPI::View::CreateView(cameraName, AZ::RPI::View::UsageFlags::UsageCamera);
|
||||
AZ::Interface<AZ::RPI::ViewportContextRequestsInterface>::Get()->PushView(m_viewportContext->GetName(), m_defaultCamera);
|
||||
|
||||
AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler::BusConnect(GetId());
|
||||
m_viewportInteractionImpl = AZStd::make_unique<ViewportInteractionImpl>(m_defaultCamera);
|
||||
m_viewportInteractionImpl->m_deviceScalingFactorFn = [this] { return aznumeric_cast<float>(devicePixelRatioF()); };
|
||||
m_viewportInteractionImpl->m_screenSizeFn = [this] { return AzFramework::ScreenSize(width(), height()); };
|
||||
m_viewportInteractionImpl->Connect(id);
|
||||
|
||||
AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Handler::BusConnect(GetId());
|
||||
AzFramework::InputChannelEventListener::Connect();
|
||||
AZ::TickBus::Handler::BusConnect();
|
||||
@@ -107,7 +111,7 @@ namespace AtomToolsFramework
|
||||
AZ::TickBus::Handler::BusDisconnect();
|
||||
AzFramework::InputChannelEventListener::Disconnect();
|
||||
AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Handler::BusDisconnect();
|
||||
AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler::BusDisconnect();
|
||||
m_viewportInteractionImpl->Disconnect();
|
||||
}
|
||||
|
||||
void RenderViewportWidget::LockRenderTargetSize(uint32_t width, uint32_t height)
|
||||
@@ -278,77 +282,23 @@ namespace AtomToolsFramework
|
||||
|
||||
AzFramework::CameraState RenderViewportWidget::GetCameraState()
|
||||
{
|
||||
AZ::RPI::ViewPtr currentView = m_viewportContext->GetDefaultView();
|
||||
if (currentView == nullptr)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
// Build camera state from Atom camera transforms
|
||||
AzFramework::CameraState cameraState = AzFramework::CreateCameraFromWorldFromViewMatrix(
|
||||
currentView->GetViewToWorldMatrix(),
|
||||
AZ::Vector2{aznumeric_cast<float>(width()), aznumeric_cast<float>(height())}
|
||||
);
|
||||
AzFramework::SetCameraClippingVolumeFromPerspectiveFovMatrixRH(cameraState, currentView->GetViewToClipMatrix());
|
||||
|
||||
// Convert from Z-up
|
||||
AZStd::swap(cameraState.m_forward, cameraState.m_up);
|
||||
cameraState.m_forward = -cameraState.m_forward;
|
||||
|
||||
return cameraState;
|
||||
return m_viewportInteractionImpl->GetCameraState();
|
||||
}
|
||||
|
||||
AzFramework::ScreenPoint RenderViewportWidget::ViewportWorldToScreen(const AZ::Vector3& worldPosition)
|
||||
{
|
||||
if (AZ::RPI::ViewPtr currentView = m_viewportContext->GetDefaultView();
|
||||
currentView == nullptr)
|
||||
{
|
||||
return AzFramework::ScreenPoint(0, 0);
|
||||
}
|
||||
|
||||
return AzFramework::WorldToScreen(worldPosition, GetCameraState());
|
||||
return m_viewportInteractionImpl->ViewportWorldToScreen(worldPosition);
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::Vector3> RenderViewportWidget::ViewportScreenToWorld(const AzFramework::ScreenPoint& screenPosition, float depth)
|
||||
AZ::Vector3 RenderViewportWidget::ViewportScreenToWorld(const AzFramework::ScreenPoint& screenPosition)
|
||||
{
|
||||
const auto& cameraProjection = m_viewportContext->GetCameraProjectionMatrix();
|
||||
const auto& cameraView = m_viewportContext->GetCameraViewMatrix();
|
||||
|
||||
const AZ::Vector4 normalizedScreenPosition {
|
||||
screenPosition.m_x * 2.f / width() - 1.0f,
|
||||
(height() - screenPosition.m_y) * 2.f / height() - 1.0f,
|
||||
1.f - depth, // [GFX TODO] [ATOM-1501] Currently we always assume reverse depth
|
||||
1.f
|
||||
};
|
||||
|
||||
AZ::Matrix4x4 worldFromScreen = cameraProjection * cameraView;
|
||||
worldFromScreen.InvertFull();
|
||||
|
||||
const AZ::Vector4 projectedPosition = worldFromScreen * normalizedScreenPosition;
|
||||
if (projectedPosition.GetW() == 0.0f)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return projectedPosition.GetAsVector3() / projectedPosition.GetW();
|
||||
return m_viewportInteractionImpl->ViewportScreenToWorld(screenPosition);
|
||||
}
|
||||
|
||||
AZStd::optional<AzToolsFramework::ViewportInteraction::ProjectedViewportRay> RenderViewportWidget::ViewportScreenToWorldRay(
|
||||
AzToolsFramework::ViewportInteraction::ProjectedViewportRay RenderViewportWidget::ViewportScreenToWorldRay(
|
||||
const AzFramework::ScreenPoint& screenPosition)
|
||||
{
|
||||
auto pos0 = ViewportScreenToWorld(screenPosition, 0.f);
|
||||
auto pos1 = ViewportScreenToWorld(screenPosition, 1.f);
|
||||
if (!pos0.has_value() || !pos1.has_value())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
pos0 = m_viewportContext->GetDefaultView()->GetViewToWorldMatrix().GetTranslation();
|
||||
AZ::Vector3 rayOrigin = pos0.value();
|
||||
AZ::Vector3 rayDirection = pos1.value() - pos0.value();
|
||||
rayDirection.Normalize();
|
||||
|
||||
return AzToolsFramework::ViewportInteraction::ProjectedViewportRay{rayOrigin, rayDirection};
|
||||
return m_viewportInteractionImpl->ViewportScreenToWorldRay(screenPosition);
|
||||
}
|
||||
|
||||
float RenderViewportWidget::DeviceScalingFactor()
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AtomToolsFramework/Viewport/ViewportInteractionImpl.h>
|
||||
#include <AzFramework/Viewport/ViewportScreen.h>
|
||||
|
||||
namespace AtomToolsFramework
|
||||
{
|
||||
ViewportInteractionImpl::ViewportInteractionImpl(AZ::RPI::ViewPtr viewPtr)
|
||||
: m_viewPtr(AZStd::move(viewPtr))
|
||||
{
|
||||
}
|
||||
|
||||
void ViewportInteractionImpl::Connect(const AzFramework::ViewportId viewportId)
|
||||
{
|
||||
AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler::BusConnect(viewportId);
|
||||
}
|
||||
|
||||
void ViewportInteractionImpl::Disconnect()
|
||||
{
|
||||
AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
AzFramework::CameraState ViewportInteractionImpl::GetCameraState()
|
||||
{
|
||||
// build camera state from atom camera transforms
|
||||
AzFramework::CameraState cameraState =
|
||||
AzFramework::CreateDefaultCamera(m_viewPtr->GetCameraTransform(), AzFramework::Vector2FromScreenSize(m_screenSizeFn()));
|
||||
AzFramework::SetCameraClippingVolumeFromPerspectiveFovMatrixRH(cameraState, m_viewPtr->GetViewToClipMatrix());
|
||||
return cameraState;
|
||||
}
|
||||
|
||||
AzFramework::ScreenPoint ViewportInteractionImpl::ViewportWorldToScreen(const AZ::Vector3& worldPosition)
|
||||
{
|
||||
return AzFramework::WorldToScreen(worldPosition, GetCameraState());
|
||||
}
|
||||
|
||||
AZ::Vector3 ViewportInteractionImpl::ViewportScreenToWorld(const AzFramework::ScreenPoint& screenPosition)
|
||||
{
|
||||
return AzFramework::ScreenToWorld(screenPosition, GetCameraState());
|
||||
}
|
||||
|
||||
AzToolsFramework::ViewportInteraction::ProjectedViewportRay ViewportInteractionImpl::ViewportScreenToWorldRay(
|
||||
const AzFramework::ScreenPoint& screenPosition)
|
||||
{
|
||||
const AzFramework::CameraState cameraState = GetCameraState();
|
||||
const AZ::Vector3 rayOrigin = AzFramework::ScreenToWorld(screenPosition, cameraState);
|
||||
const AZ::Vector3 rayDirection = (rayOrigin - cameraState.m_position).GetNormalized();
|
||||
return AzToolsFramework::ViewportInteraction::ProjectedViewportRay{ rayOrigin, rayDirection };
|
||||
}
|
||||
|
||||
float ViewportInteractionImpl::DeviceScalingFactor()
|
||||
{
|
||||
return m_deviceScalingFactorFn();
|
||||
}
|
||||
} // namespace AtomToolsFramework
|
||||
Reference in New Issue
Block a user