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

818 lines
31 KiB
C++

// Copyright 2023 PICO Inc. All Rights Reserved.
#include "PICO_MR.h"
#include "OpenXRCore.h"
#include "IOpenXRHMDModule.h"
#include "IXRTrackingSystem.h"
#include "Engine/Engine.h"
#include "PICO_MRFunctionLibrary.h"
#include "PICO_MRTypes.h"
#include "PICO_SceneCapture.h"
#include "PICO_SpatialAnchor.h"
#include "PICO_SpatialMesh.h"
FSpatialSensingExtensionPICO::FSpatialSensingExtensionPICO(): CurrentDisplayTime(0), GlobalUUIDCount(0)
{
}
void FSpatialSensingExtensionPICO::Register()
{
RegisterOpenXRExtensionModularFeature();
}
void FSpatialSensingExtensionPICO::Unregister()
{
UnregisterOpenXRExtensionModularFeature();
}
void FSpatialSensingExtensionPICO::OnEvent(XrSession InSession, const XrEventDataBaseHeader* InHeader)
{
const XrEventDataBuffer* EventDataBuffer = reinterpret_cast<const XrEventDataBuffer*>(InHeader);
if (EventDataBuffer == nullptr)
{
return;
}
PollEvent(EventDataBuffer);
}
bool FSpatialSensingExtensionPICO::GetOptionalExtensions(TArray<const ANSICHAR*>& OutExtensions)
{
OutExtensions.Add("XR_PICO_spatial_sensing");
OutExtensions.Add("XR_EXT_future");
return true;
}
void FSpatialSensingExtensionPICO::PostGetSystem(XrInstance InInstance, XrSystemId InSystem)
{
bSupportsSpatialSensingEXT = IOpenXRHMDModule::Get().IsExtensionEnabled(XR_PICO_SPATIAL_SENSING_EXTENSION_NAME);
Instance =InInstance;
UE_LOG(LogMRPICO, Verbose, TEXT("bSupportsSpatialSensingEXT:%d"), bSupportsSpatialSensingEXT)
if (bSupportsSpatialSensingEXT)
{
XrSystemSpatialSensingPropertiesPICO SpatialSensingPropertiesPICO = { (XrStructureType)XR_TYPE_SYSTEM_SPATIAL_SENSING_PROPERTIES_PICO };
XrSystemProperties SPSpatialSensing{ XR_TYPE_SYSTEM_PROPERTIES,&SpatialSensingPropertiesPICO };
XR_ENSURE(xrGetSystemProperties(InInstance, InSystem, &SPSpatialSensing));
bSupportsSpatialSensing = SpatialSensingPropertiesPICO.supportsSpatialSensing == XR_TRUE;
UE_LOG(LogMRPICO,Log, TEXT("bSupportsSpatialSensing:%d"), bSupportsSpatialSensing)
XR_ENSURE(xrGetInstanceProcAddr(InInstance, "xrCreateSenseDataProviderPICO", (PFN_xrVoidFunction*)&xrCreateSenseDataProviderPICO));
XR_ENSURE(xrGetInstanceProcAddr(InInstance, "xrStartSenseDataProviderAsyncPICO", (PFN_xrVoidFunction*)&xrStartSenseDataProviderAsyncPICO));
XR_ENSURE(xrGetInstanceProcAddr(InInstance, "xrStartSenseDataProviderCompletePICO", (PFN_xrVoidFunction*)&xrStartSenseDataProviderCompletePICO));
XR_ENSURE(xrGetInstanceProcAddr(InInstance, "xrGetSenseDataProviderStatePICO", (PFN_xrVoidFunction*)&xrGetSenseDataProviderStatePICO));
XR_ENSURE(xrGetInstanceProcAddr(InInstance, "xrQuerySenseDataAsyncPICO", (PFN_xrVoidFunction*)&xrQuerySenseDataAsyncPICO));
XR_ENSURE(xrGetInstanceProcAddr(InInstance, "xrQuerySenseDataCompletePICO", (PFN_xrVoidFunction*)&xrQuerySenseDataCompletePICO));
XR_ENSURE(xrGetInstanceProcAddr(InInstance, "xrStopSenseDataProviderPICO", (PFN_xrVoidFunction*)&xrStopSenseDataProviderPICO));
XR_ENSURE(xrGetInstanceProcAddr(InInstance, "xrDestroySenseDataProviderPICO", (PFN_xrVoidFunction*)&xrDestroySenseDataProviderPICO));
XR_ENSURE(xrGetInstanceProcAddr(InInstance, "xrDestroySenseDataSnapshotPICO", (PFN_xrVoidFunction*)&xrDestroySenseDataSnapshotPICO));
XR_ENSURE(xrGetInstanceProcAddr(InInstance, "xrGetQueriedSenseDataPICO", (PFN_xrVoidFunction*)&xrGetQueriedSenseDataPICO));
XR_ENSURE(xrGetInstanceProcAddr(InInstance, "xrGetSpatialEntityUuidPICO", (PFN_xrVoidFunction*)&xrGetSpatialEntityUuidPICO));
XR_ENSURE(xrGetInstanceProcAddr(InInstance, "xrGetSpatialEntityComponentDataPICO", (PFN_xrVoidFunction*)&xrGetSpatialEntityComponentDataPICO));
XR_ENSURE(xrGetInstanceProcAddr(InInstance, "xrEnumerateSpatialEntityComponentTypesPICO", (PFN_xrVoidFunction*)&xrEnumerateSpatialEntityComponentTypesPICO));
XR_ENSURE(xrGetInstanceProcAddr(InInstance, "xrPollFutureEXT", (PFN_xrVoidFunction*)&xrPollFutureEXT));
XR_ENSURE(xrGetInstanceProcAddr(InInstance, "xrRetrieveSpatialEntityAnchorPICO", (PFN_xrVoidFunction*)&xrRetrieveSpatialEntityAnchorPICO));
XR_ENSURE(xrGetInstanceProcAddr(InInstance, "xrDestroyAnchorPICO", (PFN_xrVoidFunction*)&xrDestroyAnchorPICO));
XR_ENSURE(xrGetInstanceProcAddr(InInstance, "xrGetAnchorUuidPICO", (PFN_xrVoidFunction*)&xrGetAnchorUuidPICO));
XR_ENSURE(xrGetInstanceProcAddr(InInstance, "xrLocateAnchorPICO", (PFN_xrVoidFunction*)&xrLocateAnchorPICO));
}
}
void FSpatialSensingExtensionPICO::PostCreateSession(XrSession InSession)
{
Session = InSession;
static FName SystemName(TEXT("OpenXR"));
if (GEngine->XRSystem.IsValid() && (GEngine->XRSystem->GetSystemName() == SystemName))
{
XRTrackingSystem = GEngine->XRSystem.Get();
}
FCoreDelegates::ApplicationHasEnteredForegroundDelegate.AddRaw(this, &FSpatialSensingExtensionPICO::ApplicationResumeDelegate);
}
void FSpatialSensingExtensionPICO::UpdateDeviceLocations(XrSession InSession, XrTime DisplayTime, XrSpace InTrackingSpace)
{
CurrentDisplayTime = DisplayTime;
TrackingSpace = InTrackingSpace;
PXR_PollFuture();
}
void FSpatialSensingExtensionPICO::ApplicationResumeDelegate()
{
UMRFunctionLibraryPICO::GetMRDelegateManagerPICO()->ResumeDelegate.Broadcast();
}
bool FSpatialSensingExtensionPICO::AddPollFutureRequirement(const XrFutureEXT& FutureHandle, const FPICOPollFutureDelegate& Delegate)
{
FFutureMessagePICO cFutureMessage;
cFutureMessage.MessageHandle = FutureHandle;
cFutureMessage.Uuid = GetUUID();
FutureToDelegateMap.Add(cFutureMessage.Uuid, Delegate);
return FutureQueueForProviders.Enqueue(cFutureMessage);
}
bool FSpatialSensingExtensionPICO::StartSenseDataProviderComplete(const XrFutureEXT& FutureHandle, FSenseDataProviderStartCompletionPICO& Completion, EResultPICO& OutResult)
{
bool bResult = false;
if (bSupportsSpatialSensing)
{
XrSenseDataProviderStartCompletionPICO SenseDataProviderStartCompletionBD = {};
SenseDataProviderStartCompletionBD.type = XR_TYPE_SENSE_DATA_PROVIDER_START_COMPLETION_PICO;
XrResult xrResult = xrStartSenseDataProviderCompletePICO(Session, FutureHandle, &SenseDataProviderStartCompletionBD);
bResult = XR_SUCCEEDED(xrResult);
Completion.FutureResult = CastToPICOResult(SenseDataProviderStartCompletionBD.futureResult);
OutResult = CastToPICOResult(xrResult);
}
return bResult;
}
bool FSpatialSensingExtensionPICO::QuerySenseDataComplete(const XrSenseDataProviderPICO& ProviderHandle, const XrFutureEXT& FutureHandle, FSenseDataQueryCompletionPICO& Completion, EResultPICO& OutResult)
{
bool bResult = false;
if (bSupportsSpatialSensing)
{
XrSenseDataQueryCompletionPICO cPxrSenseDataQueryCompletionBD = {};
cPxrSenseDataQueryCompletionBD.type = XR_TYPE_SENSE_DATA_QUERY_COMPLETION_PICO;
XrResult xrResult = xrQuerySenseDataCompletePICO(ProviderHandle, FutureHandle, &cPxrSenseDataQueryCompletionBD);
bResult = XR_SUCCEEDED(xrResult);
Completion.SnapShotHandle = cPxrSenseDataQueryCompletionBD.snapshot;
Completion.FutureResult = CastToPICOResult(cPxrSenseDataQueryCompletionBD.futureResult);
OutResult = CastToPICOResult(xrResult);
}
return bResult;
}
bool FSpatialSensingExtensionPICO::GetQueriedSenseData(const XrSenseDataProviderPICO& ProviderHandle, const XrSenseDataSnapshotPICO& QueryResultHandle, FQueriedSenseDataPICO& QueriedSenseData, EResultPICO& OutResult)
{
bool bResult = false;
if (bSupportsSpatialSensing)
{
XrQueriedSenseDataGetInfoPICO cQueriedSenseDataGetInfoPICO = {};
cQueriedSenseDataGetInfoPICO.type = XR_TYPE_QUERIED_SENSE_DATA_GET_INFO_PICO;
cQueriedSenseDataGetInfoPICO.snapshot = QueryResultHandle;
XrQueriedSenseDataPICO cPxrQueriedSenseDataBD = {};
cPxrQueriedSenseDataBD.type = XR_TYPE_QUERIED_SENSE_DATA_PICO;
XrResult xrResult = xrGetQueriedSenseDataPICO(ProviderHandle, &cQueriedSenseDataGetInfoPICO, &cPxrQueriedSenseDataBD);
bResult = XR_SUCCEEDED(xrResult);
if (bResult)
{
if (cPxrQueriedSenseDataBD.spatialEntityCountOutput == 0)
{
return bResult;
}
cPxrQueriedSenseDataBD.spatialEntityCapacityInput = cPxrQueriedSenseDataBD.spatialEntityCountOutput;
QueriedSenseData.QueriedSpatialEntityInfos.SetNum(cPxrQueriedSenseDataBD.spatialEntityCapacityInput);
cPxrQueriedSenseDataBD.spatialEntities = QueriedSenseData.QueriedSpatialEntityInfos.GetData();
xrResult = xrGetQueriedSenseDataPICO(ProviderHandle, &cQueriedSenseDataGetInfoPICO, &cPxrQueriedSenseDataBD);
bResult = XR_SUCCEEDED(xrResult);
}
OutResult = CastToPICOResult(xrResult);
}
return bResult;
}
bool FSpatialSensingExtensionPICO::DestroySenseDataQueryResult(const XrSenseDataSnapshotPICO& QueryResultHandle, EResultPICO& OutResult)
{
bool bResult = false;
if (bSupportsSpatialSensing)
{
FRWScopeLock Lock(DestroyLock, SLT_Write);
XrResult xrResult = xrDestroySenseDataSnapshotPICO(QueryResultHandle);
bResult = XR_SUCCEEDED(xrResult);
OutResult = CastToPICOResult(xrResult);
}
return bResult;
}
void FSpatialSensingExtensionPICO::PXR_PollFuture()
{
if (bSupportsSpatialSensing)
{
FFutureMessagePICO CurrentMessage;
uint64 LeftMessageCount = 0;
bool hasFoundFrameBarrier = false;
while (FutureQueueForProviders.Peek(CurrentMessage))
{
if (CurrentMessage.IsFrameBarrier)
{
CurrentMessage.IsFrameBarrier = false;
FutureQueueForProviders.Pop();
FutureQueueForProviders.Enqueue(CurrentMessage);
break;
}
FutureQueueForProviders.Pop();
XrFuturePollInfoEXT FuturePollInfoEXT = {};
FuturePollInfoEXT.type = XR_TYPE_FUTURE_POLL_INFO_EXT;
FuturePollInfoEXT.future = CurrentMessage.MessageHandle;
XrFuturePollResultEXT cPollResultEXT = {};
cPollResultEXT.type = XR_TYPE_FUTURE_POLL_RESULT_EXT;
XrResult Result = xrPollFutureEXT(Instance, &FuturePollInfoEXT, &cPollResultEXT);
const bool bResult = XR_SUCCEEDED(Result);
if (!bResult)
{
UE_LOG(LogMRPICO, Error, TEXT("Provider PollFuture failed at:%p"), FuturePollInfoEXT.future);
}
if (cPollResultEXT.state == XR_FUTURE_STATE_READY_EXT
&& FutureToDelegateMap.Contains(CurrentMessage.Uuid))
{
FutureToDelegateMap[CurrentMessage.Uuid].ExecuteIfBound(CurrentMessage.MessageHandle);
FutureToDelegateMap.Remove(CurrentMessage.Uuid);
}
else
{
LeftMessageCount++;
if (!hasFoundFrameBarrier)
{
CurrentMessage.IsFrameBarrier = true;
hasFoundFrameBarrier = true;
}
FutureQueueForProviders.Enqueue(CurrentMessage);
}
}
}
}
bool FSpatialSensingExtensionPICO::GetSpatialEntityLocation(const XrSenseDataSnapshotPICO& SnapshotHandle, const XrSpatialEntityIdPICO& EntityHandle, FTransform& Transform, EResultPICO& OutResult)
{
bool bResult = false;
if (bSupportsSpatialSensing)
{
XrSpatialEntityLocationGetInfoPICO cComponentInfoGetInfo = {};
cComponentInfoGetInfo.type = XR_TYPE_SPATIAL_ENTITY_LOCATION_GET_INFO_PICO;
cComponentInfoGetInfo.componentType = XR_SPATIAL_ENTITY_COMPONENT_TYPE_LOCATION_PICO;
cComponentInfoGetInfo.entity = EntityHandle;
cComponentInfoGetInfo.baseSpace = TrackingSpace;
XrSpatialEntityLocationDataPICO cComponentInfo = {};
cComponentInfo.type = XR_TYPE_SPATIAL_ENTITY_LOCATION_DATA_PICO;
XrResult xrResult = xrGetSpatialEntityComponentDataPICO(SnapshotHandle
, reinterpret_cast<XrSpatialEntityComponentGetInfoBaseHeaderPICO*>(&cComponentInfoGetInfo)
, reinterpret_cast<XrSpatialEntityComponentDataBaseHeaderPICO*>(&cComponentInfo));
bResult = XR_SUCCEEDED(xrResult);
if (bResult)
{
float WorldToMetersScale = XRTrackingSystem->GetWorldToMetersScale();
FTransform TrackingToWorld = XRTrackingSystem->GetTrackingToWorldTransform();
FTransform UnrealPose = ToFTransform(cComponentInfo.location.pose, WorldToMetersScale);
Transform.SetLocation(TrackingToWorld.TransformPosition(UnrealPose.GetLocation()));
Transform.SetRotation(TrackingToWorld.TransformRotation(UnrealPose.GetRotation()));
}
OutResult = CastToPICOResult(xrResult);
}
return bResult;
}
bool FSpatialSensingExtensionPICO::GetSpatialEntitySemantic(const XrSenseDataSnapshotPICO& SnapshotHandle, const XrSpatialEntityIdPICO& EntityHandle, TArray<ESemanticLabelPICO>& Semantics, EResultPICO& OutResult)
{
bool bResult = false;
if (bSupportsSpatialSensing)
{
XrSpatialEntitySemanticGetInfoPICO cComponentInfoGetInfo = {};
cComponentInfoGetInfo.type = XR_TYPE_SPATIAL_ENTITY_SEMANTIC_GET_INFO_PICO;
cComponentInfoGetInfo.componentType = XR_SPATIAL_ENTITY_COMPONENT_TYPE_SEMANTIC_PICO;
cComponentInfoGetInfo.entity = EntityHandle;
XrSpatialEntitySemanticDataPICO cComponentInfo;
cComponentInfo.type = XR_TYPE_SPATIAL_ENTITY_SEMANTIC_DATA_PICO;
cComponentInfo.semanticLabels = nullptr;
cComponentInfo.semanticCapacityInput = 0;
XrResult xrResult = xrGetSpatialEntityComponentDataPICO(SnapshotHandle
, reinterpret_cast<XrSpatialEntityComponentGetInfoBaseHeaderPICO*>(&cComponentInfoGetInfo)
, reinterpret_cast<XrSpatialEntityComponentDataBaseHeaderPICO*>(&cComponentInfo));
bResult = XR_SUCCEEDED(xrResult);
if (bResult)
{
cComponentInfo.semanticCapacityInput = cComponentInfo.semanticCountOutput;
TArray<XrSemanticLabelPICO> TempSemantics;
TempSemantics.SetNum(cComponentInfo.semanticCapacityInput);
cComponentInfo.semanticLabels = TempSemantics.GetData();
xrResult = xrGetSpatialEntityComponentDataPICO(SnapshotHandle
, reinterpret_cast<XrSpatialEntityComponentGetInfoBaseHeaderPICO*>(&cComponentInfoGetInfo)
, reinterpret_cast<XrSpatialEntityComponentDataBaseHeaderPICO*>(&cComponentInfo));
bResult = XR_SUCCEEDED(xrResult);
if (bResult)
{
for (auto Semantic : TempSemantics)
{
Semantics.Add(static_cast<ESemanticLabelPICO>(Semantic));
}
}
}
OutResult = CastToPICOResult(xrResult);
}
return bResult;
}
bool FSpatialSensingExtensionPICO::GetSpatialEntityBoundary3D(const XrSenseDataSnapshotPICO& SnapshotHandle, const XrSpatialEntityIdPICO& EntityHandle, FBoundingBox3DPICO& Box, EResultPICO& OutResult)
{
bool bResult = false;
if (bSupportsSpatialSensing)
{
XrSpatialEntityBoundingBox3DGetInfoPICO cComponentInfoGetInfo = {};
cComponentInfoGetInfo.type = XR_TYPE_SPATIAL_ENTITY_BOUNDING_BOX_3D_GET_INFO_PICO;
cComponentInfoGetInfo.componentType = XR_SPATIAL_ENTITY_COMPONENT_TYPE_BOUNDING_BOX_3D_PICO;
cComponentInfoGetInfo.entity = EntityHandle;
XrSpatialEntityBoundingBox3DDataPICO cComponentInfo = {};
cComponentInfo.type = XR_TYPE_SPATIAL_ENTITY_BOUNDING_BOX_3D_DATA_PICO;
XrResult xrResult = xrGetSpatialEntityComponentDataPICO(SnapshotHandle
, reinterpret_cast<XrSpatialEntityComponentGetInfoBaseHeaderPICO*>(&cComponentInfoGetInfo)
, reinterpret_cast<XrSpatialEntityComponentDataBaseHeaderPICO*>(&cComponentInfo));
bResult = XR_SUCCEEDED(xrResult);
if (bResult)
{
float WorldToMetersScale = XRTrackingSystem->GetWorldToMetersScale();
Box.Center.SetLocation(FVector(cComponentInfo.boundingBox3D.center.position.x,
cComponentInfo.boundingBox3D.center.position.y,
cComponentInfo.boundingBox3D.center.position.z) * WorldToMetersScale);
Box.Center.SetRotation(FQuat(cComponentInfo.boundingBox3D.center.orientation.x,
cComponentInfo.boundingBox3D.center.orientation.y,
cComponentInfo.boundingBox3D.center.orientation.z,
cComponentInfo.boundingBox3D.center.orientation.w));
Box.Extent.Width = cComponentInfo.boundingBox3D.extents.width * WorldToMetersScale;
Box.Extent.Height = cComponentInfo.boundingBox3D.extents.height * WorldToMetersScale;
Box.Extent.Depth = cComponentInfo.boundingBox3D.extents.depth * WorldToMetersScale;
}
OutResult = CastToPICOResult(xrResult);
}
return bResult;
}
bool FSpatialSensingExtensionPICO::GetSpatialEntityBoundary2D(const XrSenseDataSnapshotPICO& SnapshotHandle, const XrSpatialEntityIdPICO& EntityHandle, FBoundingBox2DPICO& Box, EResultPICO& OutResult)
{
bool bResult = false;
if (bSupportsSpatialSensing)
{
XrSpatialEntityBoundingBox2DGetInfoPICO cComponentInfoGetInfo = {};
cComponentInfoGetInfo.type = XR_TYPE_SPATIAL_ENTITY_BOUNDING_BOX_2D_GET_INFO_PICO;
cComponentInfoGetInfo.componentType = XR_SPATIAL_ENTITY_COMPONENT_TYPE_BOUNDING_BOX_2D_PICO;
cComponentInfoGetInfo.entity = EntityHandle;
XrSpatialEntityBoundingBox2DDataPICO cComponentInfo = {};
cComponentInfo.type = XR_TYPE_SPATIAL_ENTITY_BOUNDING_BOX_2D_DATA_PICO;
XrResult xrResult = xrGetSpatialEntityComponentDataPICO(SnapshotHandle
, reinterpret_cast<XrSpatialEntityComponentGetInfoBaseHeaderPICO*>(&cComponentInfoGetInfo)
, reinterpret_cast<XrSpatialEntityComponentDataBaseHeaderPICO*>(&cComponentInfo));
bResult = XR_SUCCEEDED(xrResult);
if (bResult)
{
float WorldToMetersScale = XRTrackingSystem->GetWorldToMetersScale();
Box.Center = FVector(0, cComponentInfo.boundingBox2D.offset.x, cComponentInfo.boundingBox2D.offset.y) * WorldToMetersScale;
Box.Extent.Width = cComponentInfo.boundingBox2D.extent.width * WorldToMetersScale;
Box.Extent.Height = cComponentInfo.boundingBox2D.extent.height * WorldToMetersScale;
}
OutResult = CastToPICOResult(xrResult);
}
return bResult;
}
bool FSpatialSensingExtensionPICO::GetSpatialEntityPolygon(const XrSenseDataSnapshotPICO& SnapshotHandle, const XrSpatialEntityIdPICO& EntityHandle, TArray<FVector>& Vertices, EResultPICO& OutResult)
{
bool bResult = false;
if (bSupportsSpatialSensing)
{
XrSpatialEntityPolygonGetInfoPICO cComponentInfoGetInfo = {};
cComponentInfoGetInfo.type = XR_TYPE_SPATIAL_ENTITY_POLYGON_GET_INFO_PICO;
cComponentInfoGetInfo.componentType = XR_SPATIAL_ENTITY_COMPONENT_TYPE_POLYGON_PICO;
cComponentInfoGetInfo.entity = EntityHandle;
XrSpatialEntityPolygonDataPICO cComponentInfo = {};
cComponentInfo.type = XR_TYPE_SPATIAL_ENTITY_POLYGON_DATA_PICO;
XrResult xrResult = xrGetSpatialEntityComponentDataPICO(SnapshotHandle
, reinterpret_cast<XrSpatialEntityComponentGetInfoBaseHeaderPICO*>(&cComponentInfoGetInfo)
, reinterpret_cast<XrSpatialEntityComponentDataBaseHeaderPICO*>(&cComponentInfo));
bResult = XR_SUCCEEDED(xrResult);
if (bResult)
{
cComponentInfo.polygonCapacityInput = cComponentInfo.polygonCountOutput;
TArray<XrVector2f> TempVertices;
TempVertices.SetNum(cComponentInfo.polygonCapacityInput);
cComponentInfo.polygonVertices = TempVertices.GetData();
xrResult = xrGetSpatialEntityComponentDataPICO(SnapshotHandle
, reinterpret_cast<XrSpatialEntityComponentGetInfoBaseHeaderPICO*>(&cComponentInfoGetInfo)
, reinterpret_cast<XrSpatialEntityComponentDataBaseHeaderPICO*>(&cComponentInfo));
bResult = XR_SUCCEEDED(xrResult);
float WorldToMetersScale = XRTrackingSystem->GetWorldToMetersScale();
if (bResult)
{
Vertices.Empty(TempVertices.Num());
Algo::Transform(TempVertices, Vertices, [this,WorldToMetersScale](const auto& Vertex) { return FVector(0.f, Vertex.x, Vertex.y) * WorldToMetersScale; });
}
}
OutResult = CastToPICOResult(xrResult);
}
return bResult;
}
bool FSpatialSensingExtensionPICO::GetSpatialEntityTriangleMesh(const XrSenseDataSnapshotPICO& SnapshotHandle, const XrSpatialEntityIdPICO& EntityHandle, TArray<FVector>& Vertices, TArray<uint16>& Triangles, EResultPICO& OutResult)
{
bool bResult = false;
if (bSupportsSpatialSensing)
{
XrSpatialEntityTriangleMeshGetInfoPICO cComponentInfoGetInfo = {};
cComponentInfoGetInfo.type = XR_TYPE_SPATIAL_ENTITY_TRIANGLE_MESH_GET_INFO_PICO;
cComponentInfoGetInfo.componentType = XR_SPATIAL_ENTITY_COMPONENT_TYPE_TRIANGLE_MESH_PICO;
cComponentInfoGetInfo.entity = EntityHandle;
XrSpatialEntityTriangleMeshDataPICO cComponentInfo = {};
cComponentInfo.type = XR_TYPE_SPATIAL_ENTITY_TRIANGLE_MESH_DATA_PICO;
XrResult xrResult = xrGetSpatialEntityComponentDataPICO(SnapshotHandle
, reinterpret_cast<XrSpatialEntityComponentGetInfoBaseHeaderPICO*>(&cComponentInfoGetInfo)
, reinterpret_cast<XrSpatialEntityComponentDataBaseHeaderPICO*>(&cComponentInfo));
bResult = XR_SUCCEEDED(xrResult);
if (bResult)
{
cComponentInfo.indexCapacityInput = cComponentInfo.indexCountOutput;
cComponentInfo.vertexCapacityInput = cComponentInfo.vertexCountOutput;
Triangles.SetNum(cComponentInfo.indexCapacityInput);
cComponentInfo.indices = Triangles.GetData();
TArray<XrVector3f> TempVertices;
TempVertices.SetNum(cComponentInfo.vertexCapacityInput);
cComponentInfo.vertices = TempVertices.GetData();
xrResult = xrGetSpatialEntityComponentDataPICO(SnapshotHandle
, reinterpret_cast<XrSpatialEntityComponentGetInfoBaseHeaderPICO*>(&cComponentInfoGetInfo)
, reinterpret_cast<XrSpatialEntityComponentDataBaseHeaderPICO*>(&cComponentInfo));
bResult = XR_SUCCEEDED(xrResult);
if (bResult)
{
float WorldToMetersScale = XRTrackingSystem->GetWorldToMetersScale();
for (auto Vertice : TempVertices)
{
FVector VertexPose = ToFVector(Vertice) * WorldToMetersScale;
if (VertexPose.ContainsNaN())
{
return false;
}
Vertices.Add(VertexPose);
}
}
}
OutResult = CastToPICOResult(xrResult);
}
return bResult;
}
bool FSpatialSensingExtensionPICO::EnumerateSpatialEntityComponentTypes(const XrSenseDataSnapshotPICO& SnapshotHandle, const XrSpatialEntityIdPICO& EntityHandle, TArray<ESpatialEntityComponentTypePICO>& componentTypes, EResultPICO& OutResult)
{
bool bResult = false;
if (bSupportsSpatialSensing)
{
uint32_t ComponentTypeCapacityInput = 0;
uint32_t ComponentTypeCountOutput = 0;
XrResult xrResult = xrEnumerateSpatialEntityComponentTypesPICO(SnapshotHandle, EntityHandle, ComponentTypeCapacityInput, &ComponentTypeCountOutput, nullptr);
bResult = XR_SUCCEEDED(xrResult);
if (bResult && ComponentTypeCountOutput != 0)
{
ComponentTypeCapacityInput = ComponentTypeCountOutput;
TArray<XrSpatialEntityComponentTypePICO> TempComponentTypes;
TempComponentTypes.SetNum(ComponentTypeCapacityInput);
xrResult = xrEnumerateSpatialEntityComponentTypesPICO(SnapshotHandle,
EntityHandle,
ComponentTypeCapacityInput,
&ComponentTypeCountOutput,
TempComponentTypes.GetData());
bResult = XR_SUCCEEDED(xrResult);
for (auto ComponentTypeBD : TempComponentTypes)
{
componentTypes.Add(static_cast<ESpatialEntityComponentTypePICO>(ComponentTypeBD));
}
}
OutResult = CastToPICOResult(xrResult);
}
return bResult;
}
void FSpatialSensingExtensionPICO::PollEvent(const XrEventDataBuffer* EventData)
{
if (bSupportsSpatialSensing)
{
UE_LOG(LogMRPICO, VeryVerbose, TEXT("PollEvent EventData:%d"), EventData->type);
switch (EventData->type)
{
case XR_TYPE_EVENT_DATA_SENSE_DATA_UPDATED_PICO:
{
const XrEventDataSenseDataUpdatedPICO* DataSenseDataState = reinterpret_cast<const XrEventDataSenseDataUpdatedPICO*>(EventData);
UE_LOG(LogMRPICO, VeryVerbose, TEXT("DataSenseDataState->provider:%p"), DataSenseDataState->provider);
switch (GetProviderTypeByHandle(DataSenseDataState->provider))
{
case EProviderTypePICO::Pico_Provider_Anchor:
{
UE_LOG(LogMRPICO, VeryVerbose, TEXT("Pico_Provider_Anchor DataUpdated"));
UMRFunctionLibraryPICO::GetMRDelegateManagerPICO()->AnchorDataUpdatedDelegate.Broadcast();
}
break;
case EProviderTypePICO::Pico_Provider_Mesh:
{
UE_LOG(LogMRPICO, VeryVerbose, TEXT("Pico_Provider_Mesh DataUpdated"));
UMRFunctionLibraryPICO::GetMRDelegateManagerPICO()->MeshDataUpdatedDelegate.Broadcast();
}
break;
case EProviderTypePICO::Pico_Provider_Scene_Capture:
{
UE_LOG(LogMRPICO, VeryVerbose, TEXT("Pico_Provider_Scene_Capture DataUpdated"));
UMRFunctionLibraryPICO::GetMRDelegateManagerPICO()->SceneCaptureDataUpdatedDelegate.Broadcast();
}
break;
default: ;
};
break;
}
case XR_TYPE_EVENT_DATA_SENSE_DATA_PROVIDER_STATE_CHANGED_PICO:
{
const XrEventDataSenseDataProviderStateChangedPICO* SenseDataProviderState = reinterpret_cast<const XrEventDataSenseDataProviderStateChangedPICO*>(EventData);
const EMRStatePICO State = static_cast<EMRStatePICO>(SenseDataProviderState->newState);
UE_LOG(LogMRPICO, VeryVerbose, TEXT("PollEvent State:%d"), State);
switch (GetProviderTypeByHandle(SenseDataProviderState->provider))
{
case EProviderTypePICO::Pico_Provider_Anchor:
{
UMRFunctionLibraryPICO::GetMRDelegateManagerPICO()->SpatialAnchorServiceStateUpdatedDelegate.Broadcast(State);
}
break;
case EProviderTypePICO::Pico_Provider_Mesh:
{
UMRFunctionLibraryPICO::GetMRDelegateManagerPICO()->MeshScanningStateUpdatedDelegate.Broadcast(State);
}
break;
case EProviderTypePICO::Pico_Provider_Scene_Capture:
{
UMRFunctionLibraryPICO::GetMRDelegateManagerPICO()->SceneCaptureServiceStateUpdatedDelegate.Broadcast(State);
}
break;
default: ;
};
break;
}
default:
{
break;
}
}
}
}
EProviderTypePICO FSpatialSensingExtensionPICO::GetProviderTypeByHandle(const XrSenseDataProviderPICO& Handle)
{
if (FSpatialAnchorExtensionPICO::GetInstance()->IsEqualProvider(Handle))
{
return EProviderTypePICO::Pico_Provider_Anchor;
}
if (FSpatialMeshExtensionPICO::GetInstance()->IsEqualProvider(Handle))
{
return EProviderTypePICO::Pico_Provider_Mesh;
}
if (FSceneCaptureExtensionPICO::GetInstance()->IsEqualProvider(Handle))
{
return EProviderTypePICO::Pico_Provider_Scene_Capture;
}
return EProviderTypePICO::Pico_Provider_Max;
}
EResultPICO FSpatialSensingExtensionPICO::CastToPICOResult(XrResult Result)
{
EResultPICO PICOResult = EResultPICO::XR_Error_Unknown_PICO;
switch (Result)
{
case XrResult::XR_SUCCESS: PICOResult = EResultPICO::XR_Success;
break;
case XrResult::XR_TIMEOUT_EXPIRED: PICOResult = EResultPICO::XR_TimeoutExpired;
break;
case XrResult::XR_ERROR_VALIDATION_FAILURE: PICOResult = EResultPICO::XR_Error_ValidationFailure;
break;
case XrResult::XR_ERROR_RUNTIME_FAILURE: PICOResult = EResultPICO::XR_Error_RuntimeFailure;
break;
case XrResult::XR_ERROR_OUT_OF_MEMORY: PICOResult = EResultPICO::XR_Error_OutOfMemory;
break;
case XrResult::XR_ERROR_API_VERSION_UNSUPPORTED: PICOResult = EResultPICO::XR_Error_APIVersionUnsupported;
break;
case XrResult::XR_ERROR_INITIALIZATION_FAILED: PICOResult = EResultPICO::XR_Error_InitializationFailed;
break;
case XrResult::XR_ERROR_FUNCTION_UNSUPPORTED: PICOResult = EResultPICO::XR_Error_FunctionUnsupported;
break;
case XrResult::XR_ERROR_FEATURE_UNSUPPORTED: PICOResult = EResultPICO::XR_Error_FeatureUnsupported;
break;
case XrResult::XR_ERROR_LIMIT_REACHED: PICOResult = EResultPICO::XR_Error_LimitReached;
break;
case XrResult::XR_ERROR_SIZE_INSUFFICIENT: PICOResult = EResultPICO::XR_Error_SizeInsufficient;
break;
case XrResult::XR_ERROR_HANDLE_INVALID: PICOResult = EResultPICO::XR_Error_HandleInvalid;
break;
case XrResult::XR_ERROR_POSE_INVALID: PICOResult = EResultPICO::XR_Error_Pose_Invalid_PICO;
break;
case XrResult::XR_ERROR_SPATIAL_ANCHOR_SHARING_NETWORK_TIMEOUT_PICO: PICOResult = EResultPICO::XR_Error_Anchor_Sharing_Network_Timeout_PICO;
break;
case XrResult::XR_ERROR_SPATIAL_ANCHOR_SHARING_AUTHENTICATION_FAILURE_PICO: PICOResult = EResultPICO::XR_Error_Anchor_Sharing_Authentication_Failure_PICO;
break;
case XrResult::XR_ERROR_SPATIAL_ANCHOR_SHARING_NETWORK_FAILURE_PICO: PICOResult = EResultPICO::XR_Error_Anchor_Sharing_Network_Failure_PICO;
break;
case XrResult::XR_ERROR_SPATIAL_ANCHOR_SHARING_LOCALIZATION_FAIL_PICO: PICOResult = EResultPICO::XR_Error_Anchor_Sharing_Localization_Fail_PICO;
break;
case XrResult::XR_ERROR_SPATIAL_ANCHOR_SHARING_MAP_INSUFFICIENT_PICO: PICOResult = EResultPICO::XR_Error_Anchor_Sharing_Map_Insufficient_PICO;
break;
case XrResult::XR_ERROR_SPATIAL_SENSING_SERVICE_UNAVAILABLE_PICO: PICOResult = EResultPICO::XR_Error_SpatialSensingServiceUnavailable_PICO;
break;
case XrResult::XR_ERROR_PERMISSION_INSUFFICIENT: PICOResult = EResultPICO::XR_Error_Permission_Insufficient_PICO;
break;
default:
PICOResult = EResultPICO::XR_Error_Unknown_PICO;
break;
}
return PICOResult;
}
uint64 FSpatialSensingExtensionPICO::GetUUID()
{
return GlobalUUIDCount++;
}
FMixedRealityPICO::FMixedRealityPICO(): CurrentDisplayTime(0)
{
}
void FMixedRealityPICO::Register()
{
RegisterOpenXRExtensionModularFeature();
}
void FMixedRealityPICO::Unregister()
{
UnregisterOpenXRExtensionModularFeature();
}
void FMixedRealityPICO::OnDestroySession(XrSession InSession)
{
if (IsHandleValid())
{
switch (GetSenseDataProviderState())
{
case EMRStatePICO::Initialized:
{
EResultPICO xrResult = EResultPICO::XR_Error_Unknown_PICO;
DestroyProvider(xrResult);
}
break;
case EMRStatePICO::Running:
{
EResultPICO xrResult = EResultPICO::XR_Error_Unknown_PICO;
if (StopProvider(xrResult))
{
DestroyProvider(xrResult);
}
}
break;
case EMRStatePICO::Stopped:
break;
}
}
}
void FMixedRealityPICO::PostCreateSession(XrSession InSession)
{
Session = InSession;
static FName SystemName(TEXT("OpenXR"));
if (GEngine->XRSystem.IsValid() && (GEngine->XRSystem->GetSystemName() == SystemName))
{
XRTrackingSystem = GEngine->XRSystem.Get();
}
}
void FMixedRealityPICO::UpdateDeviceLocations(XrSession InSession, XrTime DisplayTime, XrSpace InTrackingSpace)
{
CurrentDisplayTime = DisplayTime;
TrackingSpace = InTrackingSpace;
}
bool FMixedRealityPICO::StartProvider(const FPICOPollFutureDelegate& StartSenseDataProviderDelegate, EResultPICO& OutResult)
{
bool bResult = false;
if (FSpatialSensingExtensionPICO::GetInstance()->IsSupportsSpatialSensing())
{
XrSenseDataProviderStartInfoPICO cSenseDataProviderStartInfoPICO = {};
cSenseDataProviderStartInfoPICO.type = XR_TYPE_SENSE_DATA_PROVIDER_START_INFO_PICO;
cSenseDataProviderStartInfoPICO.provider = ProviderHandle;
XrFutureEXT ProviderFutureEXT;
XrResult xrResult = FSpatialSensingExtensionPICO::GetInstance()->xrStartSenseDataProviderAsyncPICO(Session, &cSenseDataProviderStartInfoPICO, &ProviderFutureEXT);
bResult = XR_SUCCEEDED(xrResult);
OutResult = FSpatialSensingExtensionPICO::CastToPICOResult(xrResult);
if (bResult)
{
bResult = FSpatialSensingExtensionPICO::GetInstance()->AddPollFutureRequirement(ProviderFutureEXT, StartSenseDataProviderDelegate);
}
bResult = bResult ? ProviderFutureEXT != XR_NULL_HANDLE : false;
}
return bResult;
}
bool FMixedRealityPICO::StopProvider(EResultPICO& OutResult)
{
bool bResult = false;
if (FSpatialSensingExtensionPICO::GetInstance()->IsSupportsSpatialSensing())
{
XrResult xrResult = FSpatialSensingExtensionPICO::GetInstance()->xrStopSenseDataProviderPICO(ProviderHandle);
bResult = XR_SUCCEEDED(xrResult);
OutResult = FSpatialSensingExtensionPICO::CastToPICOResult(xrResult);
}
return bResult;
}
bool FMixedRealityPICO::DestroyProvider(EResultPICO& OutResult)
{
bool bResult = false;
if (FSpatialSensingExtensionPICO::GetInstance()->IsSupportsSpatialSensing())
{
XrResult xrResult = FSpatialSensingExtensionPICO::GetInstance()->xrDestroySenseDataProviderPICO(ProviderHandle);
bResult = XR_SUCCEEDED(xrResult);
if (bResult)
{
ProviderHandle = XR_NULL_HANDLE;
}
OutResult = FSpatialSensingExtensionPICO::CastToPICOResult(xrResult);
}
return bResult;
}
EProviderTypePICO FMixedRealityPICO::GetProviderType()
{
return Type;
}
EMRStatePICO FMixedRealityPICO::GetSenseDataProviderState() const
{
EMRStatePICO SenseDataProviderState = EMRStatePICO::Stopped;
if (FSpatialSensingExtensionPICO::GetInstance()->IsSupportsSpatialSensing())
{
XrSenseDataProviderStatePICO cPxrSenseDataProviderStateBD = {};
XrResult xrResult = FSpatialSensingExtensionPICO::GetInstance()->xrGetSenseDataProviderStatePICO(ProviderHandle, &cPxrSenseDataProviderStateBD);
SenseDataProviderState = XR_SUCCEEDED(xrResult) ? static_cast<EMRStatePICO>(cPxrSenseDataProviderStateBD) : EMRStatePICO::Stopped;
}
return SenseDataProviderState;
}