// 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& Primitives) { // If a scene proxy is present, cache it UPrimitiveComponent* PrimitiveComponent = dynamic_cast(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); } } class FHeadMountedDisplayModule : public IHeadMountedDisplayModule { virtual TSharedPtr< class IHeadMountedDisplay, ESPMode::ThreadSafe > CreateHeadMountedDisplay() { TSharedPtr 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(); }