You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
- New functions are added to get the Primary View or all Secondary Views and takes advantage of that to replace hardcoded indices. - Added support for retrieving a monoscopic projection/pose from IStereoRendering when a single frustum is needed for culling purposes. #rb Steve.Smith #rb Jeff.Fisher #rb Zach.Bethel #preflight 61de16e96a076ddb53cf59b4 #ROBOMERGE-AUTHOR: jules.blok #ROBOMERGE-SOURCE: CL 18579012 in //UE5/Release-5.0/... via CL 18579021 via CL 18579025 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Test -> Main) (v899-18417669) [CL 18579042 by jules blok in ue5-main branch]
227 lines
8.2 KiB
C++
227 lines
8.2 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "DefaultXRCamera.h"
|
|
#include "GameFramework/PlayerController.h"
|
|
#include "RendererPrivate.h"
|
|
#include "ScenePrivate.h"
|
|
#include "Slate/SceneViewport.h"
|
|
#include "StereoRendering.h"
|
|
#include "StereoRenderTargetManager.h"
|
|
#include "IHeadMountedDisplay.h"
|
|
|
|
FDefaultXRCamera::FDefaultXRCamera(const FAutoRegister& AutoRegister, IXRTrackingSystem* InTrackingSystem, int32 InDeviceId)
|
|
: FHMDSceneViewExtension(AutoRegister)
|
|
, TrackingSystem(InTrackingSystem)
|
|
, DeviceId(InDeviceId)
|
|
, DeltaControlRotation(0, 0, 0)
|
|
, DeltaControlOrientation(FQuat::Identity)
|
|
, bUseImplicitHMDPosition(false)
|
|
{
|
|
}
|
|
|
|
void FDefaultXRCamera::ApplyHMDRotation(APlayerController* PC, FRotator& ViewRotation)
|
|
{
|
|
ViewRotation.Normalize();
|
|
FQuat DeviceOrientation;
|
|
FVector DevicePosition;
|
|
if ( TrackingSystem->GetCurrentPose(DeviceId, DeviceOrientation, DevicePosition) )
|
|
{
|
|
const FRotator DeltaRot = ViewRotation - PC->GetControlRotation();
|
|
DeltaControlRotation = (DeltaControlRotation + DeltaRot).GetNormalized();
|
|
|
|
// Pitch from other sources is never good, because there is an absolute up and down that must be respected to avoid motion sickness.
|
|
// Same with roll.
|
|
DeltaControlRotation.Pitch = 0;
|
|
DeltaControlRotation.Roll = 0;
|
|
DeltaControlOrientation = DeltaControlRotation.Quaternion();
|
|
|
|
ViewRotation = FRotator(DeltaControlOrientation * DeviceOrientation);
|
|
}
|
|
}
|
|
|
|
bool FDefaultXRCamera::UpdatePlayerCamera(FQuat& CurrentOrientation, FVector& CurrentPosition)
|
|
{
|
|
FQuat DeviceOrientation;
|
|
FVector DevicePosition;
|
|
if (!TrackingSystem->GetCurrentPose(DeviceId, DeviceOrientation, DevicePosition))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (GEnableVREditorHacks && !bUseImplicitHMDPosition)
|
|
{
|
|
DeltaControlOrientation = CurrentOrientation;
|
|
DeltaControlRotation = DeltaControlOrientation.Rotator();
|
|
}
|
|
|
|
CurrentPosition = DevicePosition;
|
|
CurrentOrientation = DeviceOrientation;
|
|
|
|
return true;
|
|
}
|
|
|
|
void FDefaultXRCamera::OverrideFOV(float& InOutFOV)
|
|
{
|
|
// The default camera does not override the FOV
|
|
}
|
|
|
|
void FDefaultXRCamera::SetupLateUpdate(const FTransform& ParentToWorld, USceneComponent* Component, bool bSkipLateUpdate)
|
|
{
|
|
LateUpdate.Setup(ParentToWorld, Component, bSkipLateUpdate);
|
|
}
|
|
|
|
void FDefaultXRCamera::CalculateStereoCameraOffset(const int32 ViewIndex, FRotator& ViewRotation, FVector& ViewLocation)
|
|
{
|
|
FQuat EyeOrientation;
|
|
FVector EyeOffset;
|
|
if (TrackingSystem->GetRelativeEyePose(DeviceId, ViewIndex, EyeOrientation, EyeOffset))
|
|
{
|
|
ViewLocation += ViewRotation.Quaternion().RotateVector(EyeOffset);
|
|
ViewRotation = FRotator(ViewRotation.Quaternion() * EyeOrientation);
|
|
}
|
|
else if (ViewIndex == EStereoscopicEye::eSSE_MONOSCOPIC && TrackingSystem->GetHMDDevice())
|
|
{
|
|
float HFov, VFov;
|
|
TrackingSystem->GetHMDDevice()->GetFieldOfView(HFov, VFov);
|
|
if (HFov > 0.0f)
|
|
{
|
|
const float CenterOffset = GNearClippingPlane + (TrackingSystem->GetHMDDevice()->GetInterpupillaryDistance() / 2.0f) * (1.0f / FMath::Tan(FMath::DegreesToRadians(HFov)));
|
|
ViewLocation += ViewRotation.Quaternion().RotateVector(FVector(CenterOffset, 0, 0));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!bUseImplicitHMDPosition)
|
|
{
|
|
FQuat DeviceOrientation; // Unused
|
|
FVector DevicePosition;
|
|
TrackingSystem->GetCurrentPose(DeviceId, DeviceOrientation, DevicePosition);
|
|
ViewLocation += DeltaControlOrientation.RotateVector(DevicePosition);
|
|
}
|
|
}
|
|
|
|
void FDefaultXRCamera::PreRenderView_RenderThread(FRHICommandListImmediate& RHICmdList, FSceneView& View)
|
|
{
|
|
check(IsInRenderingThread());
|
|
|
|
// Disable late update for day dream, their compositor doesn't support it.
|
|
// Also disable it if we are set to skip it.
|
|
const bool bDoLateUpdate = !LateUpdate.GetSkipLateUpdate_RenderThread();
|
|
if (bDoLateUpdate)
|
|
{
|
|
FQuat DeviceOrientation;
|
|
FVector DevicePosition;
|
|
|
|
if (TrackingSystem->DoesSupportLateProjectionUpdate() && TrackingSystem->GetStereoRenderingDevice())
|
|
{
|
|
View.UpdateProjectionMatrix(TrackingSystem->GetStereoRenderingDevice()->GetStereoProjectionMatrix(View.StereoViewIndex));
|
|
}
|
|
|
|
if (TrackingSystem->GetCurrentPose(DeviceId, DeviceOrientation, DevicePosition))
|
|
{
|
|
const FQuat DeltaOrient = View.BaseHmdOrientation.Inverse() * DeviceOrientation;
|
|
View.ViewRotation = FRotator(View.ViewRotation.Quaternion() * DeltaOrient);
|
|
|
|
if (bUseImplicitHMDPosition)
|
|
{
|
|
const FQuat LocalDeltaControlOrientation = View.ViewRotation.Quaternion() * DeviceOrientation.Inverse();
|
|
const FVector DeltaPosition = DevicePosition - View.BaseHmdLocation;
|
|
View.ViewLocation += LocalDeltaControlOrientation.RotateVector(DeltaPosition);
|
|
}
|
|
|
|
View.UpdateViewMatrix();
|
|
}
|
|
}
|
|
}
|
|
|
|
void FDefaultXRCamera::BeginRenderViewFamily(FSceneViewFamily& InViewFamily)
|
|
{
|
|
check(IsInGameThread());
|
|
{
|
|
// Backwards compatibility during deprecation phase. Remove once IHeadMountedDisplay::BeginRendering_GameThread has been removed.
|
|
PRAGMA_DISABLE_DEPRECATION_WARNINGS
|
|
auto HMD = TrackingSystem->GetHMDDevice();
|
|
if (HMD)
|
|
{
|
|
HMD->BeginRendering_GameThread();
|
|
}
|
|
PRAGMA_ENABLE_DEPRECATION_WARNINGS
|
|
}
|
|
TrackingSystem->OnBeginRendering_GameThread();
|
|
}
|
|
|
|
void FDefaultXRCamera::PreRenderViewFamily_RenderThread(FRHICommandListImmediate& RHICmdList, FSceneViewFamily& ViewFamily)
|
|
{
|
|
check(IsInRenderingThread());
|
|
|
|
{
|
|
// Backwards compatibility during deprecation phase. Remove once IXRTrackingSystem::RefreshPoses has been removed.
|
|
PRAGMA_DISABLE_DEPRECATION_WARNINGS
|
|
TrackingSystem->RefreshPoses();
|
|
PRAGMA_ENABLE_DEPRECATION_WARNINGS
|
|
}
|
|
TrackingSystem->OnBeginRendering_RenderThread(RHICmdList, ViewFamily);
|
|
|
|
{
|
|
FQuat CurrentOrientation;
|
|
FVector CurrentPosition;
|
|
if (TrackingSystem->DoesSupportLateUpdate() && TrackingSystem->GetCurrentPose(DeviceId, CurrentOrientation, CurrentPosition))
|
|
{
|
|
const FSceneView* MainView = ViewFamily.Views[0];
|
|
check(MainView);
|
|
|
|
// TODO: Should we (and do we have enough information to) double-check that the plugin actually has updated the pose here?
|
|
// ensure((CurrentPosition != MainView->BaseHmdLocation && CurrentOrientation != MainView->BaseHmdOrientation) || CurrentPosition.IsZero() || CurrentOrientation.IsIdentity() );
|
|
|
|
const FTransform OldRelativeTransform(MainView->BaseHmdOrientation, MainView->BaseHmdLocation);
|
|
const FTransform CurrentRelativeTransform(CurrentOrientation, CurrentPosition);
|
|
|
|
LateUpdate.Apply_RenderThread(ViewFamily.Scene, OldRelativeTransform, CurrentRelativeTransform);
|
|
TrackingSystem->OnLateUpdateApplied_RenderThread(RHICmdList, CurrentRelativeTransform);
|
|
|
|
{
|
|
// Backwards compatibility during deprecation phase. Remove once IHeadMountedDisplay::BeginRendering_RenderThread has been removed.
|
|
PRAGMA_DISABLE_DEPRECATION_WARNINGS
|
|
auto HMD = TrackingSystem->GetHMDDevice();
|
|
if (HMD)
|
|
{
|
|
HMD->BeginRendering_RenderThread(CurrentRelativeTransform, RHICmdList, ViewFamily);
|
|
}
|
|
PRAGMA_ENABLE_DEPRECATION_WARNINGS
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void FDefaultXRCamera::SetupViewFamily(FSceneViewFamily& InViewFamily)
|
|
{
|
|
static const auto CVarAllowMotionBlurInVR = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("vr.AllowMotionBlurInVR"));
|
|
const bool AllowMotionBlur = (CVarAllowMotionBlurInVR && CVarAllowMotionBlurInVR->GetValueOnAnyThread() != 0);
|
|
const IHeadMountedDisplay* const HMD = TrackingSystem->GetHMDDevice();
|
|
InViewFamily.EngineShowFlags.MotionBlur = AllowMotionBlur;
|
|
InViewFamily.EngineShowFlags.HMDDistortion = HMD != nullptr ? HMD->GetHMDDistortionEnabled(InViewFamily.Scene->GetShadingPath()) : false;
|
|
InViewFamily.EngineShowFlags.StereoRendering = bCurrentFrameIsStereoRendering;
|
|
InViewFamily.EngineShowFlags.Rendering = HMD != nullptr ? !HMD->IsRenderingPaused() : true;
|
|
}
|
|
|
|
void FDefaultXRCamera::SetupView(FSceneViewFamily& InViewFamily, FSceneView& InView)
|
|
{
|
|
FQuat DeviceOrientation;
|
|
FVector DevicePosition;
|
|
|
|
if ( TrackingSystem->GetCurrentPose(DeviceId, DeviceOrientation, DevicePosition) )
|
|
{
|
|
InView.BaseHmdOrientation = DeviceOrientation;
|
|
InView.BaseHmdLocation = DevicePosition;
|
|
}
|
|
}
|
|
|
|
bool FDefaultXRCamera::IsActiveThisFrame_Internal(const FSceneViewExtensionContext& Context) const
|
|
{
|
|
bCurrentFrameIsStereoRendering = FHMDSceneViewExtension::IsActiveThisFrame_Internal(Context); // The current context/viewport might disallow stereo rendering. Save it so we'll use the correct value in SetupViewFamily.
|
|
return bCurrentFrameIsStereoRendering && TrackingSystem->IsHeadTrackingAllowed();
|
|
}
|