Files
UnrealEngineUWP/Engine/Source/Runtime/HeadMountedDisplay/Private/HeadMountedDisplayModule.cpp
Dan Oconnor 267de41daa Copying //UE4/Dev-VR to //UE4/Dev-Main (Source: //UE4/Dev-VR @ 3231914)
#lockdown Nick.Penwarden

==========================
MAJOR FEATURES + CHANGES
==========================

Change 3060975 on 2016/07/21 by Ryan.Vance

	Integrating 3058175 from Oculus

Change 3149273 on 2016/10/03 by Keli.Hlodversson

	#jira UE-36736: Fix rendering of Canvas Tiles when in stereo mode.
	FCanvas::DrawTile batched the triangles directly instead of passing a FCanvasTileItem to FCanvas::DrawItem

Change 3150583 on 2016/10/04 by Keli.Hlodversson

	#jira UEVR-288 Minor optimization of UCameraComponent transform update when bLockToHmd is set.

	As suggested by Michael  Atkins https://udn.unrealengine.com/questions/314290/issue-with-ucameracomponent-transform-update.html

Change 3150635 on 2016/10/04 by Keli.Hlodversson

	Minor change: no need to spell out rotation, position and scale, as FTransform's default constructor initializes an identity transform

Change 3150776 on 2016/10/04 by Chad.Taylor

	Oculus layers fix where the "changed" flags were getting prematuraly cleared for quad layers before they were being processed.

Change 3152251 on 2016/10/05 by Chad.Taylor

	Oculus layers code cleanup

Change 3152834 on 2016/10/05 by Chad.Taylor

	VR splash screen update: Hooked up UVs for OculusRift and disable alpha for parity

Change 3158823 on 2016/10/11 by Chad.Taylor

	VR Loading screen placement for SteamVR and Oculus

Change 3164516 on 2016/10/17 by Ben.Marsh

	Add a build node to compile UE4Game for Windows XP, and run it in Dev-VR.

	#jira UEB-713

Change 3169683 on 2016/10/20 by Nick.Whiting

	Updating to Oculus SDK 1.9

Change 3191389 on 2016/11/09 by Ben.Marsh

	Build: Remove Windows XP build step for //UE4/Dev-VR.

	#jira UEB-716

Change 3196810 on 2016/11/14 by Jeff.Fisher

	UEVR-286 PSVR reprojection prediction time too big?
	-Fixed reprojection desync when the frame time is too short.
	-Eliminated the MorpheusReprojector class, and its thread.  ReprojectionStart calls are now made from GnmManager::EndFrame.
	-GnmManager::EndFrame is now always locked to vSync.
	-GameThreadFrame is no longer filled with the previous RenderThreadFrame, instead a separate poll of tracker data is made with a larger prediction time to fill it.
	-Prediction time was increased from RenderFrameTime * 2 to RenderFrameTime * 2.5 after examination of Sony VR Trace tool output.  In 60/120 mode this is 45ms.
	-Double buffering reprojection data to avoid race conditions between updating the reprojection data and submitting the frame.
	-Tracker compute and update are now called from a single thread and synced to the beginning of the game frame.  The timing is similar to what it was previously, but can probably be improved.
	-Added a bunch of error warnings from sony system calls.
	-Added events to visualize the vr frame sequence in RazorCPU these events will only show up when Morpheus is enabled.
	-Added commented out reprojection flags that are useful for debugging (like the one that turns reprojection off)
	-Added commented out function to call and print results from a sceHmdReprojectionDebugGetLastInfo

	#review-3193674 @nick.whiting @ryan.vance
	#jira UEVR-286

Change 3198965 on 2016/11/15 by Jeff.Fisher

	UE-38630 IsHeadMountedDisplayConnected blueprint function
	-Exposed IsHMDConnected to blueprint.
	-Made PSVR IsHMDConnected behavior match other platforms, it just means the hmd hardware is ready to use - not that we are using it.
	#review-3198949
	-With this change I was able to setup a psvr game in blueprint to start not in vr, detect that the hmd was availalbe, switch to stereo rendering, prompt the user to reconnect the hmd if they disconnected it, but switch back to 2d mode if they cancelled the reconnect dialog.
	#jira UE-38630

