October3d55/M/PICOOpenXR/Source/PICOOpenXRMR/Private/PICO_MRFunctionLibrary.cpp

341 lines
11 KiB
C++
Raw Permalink Normal View History

2025-03-10 09:43:27 +08:00
// Copyright® 2015-2023 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.
// Unreal® Engine, Copyright 1998 2023, Epic Games, Inc. All rights reserved.
#include "PICO_MRFunctionLibrary.h"
#include "PICOOpenXRRuntimeSettings.h"
#include "PICO_SceneCapture.h"
#include "PICO_SpatialAnchor.h"
#include "PICO_SpatialMesh.h"
2025-07-21 10:22:56 +08:00
#include "ProceduralMeshComponent.h"
2025-03-10 09:43:27 +08:00
#include "Engine/Engine.h"
#include "Engine/World.h"
2025-07-21 10:22:56 +08:00
#include "Materials/Material.h"
#include "Materials/MaterialInterface.h"
2025-03-10 09:43:27 +08:00
UMRDelegateManagerPICO* UMRFunctionLibraryPICO::PICODelegateManager = nullptr;
UMRDelegateManagerPICO* UMRFunctionLibraryPICO::GetMRDelegateManagerPICO()
{
if (PICODelegateManager == nullptr)
{
PICODelegateManager = NewObject<UMRDelegateManagerPICO>();
PICODelegateManager->AddToRoot();
}
return PICODelegateManager;
}
bool UMRFunctionLibraryPICO::GetAnchorEntityUuidPICO(AActor* BoundActor, FSpatialUUIDPICO& OutAnchorUUID,EResultPICO& OutResult)
{
if (!IsValid(BoundActor) || !IsValid(BoundActor->GetWorld()))
{
return false;
}
UAnchorComponentPICO* AnchorComponent = Cast<UAnchorComponentPICO>(BoundActor->GetComponentByClass(UAnchorComponentPICO::StaticClass()));
if (IsValid(AnchorComponent) && AnchorComponent->IsAnchorValid())
{
return FSpatialAnchorExtensionPICO::GetInstance()->GetAnchorEntityUUID(AnchorComponent, OutAnchorUUID,OutResult);
}
return false;
}
bool UMRFunctionLibraryPICO::GetAnchorEntityUuidByComponentPICO(UAnchorComponentPICO* AnchorComponent, FSpatialUUIDPICO& OutAnchorUUID,EResultPICO& OutResult)
{
if (IsValid(AnchorComponent) && AnchorComponent->IsAnchorValid())
{
return FSpatialAnchorExtensionPICO::GetInstance()->GetAnchorEntityUUID(AnchorComponent, OutAnchorUUID,OutResult);
}
return false;
}
bool UMRFunctionLibraryPICO::GetSceneBoundingBox2DPICO(const FSpatialUUIDPICO& UUID, FBoundingBox2DPICO& Box2D)
{
return FSceneCaptureExtensionPICO::GetInstance()->GetSpatialSceneBoundingBox2D(UUID, Box2D);
}
bool UMRFunctionLibraryPICO::GetSceneBoundingPolygonPICO(const FSpatialUUIDPICO& UUID, TArray<FVector>& OutPolygonVertices)
{
return FSceneCaptureExtensionPICO::GetInstance()->GetSpatialSceneBoundingPolygon(UUID, OutPolygonVertices);
}
bool UMRFunctionLibraryPICO::GetSceneBoundingBox3DPICO(const FSpatialUUIDPICO& UUID, FBoundingBox3DPICO& Box3D)
{
return FSceneCaptureExtensionPICO::GetInstance()->GetSpatialSceneBoundingBox3D(UUID, Box3D);
}
bool UMRFunctionLibraryPICO::GetAnchorPoseByActorPICO(AActor* BoundActor, FTransform& OutTransform,EResultPICO& OutResult)
{
if (!IsValid(BoundActor) || !IsValid(BoundActor->GetWorld()))
{
return false;
}
UAnchorComponentPICO* AnchorComponent = Cast<UAnchorComponentPICO>(BoundActor->GetComponentByClass(UAnchorComponentPICO::StaticClass()));
if (IsValid(AnchorComponent) && AnchorComponent->IsAnchorValid())
{
return FSpatialAnchorExtensionPICO::GetInstance()->GetAnchorPose(AnchorComponent, OutTransform,OutResult);
}
return false;
}
bool UMRFunctionLibraryPICO::GetAnchorPoseByComponentPICO(UAnchorComponentPICO* AnchorComponent, FTransform& OutTransform,EResultPICO& OutResult)
{
if (IsValid(AnchorComponent) && AnchorComponent->IsAnchorValid())
{
return FSpatialAnchorExtensionPICO::GetInstance()->GetAnchorPose(AnchorComponent, OutTransform,OutResult);
}
return false;
}
AActor* UMRFunctionLibraryPICO::SpawnActorFromLoadResultPICO(UObject* WorldContext, const FAnchorLoadResultPICO& LoadResult, UClass* ActorClass)
{
UWorld* World = GEngine->GetWorldFromContextObject(WorldContext, EGetWorldErrorMode::ReturnNull);
if (!IsValid(World))
{
return nullptr;
}
FActorSpawnParameters SpawnInfo;
SpawnInfo.ObjectFlags |= RF_Transient;
AActor* AnchorActor = World->SpawnActor(ActorClass, nullptr, nullptr, SpawnInfo);
if (!IsValid(AnchorActor))
{
return nullptr;
}
UAnchorComponentPICO* AnchorComponent = Cast<UAnchorComponentPICO>(AnchorActor->GetComponentByClass(UAnchorComponentPICO::StaticClass()));
if (IsValid(AnchorComponent) && AnchorComponent->IsAnchorValid())
{
return AnchorActor;
}
if (AnchorComponent == nullptr)
{
AnchorComponent = Cast<UAnchorComponentPICO>(AnchorActor->AddComponentByClass(UAnchorComponentPICO::StaticClass(), false, FTransform::Identity, false));
}
AnchorComponent->SetAnchorHandle(LoadResult.AnchorHandle);
return AnchorActor;
}
bool UMRFunctionLibraryPICO::IsAnchorValidForActorPICO(AActor* BoundActor)
{
if (!IsValid(BoundActor))
{
return false;
}
UAnchorComponentPICO* AnchorComponent = Cast<UAnchorComponentPICO>(BoundActor->GetComponentByClass(UAnchorComponentPICO::StaticClass()));
if (IsValid(AnchorComponent) && AnchorComponent->IsAnchorValid())
{
return true;
}
return false;
}
bool UMRFunctionLibraryPICO::IsAnchorValidForComponentPICO(UAnchorComponentPICO* AnchorComponent)
{
if (IsValid(AnchorComponent) && AnchorComponent->IsAnchorValid())
{
return true;
}
return false;
}
FString UMRFunctionLibraryPICO::FromAnchorToStringPICO(const FSpatialHandlePICO& Anchor)
{
return Anchor.ToString();
}
FString UMRFunctionLibraryPICO::FromUUIDToStringPICO(const FSpatialUUIDPICO& AnchorUUID)
{
return AnchorUUID.ToString();
}
FSpatialUUIDPICO UMRFunctionLibraryPICO::FromStringToUUIDPICO(const FString& AnchorUUIDString)
{
FSpatialUUIDPICO OutAnchorUUID={};
// Static size for the max length of the string, two chars per hex digit, 16 digits.
checkf(AnchorUUIDString.Len() == 32, TEXT("'%s' is not a valid UUID"), *AnchorUUIDString);
HexToBytes(AnchorUUIDString, OutAnchorUUID.UUIDArray);
return OutAnchorUUID;
}
bool UMRFunctionLibraryPICO::CloseSpatialMeshScanningPICO(EResultPICO& OutResult)
{
return FSpatialMeshExtensionPICO::GetInstance()->StopProvider(OutResult);
}
bool UMRFunctionLibraryPICO::ChangeSpatialMeshLodSettingPICO(ESpatialMeshLodPICO SpatialMeshLod,EResultPICO& OutResult)
{
bool bResult=false;
if (FSpatialMeshExtensionPICO::GetInstance()->GetCurrentSpatialMeshLod()!=SpatialMeshLod)
{
bResult=FSpatialMeshExtensionPICO::GetInstance()->StopProvider(OutResult);
if (bResult)
{
bResult=FSpatialMeshExtensionPICO::GetInstance()->DestroyProvider(OutResult);
if (bResult)
{
FSenseDataProviderCreateInfoMeshPICO cFPICOSenseDataProviderCreateInfoMesh = {};
cFPICOSenseDataProviderCreateInfoMesh.Lod = SpatialMeshLod;
const UPICOOpenXRRuntimeSettings* Settings = GetDefault<UPICOOpenXRRuntimeSettings>();
if(Settings)
{
if (Settings->bSemanticsAlignWithTriangle)
{
cFPICOSenseDataProviderCreateInfoMesh.ConfigArray.Add(ESpatialMeshConfigPICO::Spatial_Mesh_Config_Semantic);
}
else if (Settings->bSemanticsAlignWithVertex)
{
cFPICOSenseDataProviderCreateInfoMesh.ConfigArray.Add(ESpatialMeshConfigPICO::Spatial_Mesh_Config_Semantic);
cFPICOSenseDataProviderCreateInfoMesh.ConfigArray.Add(ESpatialMeshConfigPICO::Spatial_Mesh_Config_Semantic_Align_With_Vertex);
}
}
bResult=FSpatialMeshExtensionPICO::GetInstance()->CreateProvider(cFPICOSenseDataProviderCreateInfoMesh,OutResult);
}
}
}
return bResult;
}
ESpatialMeshLodPICO UMRFunctionLibraryPICO::GetSpatialMeshLodSettingPICO()
{
return FSpatialMeshExtensionPICO::GetInstance()->GetCurrentSpatialMeshLod();
}
EMRStatePICO UMRFunctionLibraryPICO::GetSpatialMeshScanningStatePICO()
{
return FSpatialMeshExtensionPICO::GetInstance()->GetSenseDataProviderState();
}
EMRStatePICO UMRFunctionLibraryPICO::GetSpatialAnchorServiceStatePICO()
{
return FSpatialAnchorExtensionPICO::GetInstance()->GetSenseDataProviderState();
}
EMRStatePICO UMRFunctionLibraryPICO::GetSceneCaptureServiceStatePICO()
{
return FSceneCaptureExtensionPICO::GetInstance()->GetSenseDataProviderState();
}
void UMRFunctionLibraryPICO::ResetSpatialMeshInfosStatePICO()
{
FSpatialMeshExtensionPICO::GetInstance()->ClearMeshProviderBuffer();
}
bool UMRFunctionLibraryPICO::CloseSpatialAnchorServicePICO(EResultPICO& OutResult)
{
return FSpatialAnchorExtensionPICO::GetInstance()->StopProvider(OutResult);
}
bool UMRFunctionLibraryPICO::CloseSceneCaptureServicePICO(EResultPICO& OutResult)
{
return FSceneCaptureExtensionPICO::GetInstance()->StopProvider(OutResult);
}
bool UMRFunctionLibraryPICO::DestroyAnchorByComponentPICO(UAnchorComponentPICO* AnchorComponent,EResultPICO& OutResult)
{
bool bResult=false;
if (IsValid(AnchorComponent) && AnchorComponent->IsAnchorValid())
{
bResult=FSpatialAnchorExtensionPICO::GetInstance()->DestroyAnchorByHandle(AnchorComponent->GetAnchorHandle(),OutResult);
AnchorComponent->ResetAnchorHandle();
}
return bResult;
}
bool UMRFunctionLibraryPICO::DestroyAnchorByActorPICO(AActor* BoundActor,EResultPICO& OutResult)
{
bool bResult=false;
if (!IsValid(BoundActor) || !IsValid(BoundActor->GetWorld()))
{
return bResult;
}
UAnchorComponentPICO* AnchorComponent = Cast<UAnchorComponentPICO>(BoundActor->GetComponentByClass(UAnchorComponentPICO::StaticClass()));
if (IsValid(AnchorComponent) && AnchorComponent->IsAnchorValid())
{
bResult=FSpatialAnchorExtensionPICO::GetInstance()->DestroyAnchorByHandle(AnchorComponent->GetAnchorHandle(),OutResult);
AnchorComponent->ResetAnchorHandle();
}
return bResult;
}
bool UMRFunctionLibraryPICO::CreateSceneBoundingPolygonPICO(AActor* BoundActor,bool bNeverCreateCollision,bool bFlipPolygon,bool UseWireframe, const FTransform& Transform, const TArray<FVector>& BoundaryVertices,UMaterialInterface* DefaultMeshMaterial)
{
2025-07-21 10:22:56 +08:00
auto MRMeshComponent = NewObject<UProceduralMeshComponent>(BoundActor);
TArray<int32> Indices;
TArray<FVector> Normals;
TArray<FLinearColor> VertexColors;
TArray<FProcMeshTangent> Tangents;
TArray<FVector2D> UV0;
2025-03-10 09:43:27 +08:00
if (!IsValid(BoundActor)||!BoundaryVertices.Num()||!DefaultMeshMaterial)
{
return false;
}
MRMeshComponent->SetUsingAbsoluteLocation(true);
MRMeshComponent->SetUsingAbsoluteRotation(true);
MRMeshComponent->SetUsingAbsoluteScale(true);
2025-07-21 10:22:56 +08:00
if (UseWireframe&&GEngine->WireframeMaterial)
{
MRMeshComponent->SetMaterial(0, GEngine->WireframeMaterial);
}
else
2025-03-10 09:43:27 +08:00
{
MRMeshComponent->SetMaterial(0, DefaultMeshMaterial);
}
MRMeshComponent->SetupAttachment(BoundActor->GetRootComponent());
MRMeshComponent->RegisterComponent();
auto Vertices = BoundaryVertices;
const auto NumPolygons = Vertices.Num();
Indices.Reset(3 * NumPolygons);
if (bFlipPolygon)
{
for (auto Index = 0; Index < NumPolygons; ++Index)
{
Indices.Add(0);
Indices.Add((Index + 2) % NumPolygons);
Indices.Add((Index + 1) % NumPolygons);
}
}
else
{
for (auto Index = 0; Index < NumPolygons; ++Index)
{
Indices.Add(0);
Indices.Add((Index + 1) % NumPolygons);
Indices.Add((Index + 2) % NumPolygons);
}
}
2025-07-21 10:22:56 +08:00
MRMeshComponent->CreateMeshSection_LinearColor(0, Vertices, Indices, Normals, UV0, VertexColors, Tangents, !bNeverCreateCollision);
MRMeshComponent->SetWorldLocation(Transform.GetLocation());
MRMeshComponent->SetWorldRotation(Transform.GetRotation());
2025-03-10 09:43:27 +08:00
return true;
}