268 lines
9.4 KiB
C++
268 lines
9.4 KiB
C++
// Copyright PICO Technology Co., Ltd. All rights reserved.
|
|
// This plugin incorporates portions of the Unreal® Engine. Unreal® is a trademark or registered trademark of Epic Games, Inc. in the United States of America and elsewhere.
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
#include "ProceduralMeshComponent.h"
|
|
#include "IStereoLayers.h"
|
|
#include "PXR_HMDRenderBridge.h"
|
|
#include "XRSwapChain.h"
|
|
#include "GameFramework/PlayerController.h"
|
|
#include "PXR_PluginWrapper.h"
|
|
#include "Components/StereoLayerComponent.h"
|
|
#include "PXR_HMDSettings.h"
|
|
#include "PXR_StereoLayer.generated.h"
|
|
|
|
class FDelayDeleteLayerManager;
|
|
class FPXRGameFrame;
|
|
|
|
class FPxrLayer : public TSharedFromThis<FPxrLayer, ESPMode::ThreadSafe>
|
|
{
|
|
public:
|
|
FPxrLayer(uint32 ID, uint32 InPxrLayerId, FDelayDeleteLayerManager* InDelayDeletion);
|
|
~FPxrLayer();
|
|
|
|
protected:
|
|
uint32 ID;
|
|
uint32 PxrLayerId;
|
|
private:
|
|
FDelayDeleteLayerManager* DelayDeletion;
|
|
};
|
|
|
|
typedef TSharedPtr<FPxrLayer, ESPMode::ThreadSafe> FPxrLayerPtr;
|
|
|
|
class FPICOXRStereoLayer : public TSharedFromThis<FPICOXRStereoLayer, ESPMode::ThreadSafe>
|
|
{
|
|
public:
|
|
FPICOXRStereoLayer(FPICOXRHMD* InHMDDevice,uint32 InPXRLayerId, const IStereoLayers::FLayerDesc& InLayerDesc);
|
|
FPICOXRStereoLayer(const FPICOXRStereoLayer& InPXRLayer);
|
|
~FPICOXRStereoLayer();
|
|
|
|
TSharedPtr<FPICOXRStereoLayer, ESPMode::ThreadSafe> CloneMyself() const;
|
|
void SetPXRLayerDesc(const IStereoLayers::FLayerDesc& InDesc);
|
|
const IStereoLayers::FLayerDesc& GetPXRLayerDesc() const { return LayerDesc; }
|
|
const uint32& GetID()const{return ID;}
|
|
|
|
bool IsLayerSupportDepth() { return (LayerDesc.Flags & IStereoLayers::LAYER_FLAG_SUPPORT_DEPTH) != 0; }
|
|
void ManageUnderlayComponent(bool bRatioChanged);
|
|
void CreateUnderlayMesh(TArray<FVector>& VerticePos, TArray<int32>& TriangleIndics, TArray<FVector2D>& TexUV);
|
|
|
|
const FXRSwapChainPtr& GetSwapChain() const { return SwapChain; }
|
|
const FXRSwapChainPtr& GetLeftSwapChain() const { return LeftSwapChain; }
|
|
const FXRSwapChainPtr& GetFoveationSwapChain() const { return FoveationSwapChain; }
|
|
#ifdef PICO_CUSTOM_ENGINE
|
|
const FXRSwapChainPtr& GetMotionVectorSwapChain() const { return MotionVectorSwapChain; }
|
|
const FXRSwapChainPtr& GetMotionVectorDepthSwapChain() const { return MotionVectorDepthSwapChain; }
|
|
#endif
|
|
void IncrementSwapChainIndex_RHIThread(FPICOXRRenderBridge* RenderBridge);
|
|
const void SubmitLayer_RHIThread(const FGameSettings* Settings, const FPXRGameFrame* Frame);
|
|
int32 GetShapeType();
|
|
void SetEyeLayerDesc(uint32 SizeX, uint32 SizeY, uint32 ArraySize, uint32 NumMips, uint32 NumSamples, FString RHIString,bool EnableSubSampled);
|
|
void PXRLayersCopy_RenderThread(FPICOXRRenderBridge* RenderBridge, FRHICommandListImmediate& RHICmdList);
|
|
void MarkTextureForUpdate(bool bUpdate = true) { bTextureNeedUpdate = bUpdate; }
|
|
bool InitPXRLayer_RenderThread(const FGameSettings* Settings, FPICOXRRenderBridge* CustomPresent, FDelayDeleteLayerManager* DelayDeletion, FRHICommandListImmediate& RHICmdList, const FPICOXRStereoLayer* InLayer = nullptr);
|
|
bool IfCanReuseLayers(const FPICOXRStereoLayer* InLayer) const;
|
|
void ReleaseResources_RHIThread();
|
|
bool IsVisible() { return (LayerDesc.Flags & IStereoLayers::LAYER_FLAG_HIDDEN) == 0; }
|
|
void DestroyUnderlayMesh();
|
|
bool bSplashLayer;
|
|
bool bSplashBlackProjectionLayer;
|
|
bool bMRCLayer;
|
|
bool bNeedsTexSrgbCreate;
|
|
void SetTrackingMode(PxrTrackingModeFlags mode) { TrackingMode = mode; }
|
|
|
|
#ifdef PICO_CUSTOM_ENGINE
|
|
bool bEnableEyeTrackingFoveationRendering;
|
|
#endif
|
|
|
|
protected:
|
|
FVector GetLayerLocation() const { return LayerDesc.Transform.GetLocation(); };
|
|
FQuat GetLayerOrientation() const { return LayerDesc.Transform.Rotator().Quaternion(); };
|
|
FVector GetLayerScale() const { return LayerDesc.Transform.GetScale3D(); };
|
|
FPICOXRHMD* HMDDevice;
|
|
uint32 ID;
|
|
uint32 PxrLayerID;
|
|
static uint32 PxrLayerIDCounter;
|
|
IStereoLayers::FLayerDesc LayerDesc;
|
|
FXRSwapChainPtr SwapChain;
|
|
FXRSwapChainPtr LeftSwapChain;
|
|
FXRSwapChainPtr FoveationSwapChain;
|
|
#ifdef PICO_CUSTOM_ENGINE
|
|
FXRSwapChainPtr MotionVectorSwapChain;
|
|
FXRSwapChainPtr MotionVectorDepthSwapChain;
|
|
#endif
|
|
bool bTextureNeedUpdate;
|
|
UProceduralMeshComponent* UnderlayMeshComponent;
|
|
AActor* UnderlayActor;
|
|
FPxrLayerPtr PxrLayer;
|
|
PxrLayerParam PxrLayerCreateParam;
|
|
PxrTrackingModeFlags TrackingMode;
|
|
};
|
|
|
|
typedef TSharedPtr<FPICOXRStereoLayer, ESPMode::ThreadSafe> FPICOLayerPtr;
|
|
|
|
struct FPICOLayerPtr_SortByPriority
|
|
{
|
|
FORCEINLINE bool operator()(const FPICOLayerPtr&A,const FPICOLayerPtr&B)const
|
|
{
|
|
int32 nPriorityA = A->GetPXRLayerDesc().Priority;
|
|
int32 nPriorityB = B->GetPXRLayerDesc().Priority;
|
|
if (nPriorityA < nPriorityB)
|
|
{
|
|
return true;
|
|
}
|
|
else if (nPriorityA > nPriorityB)
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
return A->GetID() < B->GetID();
|
|
}
|
|
}
|
|
};
|
|
|
|
struct FPICOLayerPtr_SortById
|
|
{
|
|
FORCEINLINE bool operator()(const FPICOLayerPtr& A, const FPICOLayerPtr& B) const
|
|
{
|
|
return A->GetID() < B->GetID();
|
|
}
|
|
};
|
|
|
|
struct FLayerPtr_CompareByAll
|
|
{
|
|
FORCEINLINE bool operator()(const FPICOLayerPtr& A, const FPICOLayerPtr& B) const
|
|
{
|
|
int32 OrderA = (A->GetID() == 0) ? 0 : A->IsLayerSupportDepth() ? -1 : 1;
|
|
int32 OrderB = (B->GetID() == 0) ? 0 : B->IsLayerSupportDepth() ? -1 : 1;
|
|
|
|
if (OrderA != OrderB)
|
|
{
|
|
return OrderA < OrderB;
|
|
}
|
|
|
|
const IStereoLayers::FLayerDesc& DescA = A->GetPXRLayerDesc();
|
|
const IStereoLayers::FLayerDesc& DescB = B->GetPXRLayerDesc();
|
|
|
|
bool bFaceLockedA = (DescA.PositionType == IStereoLayers::ELayerType::FaceLocked);
|
|
bool bFaceLockedB = (DescB.PositionType == IStereoLayers::ELayerType::FaceLocked);
|
|
|
|
if (bFaceLockedA != bFaceLockedB)
|
|
{
|
|
return bFaceLockedB;
|
|
}
|
|
|
|
if (DescA.Priority != DescB.Priority)
|
|
{
|
|
return DescA.Priority < DescB.Priority;
|
|
}
|
|
|
|
return A->GetID() < B->GetID();
|
|
}
|
|
};
|
|
|
|
UENUM()
|
|
enum class ESubtypeEAC : uint8
|
|
{
|
|
EAC180 UMETA(ToolTip = "180° degree EAC"),
|
|
EAC360 UMETA(ToolTip = "360° degree EAC")
|
|
};
|
|
|
|
/** Class describing settings for a EAC (equiangular cubemap) layer shape. */
|
|
class PICOXRHMD_API FEACLayer : public IStereoLayerShape
|
|
{
|
|
public:
|
|
static const FName ShapeName;
|
|
virtual FName GetShapeName() override { return ShapeName; }
|
|
virtual IStereoLayerShape* Clone() const override { return new FEACLayer(*this); }
|
|
|
|
public:
|
|
/** Add additional shape parameters here. See "StereoLayerShapes.h" for reference. */
|
|
|
|
FEACLayer() {}
|
|
FEACLayer(float InScale, float InOverlapFactor
|
|
, ESubtypeEAC InSubtype
|
|
, const FBox2D& InLeftUVRect
|
|
, const FBox2D& InRightUVRect
|
|
, const FVector& InOffset
|
|
, const FRotator& InOffsetRot)
|
|
: Scale(InScale),OverlapFactor(InOverlapFactor)
|
|
, Subtype(InSubtype)
|
|
{
|
|
UVRect[0] = InLeftUVRect;
|
|
UVRect[1] = InRightUVRect;
|
|
Offset[0] = Offset[1] = InOffset;
|
|
OffsetRot[0] = OffsetRot[1] = InOffsetRot.Quaternion();
|
|
}
|
|
|
|
uint32_t GetModelType() const;
|
|
float Scale;
|
|
float OverlapFactor;
|
|
ESubtypeEAC Subtype;
|
|
FBox2D UVRect[2];
|
|
FVector Offset[2];
|
|
FQuat OffsetRot[2];
|
|
};
|
|
|
|
/** Class describing settings for a stereo layer shaped as an EAC (equiangular cubemap).
|
|
This is a custom shape supported by the PicoXR Plugin. */
|
|
UCLASS(meta = (DisplayName = "EAC Layer"))
|
|
class PICOXRHMD_API UStereoLayerShapeEAC : public UStereoLayerShape
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
public:
|
|
UStereoLayerShapeEAC() :
|
|
Scale(10000),
|
|
OverlapFactor(1.0f),
|
|
Subtype(ESubtypeEAC::EAC360),
|
|
LeftUVRect(FVector2D(0), FVector2D(1)),
|
|
RightUVRect(FVector2D(0), FVector2D(1))
|
|
{}
|
|
|
|
/** Size of the cube mesh used for rendering the EAC. Used when "Support Depth" = true. */
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, export, Category = "EAC Properties", DisplayName = "Mesh World Scale")
|
|
float Scale;
|
|
|
|
/** The UV rect sampled for each face will be resized by a factor of: [1/OverlapFactor].
|
|
Modifying this value can blend seams at the edges of the cubemap. */
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, export, Category = "EAC Properties")
|
|
float OverlapFactor;
|
|
|
|
/** Specific EAC format to use. */
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, export, Category = "EAC Properties")
|
|
ESubtypeEAC Subtype;
|
|
|
|
/** Left source texture UVRect, specifying portion of input texture corresponding to left eye. */
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, export, Category = "EAC Properties", DisplayName = "Left UV Rect")
|
|
FBox2D LeftUVRect;
|
|
|
|
/** Right source texture UVRect, specifying portion of input texture corresponding to right eye. */
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, export, Category = "EAC Properties", DisplayName = "Right UV Rect")
|
|
FBox2D RightUVRect;
|
|
|
|
/** The position of the camera matrix of the EAC Texture.
|
|
This position will be inverted when sampling from the EAC Texture. */
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, export, Category = "EAC Properties",
|
|
meta = (EditCondition = "Subtype==ESubtypeEAC::EAC360", EditConditionHides))
|
|
FVector Offset;
|
|
|
|
/** The rotation of the camera matrix of the EAC Texture.
|
|
This rotation will be inverted when sampling from the EAC Texture. */
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, export, Category = "EAC Properties",
|
|
meta = (EditCondition = "Subtype==ESubtypeEAC::EAC360", EditConditionHides))
|
|
FRotator OffsetRot;
|
|
|
|
UFUNCTION(BlueprintCallable, Category = "Components|Stereo Layer")
|
|
void SetOverlapFactor(float InOverlapFactor);
|
|
|
|
UFUNCTION(BlueprintCallable, Category = "Components|Stereo Layer")
|
|
void SetSubtype(ESubtypeEAC InSubtype);
|
|
|
|
virtual void ApplyShape(IStereoLayers::FLayerDesc& LayerDesc) override;
|
|
|
|
#if WITH_EDITOR
|
|
virtual void DrawShapeVisualization(const class FSceneView* View, class FPrimitiveDrawInterface* PDI) override;
|
|
#endif
|
|
}; |