Change 3201341 on 2016/11/16 by patrickr.donovan

	Test content update. Replaced level script logic that attempted to move player start (which has native defined static capsule component) with level script logic that simply targets a second player start that's already in the previously-moved-to location.

Change 3202637 on 2016/11/17 by Jeff.Fisher

	Redundant GetViewFrustumBounds call.
	-Removed redundant call to GetViewFrustumBounds in MorpheusHMD.cpp.  It is called inside View.UpdateViewMatrix() just above with the same results.  And it actually does a fair bit of work.
	-This problem and fix was actually found by Ryan.Vance, but it was convenient for me to test and submit it.

Change 3205949 on 2016/11/21 by Jeff.Fisher

	UE-VR UEVR-329 Morpheus: need to handle camera disconnection.
	UEVR-338 PSVR upside down camera handling
	-PS4Tracker now detects camera disconnection and pops up the appropriate system dialog.
	-Minor fixes for sony library load/initialization warnings.
	-Added a timeout to PS4Tracker::Synchronize, so we at least don't hang if the camera is upside down.
	-hmdSetupDialog and camera disconnect dialogs will now not pop up until no other sceCommonDialogs are up.
	#review-3203097
	#jira UEVR-329

Change 3213849 on 2016/11/29 by Nick.Whiting

	Merging //UE4/Dev-Main to Dev-VR (//UE4/Dev-VR)

Change 3214103 on 2016/11/29 by Nick.Whiting

	Fixes for IWYU update for OnlineSubsystemOculus

Change 3222029 on 2016/12/05 by Ryan.Vance

	We need to do a full frame clear when using a hmd mask and a post processing material.
	This is re-implementing the 3212242 from 4.14.1

Change 3223780 on 2016/12/06 by Cody.Albert

	Removing MinimalAPI specifier from SteamVRChaperoneComponent

Change 3228296 on 2016/12/08 by Nick.Whiting

	Updating Oculus SDKs:  Oculus PC SDK 1.10.0, Mobile SDK 1.0.3, Audio SDK 1.0.2, and Platform SDK 1.10.0

Change 3228298 on 2016/12/08 by Nick.Whiting

	Fix for late-latching oculus touch update.  was not returning that it had data

Change 3228319 on 2016/12/08 by Jeff.Fisher

	UEVR-402 Implement the PSVR Aim (Weird Gun Controller)
	-Created AimController plugin to support the psvr aim controller space gun thingy.
	-The sony api for this controller is the same as the api for the DS4, but our DS4 implementation has a pretty deep assumption that there will only be one gamepad per player.
	-This is basically a copy of the MoveController plugin, with some of the code from PS4Controllers.h to make the buttons and force feedback work.
	-Currently the gun buttons are just mapped as gamepad buttons.  Not entirely sure that is best, but it would be straightforward (if a bit tedious) for a licencee to give them unique mappings.  Having two players play with the gamepad and gun associated with a single PS4 user is, I beleive, a trc problem, so it may actually be ok to make this a bit hard to do.
	#jira UEVR-402
	#review-3227685 @nick.whiting @keli.hlodversson

Change 3228321 on 2016/12/08 by Jeff.Fisher

	UEVR-402 Implement the PSVR Aim (Weird Gun Controller)
	-qagame vr-motioncontrollers changes to test the gun controller
	-in DS4 mode you now also have a gun controller, and can test all the buttons on the two controllers and test forcefeedback/haptics (enable with E, face buttons make things vibrate)
	#jira UEVR-402

Change 3229148 on 2016/12/09 by Jeff.Fisher

	Fixed build breaks related to OCULUS macros.

Change 3229867 on 2016/12/09 by Jeff.Fisher

	UEVR-402 Implement the PSVR Aim (Weird Gun Controller)
	-Fixed assert if you don't have the aim controller connected.  The IsControllerReady function was not implemented correctly.

