Add an Orthogonal Projection option to the Camera Gem (#2414)

* Add an Orthogonal Projection option to the Camera Gem

This adds a check-box to opt into an ortho projection along with a half-width parameter to adjust the size of the visible area. Includes some light tweaks to ensure debug rendering looks OK and that we generate a correct camera state for these non-perspective views.

Known issue: while in "Be this camera" mode in the Editor using an ortho projection manipulators aren't working correctly. This appears to be a downstream issue with CameraState consumers not actually checking the ortho flag.

Signed-off-by: nvsickle <nvsickle@amazon.com>

* Fix some typos

Signed-off-by: nvsickle <nvsickle@amazon.com>

* Account for reversed depth buffer

Signed-off-by: nvsickle <nvsickle@amazon.com>

* Clarify depth reversal for MakeOrthographicMatrixRH

Signed-off-by: nvsickle <nvsickle@amazon.com>
This commit is contained in:
Nicholas Van Sickle
2021-07-26 13:58:50 -07:00
committed by GitHub
parent e81f59d1e1
commit 7f84a4318c
12 changed files with 232 additions and 33 deletions
@@ -17,6 +17,9 @@
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <Atom/RPI.Public/ViewportContext.h>
#include <Atom/RPI.Public/View.h>
namespace Camera
{
namespace ClassConverters
@@ -155,6 +158,42 @@ namespace Camera
}
}
bool EditorCameraComponent::GetCameraState(AzFramework::CameraState& cameraState)
{
const CameraComponentConfig& config = m_controller.GetConfiguration();
AZ::RPI::ViewportContextPtr viewportContext = m_controller.GetViewportContext();
AZ::RPI::ViewPtr view = m_controller.GetView();
if (viewportContext == nullptr || view == nullptr)
{
return false;
}
AzFramework::SetCameraTransform(cameraState, view->GetCameraTransform());
{
const AzFramework::WindowSize viewportSize = viewportContext->GetViewportSize();
cameraState.m_viewportSize =
AZ::Vector2{aznumeric_cast<float>(viewportSize.m_width), aznumeric_cast<float>(viewportSize.m_height)};
}
if (config.m_orthographic)
{
cameraState.m_fovOrZoom = cameraState.m_viewportSize.GetX() / (config.m_orthographicHalfWidth * 2.0f);
cameraState.m_orthographic = true;
}
else
{
cameraState.m_fovOrZoom = config.m_fov;
cameraState.m_orthographic = false;
}
cameraState.m_nearClip = config.m_nearClipDistance;
cameraState.m_farClip = config.m_farClipDistance;
return true;
}
AZ::Crc32 EditorCameraComponent::OnPossessCameraButtonClicked()
{
AZ::EntityId currentViewEntity;
@@ -201,9 +240,20 @@ namespace Camera
const CameraComponentConfig& config = m_controller.GetConfiguration();
const float distance = config.m_farClipDistance * m_frustumViewPercentLength * 0.01f;
float tangent = static_cast<float>(tan(0.5f * AZ::DegToRad(config.m_fov)));
float height = distance * tangent;
float width = height * debugDisplay.GetAspectRatio();
float width;
float height;
if (config.m_orthographic)
{
width = config.m_orthographicHalfWidth;
height = width / debugDisplay.GetAspectRatio();
}
else
{
const float tangent = static_cast<float>(tan(0.5f * AZ::DegToRad(config.m_fov)));
height = distance * tangent;
width = height * debugDisplay.GetAspectRatio();
}
AZ::Vector3 farPoints[4];
farPoints[0] = AZ::Vector3( width, distance, height);
@@ -211,12 +261,21 @@ namespace Camera
farPoints[2] = AZ::Vector3(-width, distance, -height);
farPoints[3] = AZ::Vector3( width, distance, -height);
AZ::Vector3 start(0, 0, 0);
AZ::Vector3 nearPoints[4];
nearPoints[0] = farPoints[0].GetNormalizedSafe() * config.m_nearClipDistance;
nearPoints[1] = farPoints[1].GetNormalizedSafe() * config.m_nearClipDistance;
nearPoints[2] = farPoints[2].GetNormalizedSafe() * config.m_nearClipDistance;
nearPoints[3] = farPoints[3].GetNormalizedSafe() * config.m_nearClipDistance;
if (config.m_orthographic)
{
nearPoints[0] = AZ::Vector3( width, config.m_nearClipDistance, height);
nearPoints[1] = AZ::Vector3(-width, config.m_nearClipDistance, height);
nearPoints[2] = AZ::Vector3(-width, config.m_nearClipDistance, -height);
nearPoints[3] = AZ::Vector3( width, config.m_nearClipDistance, -height);
}
else
{
nearPoints[0] = farPoints[0].GetNormalizedSafe() * config.m_nearClipDistance;
nearPoints[1] = farPoints[1].GetNormalizedSafe() * config.m_nearClipDistance;
nearPoints[2] = farPoints[2].GetNormalizedSafe() * config.m_nearClipDistance;
nearPoints[3] = farPoints[3].GetNormalizedSafe() * config.m_nearClipDistance;
}
debugDisplay.PushMatrix(world);
debugDisplay.SetColor(m_frustumDrawColor.GetAsVector4());