// 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 MaskedMaterialRef(TEXT("/Script/Engine.Material'/PICOOpenXR/PICOOpenXR/Materials/M_PokeHole.M_PokeHole'")); OverrideMaterial = MaskedMaterialRef.Object; } template T* FindComponentByNamePICO(AActor* Actor, const FName& ComponentName) { if (IsValid(Actor) && (ComponentName != NAME_None)) { TArray ComponentsOfType; Actor->GetComponents(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(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 VerticePos; TArray TriangleIndics; TArray Normals; TArray TexUV; TArray VertexColors; TArray 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& 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& Vertices, TArray& Triangles, TArray& UV0) { if (InStereoLayer == nullptr) { return; } if(Shape->IsA()) { 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()) { float Arc, Radius, Height; const UStereoLayerShapeCylinder* CylinderProps = Cast(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()) { 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); } }