Change 3230089 on 2016/12/09 by Ryan.Vance

	Implementing monoscopic far field rendering for mobile VR.

Change 3230352 on 2016/12/11 by Keli.Hlodversson

	Merging //UE4/Main to Dev-VR (//UE4/Dev-VR)

Change 3230357 on 2016/12/11 by Keli.Hlodversson

	Fix after merge from Main

Change 3230365 on 2016/12/11 by Keli.Hlodversson

	Workaround an assert after merge. DoEnableStereo now requires a valid Frame when run. Keep around the previous frame in OnBeginFrame to avoid the crash.
	Not sure if this is the correct solution, but it does makes OculusRift run again after the merge from main.

Change 3231165 on 2016/12/12 by Keli.Hlodversson

	Back out changelist 3230365

Change 3231191 on 2016/12/12 by Keli.Hlodversson

	Revert to previous version of oculus' IsStereoEnabled
	We must return false when there is no current frame as otherwise calling DoEnableStereo will cause an check assert in FOculusRiftHMD::SetupView
	#jira UE-39631

Change 3231342 on 2016/12/12 by Ryan.Vance

	Cleaning up init order and static analysis warnings.
	#jira UE-39644, UE-39642, UE-39645

Change 3231811 on 2016/12/12 by Ryan.Vance

	#jira UE-39645
	Static analysis appeasement

#rb None

[CL 3231940 by Dan Oconnor in Main branch]
2016-12-12 20:46:42 -05:00

160 lines
4.9 KiB
C++

// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
#include "CoreMinimal.h"
#include "HAL/IConsoleManager.h"
#include "Misc/App.h"
#include "Modules/ModuleManager.h"
#include "Templates/Casts.h"
#include "EngineGlobals.h"
#include "PrimitiveSceneProxy.h"
#include "Components/PrimitiveComponent.h"
#include "Engine/Engine.h"
#include "IHeadMountedDisplayModule.h"
#include "IHeadMountedDisplay.h"
#include "PrimitiveSceneInfo.h"
void IHeadMountedDisplay::GatherLateUpdatePrimitives(USceneComponent* Component, TArray<LateUpdatePrimitiveInfo>& Primitives)
{
// If a scene proxy is present, cache it
UPrimitiveComponent* PrimitiveComponent = dynamic_cast<UPrimitiveComponent*>(Component);
if (PrimitiveComponent && PrimitiveComponent->SceneProxy)
{
FPrimitiveSceneInfo* PrimitiveSceneInfo = PrimitiveComponent->SceneProxy->GetPrimitiveSceneInfo();
if (PrimitiveSceneInfo)
{
LateUpdatePrimitiveInfo PrimitiveInfo;
PrimitiveInfo.IndexAddress = PrimitiveSceneInfo->GetIndexAddress();
PrimitiveInfo.SceneInfo = PrimitiveSceneInfo;
Primitives.Add(PrimitiveInfo);
}
}
// Gather children proxies
const int32 ChildCount = Component->GetNumChildrenComponents();
for (int32 ChildIndex = 0; ChildIndex < ChildCount; ++ChildIndex)
{
USceneComponent* ChildComponent = Component->GetChildComponent(ChildIndex);
if (!ChildComponent)
{
continue;
}
GatherLateUpdatePrimitives(ChildComponent, Primitives);
}
}
/**
* HMD device console vars
*/
static TAutoConsoleVariable<int32> CVarHiddenAreaMask(
TEXT("vr.HiddenAreaMask"),
1,
TEXT("0 to disable hidden area mask, 1 to enable."),
ECVF_Scalability | ECVF_RenderThreadSafe);
static TAutoConsoleVariable<int32> CVarMonoscopicFarField(
TEXT("vr.MonoscopicFarField"),
0,
TEXT("Experimental, mobile only")
TEXT(", 0 to disable (default), 1 to enable")
TEXT(", 2 stereo near field only")
TEXT(", 3 stereo near field with far field pixel depth test disabled")
TEXT(", 4 mono far field only"),
ECVF_Scalability | ECVF_RenderThreadSafe);
static void SetTrackingOrigin(const TArray<FString>& Args)
{
int Origin = 0;
if (Args.Num())
{
Origin = FCString::Atoi(*Args[0]);
if (GEngine && GEngine->HMDDevice.IsValid())
{
GEngine->HMDDevice->SetTrackingOrigin(EHMDTrackingOrigin::Type(Origin));
}
}
else
{
if (GEngine && GEngine->HMDDevice.IsValid())
{
Origin = GEngine->HMDDevice->GetTrackingOrigin();
}
if (GLog)
{
GLog->Logf(ELogVerbosity::Display, TEXT("Tracking orgin is set to %d"), Origin);
}
}
}
static FAutoConsoleCommand CTrackingOriginCmd(
TEXT("vr.SetTrackingOrigin"),
TEXT("0 - tracking origin is at the floor, 1 - tracking origin is at the eyes."),
FConsoleCommandWithArgsDelegate::CreateStatic(SetTrackingOrigin));
class FHeadMountedDisplayModule : public IHeadMountedDisplayModule
{
virtual TSharedPtr< class IHeadMountedDisplay, ESPMode::ThreadSafe > CreateHeadMountedDisplay()
{
TSharedPtr<IHeadMountedDisplay, ESPMode::ThreadSafe> DummyVal = NULL;
return DummyVal;
}
FString GetModuleKeyName() const
{
return FString(TEXT("Default"));
}
};
IMPLEMENT_MODULE( FHeadMountedDisplayModule, HeadMountedDisplay );
IHeadMountedDisplay::IHeadMountedDisplay()
{
LateUpdateGameWriteIndex = LateUpdateRenderReadIndex = 0;
}
void IHeadMountedDisplay::SetupLateUpdate(const FTransform& ParentToWorld, USceneComponent* Component)
{
LateUpdateParentToWorld = ParentToWorld;
LateUpdatePrimitives[LateUpdateGameWriteIndex].Reset();
GatherLateUpdatePrimitives(Component, LateUpdatePrimitives[LateUpdateGameWriteIndex]);
LateUpdateGameWriteIndex = (LateUpdateGameWriteIndex + 1) % 2;
}
void IHeadMountedDisplay::ApplyLateUpdate(FSceneInterface* Scene, const FTransform& OldRelativeTransform, const FTransform& NewRelativeTransform)
{
if (!LateUpdatePrimitives[LateUpdateRenderReadIndex].Num())
{
return;
}
const FTransform OldCameraTransform = OldRelativeTransform * LateUpdateParentToWorld;
const FTransform NewCameraTransform = NewRelativeTransform * LateUpdateParentToWorld;
const FMatrix LateUpdateTransform = (OldCameraTransform.Inverse() * NewCameraTransform).ToMatrixWithScale();
// Apply delta to the affected scene proxies
for (auto PrimitiveInfo : LateUpdatePrimitives[LateUpdateRenderReadIndex])
{
FPrimitiveSceneInfo* RetrievedSceneInfo = Scene->GetPrimitiveSceneInfo(*PrimitiveInfo.IndexAddress);
FPrimitiveSceneInfo* CachedSceneInfo = PrimitiveInfo.SceneInfo;
// If the retrieved scene info is different than our cached scene info then the primitive was removed from the scene
if (CachedSceneInfo == RetrievedSceneInfo && CachedSceneInfo->Proxy)
{
CachedSceneInfo->Proxy->ApplyLateUpdateTransform(LateUpdateTransform);
}
}
LateUpdatePrimitives[LateUpdateRenderReadIndex].Reset();
LateUpdateRenderReadIndex = (LateUpdateRenderReadIndex + 1) % 2;
}
bool IHeadMountedDisplay::DoesAppUseVRFocus() const
{
return FApp::UseVRFocus();
}
bool IHeadMountedDisplay::DoesAppHaveVRFocus() const
{
return FApp::HasVRFocus();
}