October3d55/M/PICOOpenXR/Source/PICOOpenXRHMD/Private/PICO_PokeHoleComponent.cpp

229 lines
7.1 KiB
C++

// Fill out your copyright notice in the Description page of Project Settings.
#include "PICO_PokeHoleComponent.h"
#include "Engine/Texture.h"
#include "UObject/ConstructorHelpers.h"
#include "Materials/MaterialInterface.h"
#include "TextureResource.h"
UPokeHoleComponentPICO::UPokeHoleComponentPICO(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
, TargetStereoLayerComponentName(NAME_None)
{
PrimaryComponentTick.bCanEverTick = true;
PrimaryComponentTick.bStartWithTickEnabled = true;
static ConstructorHelpers::FObjectFinder<UMaterialInterface> MaskedMaterialRef(TEXT("/Script/Engine.Material'/PICOOpenXR/PICOOpenXR/Materials/M_PokeHole.M_PokeHole'"));
OverrideMaterial = MaskedMaterialRef.Object;
}
template <typename T>
T* FindComponentByNamePICO(AActor* Actor, const FName& ComponentName)
{
if (IsValid(Actor) && (ComponentName != NAME_None))
{
TArray<T*> ComponentsOfType;
Actor->GetComponents<T>(ComponentsOfType);
T** FoundComponent = ComponentsOfType.FindByPredicate([Name = ComponentName.ToString()](T* Component) { return Component->GetName().Equals(Name); });
if (FoundComponent != nullptr)
{
return *FoundComponent;
}
}
return nullptr;
}
void UPokeHoleComponentPICO::OnRegister()
{
Super::OnRegister();
ClearAllMeshSections();
if (TargetStereoLayerComponentName != NAME_None)
{
StereoLayer = FindComponentByNamePICO<UStereoLayerComponent>(GetOwner(), TargetStereoLayerComponentName);
}
if (StereoLayer == nullptr)
{
SetComponentTickEnabled(false);
}
else
{
bLastQuadPreserveTextureRatio = StereoLayer->bQuadPreserveTextureRatio;
}
}
void UPokeHoleComponentPICO::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
if (StereoLayer == nullptr)
{
return;
}
bool bRatioChanged = StereoLayer->bQuadPreserveTextureRatio != bLastQuadPreserveTextureRatio;
if (bRatioChanged)
{
bLastQuadPreserveTextureRatio = StereoLayer->bQuadPreserveTextureRatio;
ClearAllMeshSections();
}
if (StereoLayer->bSupportsDepth && GetNumSections() < 1)
{
TArray<FVector> VerticePos;
TArray<int32> TriangleIndics;
TArray<FVector> Normals;
TArray<FVector2D> TexUV;
TArray<FLinearColor> VertexColors;
TArray<FProcMeshTangent> Tangents;
CreatePokeHoleMesh(StereoLayer, VerticePos, TriangleIndics, TexUV);
CreateMeshSection_LinearColor(0, VerticePos, TriangleIndics, Normals, TexUV, VertexColors, Tangents, false);
if (OverrideMaterial)
{
SetMaterial(0, OverrideMaterial);
}
}
else if (!StereoLayer->bSupportsDepth && GetNumSections() > 0)
{
ClearAllMeshSections();
}
SetWorldTransform(StereoLayer->GetComponentTransform());
}
void UPokeHoleComponentPICO::OnUnregister()
{
Super::OnUnregister();
ClearAllMeshSections();
}
static void AddFaceIndices(const int v0, const int v1, const int v2, const int v3, TArray<int32>& Triangles, bool inverse)
{
if (inverse)
{
Triangles.Add(v0);
Triangles.Add(v2);
Triangles.Add(v1);
Triangles.Add(v0);
Triangles.Add(v3);
Triangles.Add(v2);
}
else
{
Triangles.Add(v0);
Triangles.Add(v1);
Triangles.Add(v2);
Triangles.Add(v0);
Triangles.Add(v2);
Triangles.Add(v3);
}
}
void UPokeHoleComponentPICO::CreatePokeHoleMesh(UStereoLayerComponent* InStereoLayer, TArray<FVector>& Vertices, TArray<int32>& Triangles, TArray<FVector2D>& UV0)
{
if (InStereoLayer == nullptr)
{
return;
}
if(Shape->IsA<UStereoLayerShapeQuad>())
{
FIntPoint TexSize = InStereoLayer->GetTexture() != nullptr ? InStereoLayer->GetTexture()->GetResource()->TextureRHI->GetTexture2D()->GetSizeXY() : FIntPoint(0, 0);
float AspectRatio = TexSize.X ? (float)TexSize.Y / (float)TexSize.X : 3.0f / 4.0f;
float QuadSizeX = InStereoLayer->GetQuadSize().X;
float QuadSizeY = InStereoLayer->bQuadPreserveTextureRatio ? InStereoLayer->GetQuadSize().X * AspectRatio : InStereoLayer->GetQuadSize().Y;
Vertices.Init(FVector::ZeroVector, 4);
Vertices[0] = FVector(0.0, -QuadSizeX / 2, -QuadSizeY / 2) * QuadScale;
Vertices[1] = FVector(0.0, QuadSizeX / 2, -QuadSizeY / 2) * QuadScale;
Vertices[2] = FVector(0.0, QuadSizeX / 2, QuadSizeY / 2) * QuadScale;
Vertices[3] = FVector(0.0, -QuadSizeX / 2, QuadSizeY / 2) * QuadScale;
UV0.Init(FVector2D::ZeroVector, 4);
UV0[0] = FVector2D(0, 1);
UV0[1] = FVector2D(1, 1);
UV0[2] = FVector2D(1, 0);
UV0[3] = FVector2D(0, 0);
Triangles.Reserve(6);
AddFaceIndices(0, 1, 2, 3, Triangles, false);
}
else if (Shape->IsA<UStereoLayerShapeCylinder>())
{
float Arc, Radius, Height;
const UStereoLayerShapeCylinder* CylinderProps = Cast<UStereoLayerShapeCylinder>(Shape);
Arc = CylinderProps->OverlayArc;
Radius = CylinderProps->Radius;
Height = CylinderProps->Height;
FIntPoint TexSize = InStereoLayer->GetTexture() != nullptr ? InStereoLayer->GetTexture()->GetResource()->TextureRHI->GetTexture2D()->GetSizeXY() : FIntPoint(0, 0);
float AspectRatio = TexSize.X ? (float)TexSize.Y / (float)TexSize.X : 3.0f / 4.0f;
float CylinderHeight = InStereoLayer->bQuadPreserveTextureRatio ? Arc * AspectRatio : Height;
const FVector XAxis = FVector(1, 0, 0);
const FVector YAxis = FVector(0, 1, 0);
const FVector HalfHeight = FVector(0, 0, CylinderHeight / 2);
const float ArcAngle = Arc / Radius;
const int Sides = (int)((ArcAngle * 180) / (PI * 5));
Vertices.Init(FVector::ZeroVector, 2 * (Sides + 1));
UV0.Init(FVector2D::ZeroVector, 2 * (Sides + 1));
Triangles.Init(0, Sides * 6);
float CurrentAngle = -ArcAngle / 2;
const float AngleStep = ArcAngle / Sides;
for (int Side = 0; Side < Sides + 1; Side++)
{
FVector MidVertex = Radius * (FMath::Cos(CurrentAngle) * XAxis + FMath::Sin(CurrentAngle) * YAxis);
Vertices[2 * Side] = (MidVertex - HalfHeight) * CylinderScale;
Vertices[(2 * Side) + 1] = (MidVertex + HalfHeight) * CylinderScale;
UV0[2 * Side] = FVector2D((Side / (float)Sides), 1);
UV0[(2 * Side) + 1] = FVector2D((Side / (float)Sides), 0);
CurrentAngle += AngleStep;
if (Side < Sides)
{
Triangles[6 * Side + 0] = 2 * Side;
Triangles[6 * Side + 2] = 2 * Side + 1;
Triangles[6 * Side + 1] = 2 * (Side + 1) + 1;
Triangles[6 * Side + 3] = 2 * Side;
Triangles[6 * Side + 5] = 2 * (Side + 1) + 1;
Triangles[6 * Side + 4] = 2 * (Side + 1);
}
}
}
else if (Shape->IsA<UStereoLayerShapeCubemap>())
{
Vertices.Init(FVector::ZeroVector, 8);
Vertices[0] = FVector(-1.0, -1.0, -1.0) * CubemapScale;
Vertices[1] = FVector(-1.0, -1.0, 1.0) * CubemapScale;
Vertices[2] = FVector(-1.0, 1.0, -1.0) * CubemapScale;
Vertices[3] = FVector(-1.0, 1.0, 1.0) * CubemapScale;
Vertices[4] = FVector(1.0, -1.0, -1.0) * CubemapScale;
Vertices[5] = FVector(1.0, -1.0, 1.0) * CubemapScale;
Vertices[6] = FVector(1.0, 1.0, -1.0) * CubemapScale;
Vertices[7] = FVector(1.0, 1.0, 1.0) * CubemapScale;
Triangles.Reserve(24);
AddFaceIndices(0, 1, 3, 2, Triangles, false);
AddFaceIndices(4, 5, 7, 6, Triangles, true);
AddFaceIndices(0, 1, 5, 4, Triangles, true);
AddFaceIndices(2, 3, 7, 6, Triangles, false);
AddFaceIndices(0, 2, 6, 4, Triangles, false);
AddFaceIndices(1, 3, 7, 5, Triangles, true);
}
}