VRTowerDef/Plugins/MetaXR/Source/OculusXRAnchors/Private/OculusXRAnchorManager.cpp

817 lines
29 KiB
C++

// Copyright (c) Meta Platforms, Inc. and affiliates.
#include "OculusXRAnchorManager.h"
#include <vector>
#include "OculusXRHMD.h"
#include "OculusXRAnchorsModule.h"
#include "OculusXRAnchorDelegates.h"
#include "OculusXRAnchorBPFunctionLibrary.h"
#include "OculusXRAnchorTypesPrivate.h"
namespace OculusXRAnchors
{
OculusXRHMD::FOculusXRHMD* GetHMD(bool& OutSuccessful)
{
OculusXRHMD::FOculusXRHMD* OutHMD = OculusXRHMD::FOculusXRHMD::GetOculusXRHMD();
if (!OutHMD)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Unable to retrieve OculusXRHMD"));
OutSuccessful = false;
}
OutSuccessful = true;
return OutHMD;
}
ovrpUuid ConvertFOculusXRUUIDtoOvrpUuid(const FOculusXRUUID& UUID)
{
ovrpUuid Result;
FMemory::Memcpy(Result.data, UUID.UUIDBytes);
return Result;
}
ovrpSpaceQueryInfo ConvertToOVRPSpaceQueryInfo(const FOculusXRSpaceQueryInfo& UEQueryInfo)
{
static const int32 MaxIdsInFilter = 1024;
static const int32 MaxComponentTypesInFilter = 16;
ovrpSpaceQueryInfo Result;
Result.queryType = ovrpSpaceQueryType_Action;
Result.actionType = ovrpSpaceQueryActionType_Load;
Result.maxQuerySpaces = UEQueryInfo.MaxQuerySpaces;
Result.timeout = static_cast<double>(UEQueryInfo.Timeout); // Prevent compiler warnings, though there is a possible loss of data here.
switch (UEQueryInfo.Location)
{
case EOculusXRSpaceStorageLocation::Invalid:
Result.location = ovrpSpaceStorageLocation_Invalid;
break;
case EOculusXRSpaceStorageLocation::Local:
Result.location = ovrpSpaceStorageLocation_Local;
break;
case EOculusXRSpaceStorageLocation::Cloud:
Result.location = ovrpSpaceStorageLocation_Cloud;
break;
}
switch (UEQueryInfo.FilterType)
{
case EOculusXRSpaceQueryFilterType::None:
Result.filterType = ovrpSpaceQueryFilterType_None;
break;
case EOculusXRSpaceQueryFilterType::FilterByIds:
Result.filterType = ovrpSpaceQueryFilterType_Ids;
break;
case EOculusXRSpaceQueryFilterType::FilterByComponentType:
Result.filterType = ovrpSpaceQueryFilterType_Components;
break;
}
Result.IdInfo.numIds = FMath::Min(MaxIdsInFilter, UEQueryInfo.IDFilter.Num());
for (int i = 0; i < Result.IdInfo.numIds; ++i)
{
ovrpUuid OvrUuid = ConvertFOculusXRUUIDtoOvrpUuid(UEQueryInfo.IDFilter[i]);
Result.IdInfo.ids[i] = OvrUuid;
}
Result.componentsInfo.numComponents = FMath::Min(MaxComponentTypesInFilter, UEQueryInfo.ComponentFilter.Num());
for (int i = 0; i < Result.componentsInfo.numComponents; ++i)
{
Result.componentsInfo.components[i] = ConvertToOvrpComponentType(UEQueryInfo.ComponentFilter[i]);
}
return Result;
}
template <typename T>
void GetEventData(ovrpEventDataBuffer& Buffer, T& OutEventData)
{
unsigned char* BufData = Buffer.EventData;
BufData -= sizeof(uint64); //correct offset
memcpy(&OutEventData, BufData, sizeof(T));
}
void FOculusXRAnchorManager::OnPollEvent(ovrpEventDataBuffer* EventDataBuffer, bool& EventPollResult)
{
ovrpEventDataBuffer& buf = *EventDataBuffer;
EventPollResult = true;
switch (buf.EventType)
{
case ovrpEventType_SpatialAnchorCreateComplete:
{
ovrpEventDataSpatialAnchorCreateComplete AnchorCreateEvent;
GetEventData(buf, AnchorCreateEvent);
const FOculusXRUInt64 RequestId(AnchorCreateEvent.requestId);
const FOculusXRUInt64 Space(AnchorCreateEvent.space);
const FOculusXRUUID BPUUID(AnchorCreateEvent.uuid.data);
FOculusXRAnchorEventDelegates::OculusSpatialAnchorCreateComplete.Broadcast(RequestId, AnchorCreateEvent.result, Space, BPUUID);
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("ovrpEventType_SpatialAnchorCreateComplete Request ID: %llu -- Space: %llu -- UUID: %s -- Result: %d"),
RequestId.GetValue(),
Space.GetValue(),
*BPUUID.ToString(),
AnchorCreateEvent.result);
break;
}
case ovrpEventType_SpaceSetComponentStatusComplete:
{
ovrpEventDataSpaceSetStatusComplete SetStatusEvent;
GetEventData(buf, SetStatusEvent);
//translate to BP types
const FOculusXRUInt64 RequestId(SetStatusEvent.requestId);
const FOculusXRUInt64 Space(SetStatusEvent.space);
EOculusXRSpaceComponentType BPSpaceComponentType = ConvertToUEComponentType(SetStatusEvent.componentType);
const FOculusXRUUID BPUUID(SetStatusEvent.uuid.data);
const bool bEnabled = (SetStatusEvent.enabled == ovrpBool_True);
FOculusXRAnchorEventDelegates::OculusSpaceSetComponentStatusComplete.Broadcast(
RequestId,
SetStatusEvent.result,
Space,
BPUUID,
BPSpaceComponentType,
bEnabled);
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("ovrpEventType_SpaceSetComponentStatusComplete Request ID: %llu -- Type: %d -- Enabled: %d -- Space: %llu -- Result: %d"),
SetStatusEvent.requestId,
SetStatusEvent.componentType,
SetStatusEvent.enabled,
SetStatusEvent.space,
SetStatusEvent.result);
break;
}
case ovrpEventType_SpaceQueryResults:
{
ovrpEventSpaceQueryResults QueryEvent;
GetEventData(buf, QueryEvent);
const FOculusXRUInt64 RequestId(QueryEvent.requestId);
FOculusXRAnchorEventDelegates::OculusSpaceQueryResults.Broadcast(RequestId);
ovrpUInt32 ovrpOutCapacity = 0;
// First get capacity
const bool bGetCapacityResult = FOculusXRHMDModule::GetPluginWrapper().GetInitialized() && OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().RetrieveSpaceQueryResults(&QueryEvent.requestId, 0, &ovrpOutCapacity, nullptr));
UE_LOG(LogOculusXRAnchors, Log, TEXT("ovrpEventType_SpaceQueryResults Request ID: %llu -- Capacity: %d -- Result: %d"), QueryEvent.requestId, ovrpOutCapacity, bGetCapacityResult);
std::vector<ovrpSpaceQueryResult> ovrpResults(ovrpOutCapacity);
// Get Query Data
const bool bGetQueryDataResult = FOculusXRHMDModule::GetPluginWrapper().GetInitialized() && OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().RetrieveSpaceQueryResults(&QueryEvent.requestId, ovrpResults.size(), &ovrpOutCapacity, ovrpResults.data()));
for (auto queryResultElement : ovrpResults)
{
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("ovrpEventType_SpaceQueryResult Space: %llu -- Result: %d"), queryResultElement.space, bGetQueryDataResult);
//translate types
FOculusXRUInt64 Space(queryResultElement.space);
FOculusXRUUID BPUUID(queryResultElement.uuid.data);
FOculusXRAnchorEventDelegates::OculusSpaceQueryResult.Broadcast(RequestId, Space, BPUUID);
}
break;
}
case ovrpEventType_SpaceQueryComplete:
{
ovrpEventSpaceQueryComplete QueryCompleteEvent;
GetEventData(buf, QueryCompleteEvent);
//translate to BP types
const FOculusXRUInt64 RequestId(QueryCompleteEvent.requestId);
const bool bSucceeded = QueryCompleteEvent.result >= 0;
FOculusXRAnchorEventDelegates::OculusSpaceQueryComplete.Broadcast(RequestId, QueryCompleteEvent.result);
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("ovrpEventType_SpaceQueryComplete Request ID: %llu -- Result: %d"), QueryCompleteEvent.requestId, QueryCompleteEvent.result);
break;
}
case ovrpEventType_SpaceSaveComplete:
{
ovrpEventSpaceStorageSaveResult StorageResult;
GetEventData(buf, StorageResult);
//translate to BP types
const FOculusXRUUID uuid(StorageResult.uuid.data);
const FOculusXRUInt64 FSpace(StorageResult.space);
const FOculusXRUInt64 FRequest(StorageResult.requestId);
const bool bResult = StorageResult.result >= 0;
FOculusXRAnchorEventDelegates::OculusSpaceSaveComplete.Broadcast(FRequest, FSpace, bResult, StorageResult.result, uuid);
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("ovrpEventType_SpaceSaveComplete Request ID: %llu -- Space: %llu -- Result: %d"), StorageResult.requestId, StorageResult.space, StorageResult.result);
break;
}
case ovrpEventType_SpaceListSaveResult:
{
ovrpEventSpaceListSaveResult SpaceListSaveResult;
GetEventData(buf, SpaceListSaveResult);
FOculusXRUInt64 RequestId(SpaceListSaveResult.requestId);
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("ovrpEventType_SpaceListSaveResult Request ID: %llu -- Result: %d"), SpaceListSaveResult.requestId, SpaceListSaveResult.result);
FOculusXRAnchorEventDelegates::OculusSpaceListSaveComplete.Broadcast(RequestId, SpaceListSaveResult.result);
break;
}
case ovrpEventType_SpaceEraseComplete:
{
ovrpEventSpaceStorageEraseResult SpaceEraseEvent;
GetEventData(buf, SpaceEraseEvent);
//translate to BP types
const FOculusXRUUID uuid(SpaceEraseEvent.uuid.data);
const FOculusXRUInt64 FRequestId(SpaceEraseEvent.requestId);
const FOculusXRUInt64 FResult(SpaceEraseEvent.result);
const EOculusXRSpaceStorageLocation BPLocation = (SpaceEraseEvent.location == ovrpSpaceStorageLocation_Local) ? EOculusXRSpaceStorageLocation::Local : EOculusXRSpaceStorageLocation::Invalid;
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("ovrpEventType_SpaceEraseComplete Request ID: %llu -- Result: %d -- UUID: %s"), SpaceEraseEvent.requestId, SpaceEraseEvent.result, *UOculusXRAnchorBPFunctionLibrary::AnchorUUIDToString(SpaceEraseEvent.uuid.data));
FOculusXRAnchorEventDelegates::OculusSpaceEraseComplete.Broadcast(FRequestId, FResult.Value, uuid, BPLocation);
break;
}
case ovrpEventType_SpaceShareResult:
{
unsigned char* BufData = buf.EventData;
ovrpUInt64 OvrpRequestId = 0;
memcpy(&OvrpRequestId, BufData, sizeof(OvrpRequestId));
ovrpEventSpaceShareResult SpaceShareSpaceResult;
GetEventData(buf, SpaceShareSpaceResult);
FOculusXRUInt64 RequestId(SpaceShareSpaceResult.requestId);
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("ovrpEventType_SpaceShareSpaceResult Request ID: %llu -- Result: %d"),
SpaceShareSpaceResult.requestId,
SpaceShareSpaceResult.result);
FOculusXRAnchorEventDelegates::OculusSpaceShareComplete.Broadcast(RequestId, SpaceShareSpaceResult.result);
break;
}
case ovrpEventType_None:
default:
{
EventPollResult = false;
break;
}
}
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::CreateAnchor(const FTransform& InTransform, uint64& OutRequestId, const FTransform& CameraTransform)
{
bool bValidHMD;
OculusXRHMD::FOculusXRHMD* HMD = GetHMD(bValidHMD);
if (!bValidHMD)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("FOculusAnchorManager::CreateAnchor failed to retrieve HMD."));
return EOculusXRAnchorResult::Failure;
}
ovrpTrackingOrigin TrackingOriginType;
ovrpPosef Posef;
double Time = 0;
const FTransform TrackingToWorld = HMD->GetLastTrackingToWorld();
// convert to tracking space
const FQuat TrackingSpaceOrientation = TrackingToWorld.Inverse().TransformRotation(InTransform.Rotator().Quaternion());
const FVector TrackingSpacePosition = TrackingToWorld.Inverse().TransformPosition(InTransform.GetLocation());
const OculusXRHMD::FPose TrackingSpacePose(TrackingSpaceOrientation, TrackingSpacePosition);
#if WITH_EDITOR
// Link only head space position update
FVector OutHeadPosition;
FQuat OutHeadOrientation;
const bool bGetPose = HMD->GetCurrentPose(HMD->HMDDeviceId, OutHeadOrientation, OutHeadPosition);
if (!bGetPose)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("FOculusAnchorManager::CreateAnchor failed to get current headset pose."));
return EOculusXRAnchorResult::Failure;
}
OculusXRHMD::FPose HeadPose(OutHeadOrientation, OutHeadPosition);
OculusXRHMD::FPose MainCameraPose(CameraTransform.GetRotation(), CameraTransform.GetLocation());
OculusXRHMD::FPose PoseInHeadSpace = MainCameraPose.Inverse() * TrackingSpacePose;
// To world space pose
OculusXRHMD::FPose WorldPose = HeadPose * PoseInHeadSpace;
const bool bConverted = HMD->ConvertPose(WorldPose, Posef);
#else
const bool bConverted = HMD->ConvertPose(TrackingSpacePose, Posef);
#endif
if (!bConverted)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("FOculusAnchorManager::CreateAnchor failed to convert pose."));
return EOculusXRAnchorResult::Failure;
}
FOculusXRHMDModule::GetPluginWrapper().GetTrackingOriginType2(&TrackingOriginType);
FOculusXRHMDModule::GetPluginWrapper().GetTimeInSeconds(&Time);
const ovrpSpatialAnchorCreateInfo SpatialAnchorCreateInfo = {
TrackingOriginType,
Posef,
Time
};
const ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().CreateSpatialAnchor(&SpatialAnchorCreateInfo, &OutRequestId);
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("CreateAnchor Request ID: %llu"), OutRequestId);
if (OVRP_FAILURE(Result))
{
UE_LOG(LogOculusXRAnchors, Error, TEXT("FOculusAnchorManager::CreateAnchor failed. Result: %d"), Result);
}
return static_cast<EOculusXRAnchorResult::Type>(Result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::DestroySpace(uint64 Space)
{
const ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().DestroySpace(static_cast<ovrpSpace*>(&Space));
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("DestroySpace Space ID: %llu"), Space);
return static_cast<EOculusXRAnchorResult::Type>(Result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::SetSpaceComponentStatus(uint64 Space, EOculusXRSpaceComponentType SpaceComponentType, bool Enable, float Timeout, uint64& OutRequestId)
{
ovrpSpaceComponentType ovrpType = ConvertToOvrpComponentType(SpaceComponentType);
ovrpUInt64 OvrpOutRequestId = 0;
const ovrpUInt64 OVRPSpace = Space;
// validate existing status
ovrpBool isEnabled = false;
ovrpBool changePending = false;
const ovrpResult getComponentStatusResult = FOculusXRHMDModule::GetPluginWrapper().GetSpaceComponentStatus(&OVRPSpace, ovrpType, &isEnabled, &changePending);
bool isStatusChangingOrSame = (static_cast<bool>(isEnabled) == Enable && !changePending) || (static_cast<bool>(isEnabled) != Enable && changePending);
if (OVRP_SUCCESS(getComponentStatusResult) && isStatusChangingOrSame)
{
return EOculusXRAnchorResult::Success;
}
// set status
const ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().SetSpaceComponentStatus(
&OVRPSpace,
ovrpType,
Enable,
Timeout,
&OvrpOutRequestId);
memcpy(&OutRequestId, &OvrpOutRequestId, sizeof(uint64));
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("SetSpaceComponentStatus Request ID: %llu"), OutRequestId);
return static_cast<EOculusXRAnchorResult::Type>(Result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::GetSpaceComponentStatus(uint64 Space, EOculusXRSpaceComponentType SpaceComponentType, bool& OutEnabled, bool& OutChangePending)
{
const ovrpUInt64 OVRPSpace = Space;
ovrpBool OutOvrpEnabled = ovrpBool_False;
ovrpBool OutOvrpChangePending = ovrpBool_False;
ovrpSpaceComponentType ovrpType = ConvertToOvrpComponentType(SpaceComponentType);
const ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().GetSpaceComponentStatus(
&OVRPSpace,
ovrpType,
&OutOvrpEnabled,
&OutOvrpChangePending);
OutEnabled = (OutOvrpEnabled == ovrpBool_True);
OutChangePending = (OutOvrpChangePending == ovrpBool_True);
return static_cast<EOculusXRAnchorResult::Type>(Result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::GetSupportedAnchorComponents(uint64 Handle, TArray<EOculusXRSpaceComponentType>& OutSupportedTypes)
{
if (!FOculusXRHMDModule::GetPluginWrapper().GetInitialized())
{
return EOculusXRAnchorResult::Failure;
}
ovrpSpace ovrSpace = Handle;
TArray<ovrpSpaceComponentType> ovrComponentTypes;
ovrpUInt32 input = 0;
ovrpUInt32 output = 0;
ovrpResult enumerateResult = FOculusXRHMDModule::GetPluginWrapper().EnumerateSpaceSupportedComponents(&ovrSpace, input, &output, nullptr);
if (!OVRP_SUCCESS(enumerateResult))
{
return static_cast<EOculusXRAnchorResult::Type>(enumerateResult);
}
input = output;
ovrComponentTypes.SetNumZeroed(output);
enumerateResult = FOculusXRHMDModule::GetPluginWrapper().EnumerateSpaceSupportedComponents(&ovrSpace, input, &output, ovrComponentTypes.GetData());
if (!OVRP_SUCCESS(enumerateResult))
{
return static_cast<EOculusXRAnchorResult::Type>(enumerateResult);
}
OutSupportedTypes.SetNumZeroed(ovrComponentTypes.Num());
for (int i = 0; i < ovrComponentTypes.Num(); ++i)
{
OutSupportedTypes[i] = ConvertToUEComponentType(ovrComponentTypes[i]);
}
return static_cast<EOculusXRAnchorResult::Type>(enumerateResult);
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::SaveAnchor(uint64 Space,
EOculusXRSpaceStorageLocation StorageLocation,
EOculusXRSpaceStoragePersistenceMode StoragePersistenceMode, uint64& OutRequestId)
{
ovrpSpaceStorageLocation OvrpStorageLocation = ovrpSpaceStorageLocation_Local;
switch (StorageLocation)
{
case EOculusXRSpaceStorageLocation::Invalid:
OvrpStorageLocation = ovrpSpaceStorageLocation_Invalid;
break;
case EOculusXRSpaceStorageLocation::Local:
OvrpStorageLocation = ovrpSpaceStorageLocation_Local;
break;
case EOculusXRSpaceStorageLocation::Cloud:
OvrpStorageLocation = ovrpSpaceStorageLocation_Cloud;
break;
default:
break;
}
ovrpSpaceStoragePersistenceMode OvrpStoragePersistenceMode = ovrpSpaceStoragePersistenceMode_Invalid;
switch (StoragePersistenceMode)
{
case EOculusXRSpaceStoragePersistenceMode::Invalid:
OvrpStoragePersistenceMode = ovrpSpaceStoragePersistenceMode_Invalid;
break;
case EOculusXRSpaceStoragePersistenceMode::Indefinite:
OvrpStoragePersistenceMode = ovrpSpaceStoragePersistenceMode_Indefinite;
break;
default:
break;
}
ovrpUInt64 OvrpOutRequestId = 0;
const ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().SaveSpace(&Space, OvrpStorageLocation, OvrpStoragePersistenceMode, &OvrpOutRequestId);
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("Saving space with: SpaceID: %llu -- Location: %d -- Persistence: %d -- OutID: %llu"), Space, OvrpStorageLocation, OvrpStoragePersistenceMode, OvrpOutRequestId);
memcpy(&OutRequestId, &OvrpOutRequestId, sizeof(uint64));
if (OVRP_FAILURE(Result))
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("FOculusXRHMD::SaveAnchor failed with: SpaceID: %llu -- Location: %d -- Persistence: %d"), Space, OvrpStorageLocation, OvrpStoragePersistenceMode);
}
return static_cast<EOculusXRAnchorResult::Type>(Result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::SaveAnchorList(const TArray<uint64>& Spaces, EOculusXRSpaceStorageLocation StorageLocation, uint64& OutRequestId)
{
ovrpSpaceStorageLocation OvrpStorageLocation = ovrpSpaceStorageLocation_Local;
switch (StorageLocation)
{
case EOculusXRSpaceStorageLocation::Invalid:
OvrpStorageLocation = ovrpSpaceStorageLocation_Invalid;
break;
case EOculusXRSpaceStorageLocation::Local:
OvrpStorageLocation = ovrpSpaceStorageLocation_Local;
break;
case EOculusXRSpaceStorageLocation::Cloud:
OvrpStorageLocation = ovrpSpaceStorageLocation_Cloud;
break;
default:
break;
}
ovrpUInt64 OvrpOutRequestId = 0;
const ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().SaveSpaceList(Spaces.GetData(), Spaces.Num(), OvrpStorageLocation, &OvrpOutRequestId);
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("Saving space list: Location: %d -- OutID: %llu"), OvrpStorageLocation, OvrpOutRequestId);
for (auto& it : Spaces)
{
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("\tSpaceID: %llu"), it);
}
memcpy(&OutRequestId, &OvrpOutRequestId, sizeof(uint64));
if (OVRP_FAILURE(Result))
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("SaveSpaceList failed -- Result: %d"), Result);
}
return static_cast<EOculusXRAnchorResult::Type>(Result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::EraseAnchor(uint64 AnchorHandle,
EOculusXRSpaceStorageLocation StorageLocation, uint64& OutRequestId)
{
ovrpSpaceStorageLocation ovrpStorageLocation = ovrpSpaceStorageLocation_Local;
switch (StorageLocation)
{
case EOculusXRSpaceStorageLocation::Invalid:
ovrpStorageLocation = ovrpSpaceStorageLocation_Invalid;
break;
case EOculusXRSpaceStorageLocation::Local:
ovrpStorageLocation = ovrpSpaceStorageLocation_Local;
break;
default:;
}
ovrpUInt64 OvrpOutRequestId = 0;
const ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().EraseSpace(&AnchorHandle, ovrpStorageLocation, &OvrpOutRequestId);
memcpy(&OutRequestId, &OvrpOutRequestId, sizeof(uint64));
UE_LOG(LogOculusXRAnchors, Log, TEXT("Erasing anchor -- Handle: %llu -- Location: %d -- OutID: %llu"), AnchorHandle, ovrpStorageLocation, OvrpOutRequestId);
return static_cast<EOculusXRAnchorResult::Type>(Result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::QuerySpaces(const FOculusXRSpaceQueryInfo& QueryInfo, uint64& OutRequestId)
{
ovrpUInt64 OvrpOutRequestId = 0;
ovrpResult QuerySpacesResult = ovrpFailure;
ovrpSpaceQueryInfo ovrQueryInfo = ConvertToOVRPSpaceQueryInfo(QueryInfo);
QuerySpacesResult = FOculusXRHMDModule::GetPluginWrapper().QuerySpaces(&ovrQueryInfo, &OvrpOutRequestId);
memcpy(&OutRequestId, &OvrpOutRequestId, sizeof(uint64));
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("Query Spaces\n ovrpSpaceQueryInfo:\n\tQueryType: %d\n\tMaxQuerySpaces: %d\n\tTimeout: %f\n\tLocation: %d\n\tActionType: %d\n\tFilterType: %d\n\n\tRequest ID: %llu"),
ovrQueryInfo.queryType, ovrQueryInfo.maxQuerySpaces, (float)ovrQueryInfo.timeout, ovrQueryInfo.location, ovrQueryInfo.actionType, ovrQueryInfo.filterType, OutRequestId);
if (QueryInfo.FilterType == EOculusXRSpaceQueryFilterType::FilterByIds)
{
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("Query contains %d UUIDs"), QueryInfo.IDFilter.Num());
for (auto& it : QueryInfo.IDFilter)
{
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("UUID: %s"), *it.ToString());
}
}
else if (QueryInfo.FilterType == EOculusXRSpaceQueryFilterType::FilterByComponentType)
{
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("Query contains %d Component Types"), QueryInfo.ComponentFilter.Num());
for (auto& it : QueryInfo.ComponentFilter)
{
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("ComponentType: %s"), *UEnum::GetValueAsString(it));
}
}
return static_cast<EOculusXRAnchorResult::Type>(QuerySpacesResult);
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::ShareSpaces(const TArray<uint64>& Spaces, const TArray<uint64>& UserIds, uint64& OutRequestId)
{
TArray<const char*> stringStorage;
TArray<ovrpUser> OvrpUsers;
for (const auto& UserId : UserIds)
{
ovrpUser OvrUser;
ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().CreateSpaceUser(&UserId, &OvrUser);
if (OVRP_FAILURE(Result))
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to create space user from ID - %llu"), UserId);
continue;
}
OvrpUsers.Add(OvrUser);
}
ovrpUInt64 OvrpOutRequestId = 0;
const ovrpResult ShareSpacesResult = FOculusXRHMDModule::GetPluginWrapper().ShareSpaces(Spaces.GetData(), Spaces.Num(), OvrpUsers.GetData(), OvrpUsers.Num(), &OvrpOutRequestId);
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("Sharing space list -- OutID: %llu"), OvrpOutRequestId);
for (auto& User : OvrpUsers)
{
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("\tOvrpUser: %llu"), User);
ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().DestroySpaceUser(&User);
if (OVRP_FAILURE(Result))
{
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("Failed to destroy space user: %llu"), User);
continue;
}
}
for (auto& it : Spaces)
{
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("\tSpaceID: %llu"), it);
}
memcpy(&OutRequestId, &OvrpOutRequestId, sizeof(uint64));
return static_cast<EOculusXRAnchorResult::Type>(ShareSpacesResult);
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::GetSpaceContainerUUIDs(uint64 Space, TArray<FOculusXRUUID>& OutUUIDs)
{
TArray<ovrpUuid> ovrUuidArray;
// Get the number of elements in the container
ovrpSpaceContainer ovrSpaceContainer;
ovrSpaceContainer.uuidCapacityInput = 0;
ovrSpaceContainer.uuidCountOutput = 0;
ovrSpaceContainer.uuids = nullptr;
ovrpResult result = FOculusXRHMDModule::GetPluginWrapper().GetSpaceContainer(&Space, &ovrSpaceContainer);
if (OVRP_FAILURE(result))
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to get space container %d"), result);
return static_cast<EOculusXRAnchorResult::Type>(result);
}
// Retrieve the actual array of UUIDs
ovrUuidArray.SetNum(ovrSpaceContainer.uuidCountOutput);
ovrSpaceContainer.uuidCapacityInput = ovrSpaceContainer.uuidCountOutput;
ovrSpaceContainer.uuids = ovrUuidArray.GetData();
result = FOculusXRHMDModule::GetPluginWrapper().GetSpaceContainer(&Space, &ovrSpaceContainer);
if (OVRP_FAILURE(result))
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to get space container %d"), result);
return static_cast<EOculusXRAnchorResult::Type>(result);
}
// Write out the remaining UUIDs
OutUUIDs.Reserve(ovrUuidArray.Num());
for (auto& it : ovrUuidArray)
{
OutUUIDs.Add(FOculusXRUUID(it.data));
}
return EOculusXRAnchorResult::Success;
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::GetSpaceScenePlane(uint64 Space, FVector& OutPos, FVector& OutSize)
{
OutPos.X = OutPos.Y = OutPos.Z = 0.f;
OutSize.X = OutSize.Y = OutSize.Z = 0.f;
ovrpRectf rect;
const ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().GetSpaceBoundingBox2D(&Space, &rect);
if (OVRP_SUCCESS(Result))
{
// Convert to UE4's coordinates system
OutPos.Y = rect.Pos.x;
OutPos.Z = rect.Pos.y;
OutSize.Y = rect.Size.w;
OutSize.Z = rect.Size.h;
}
return static_cast<EOculusXRAnchorResult::Type>(Result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::GetSpaceSceneVolume(uint64 Space, FVector& OutPos, FVector& OutSize)
{
OutPos.X = OutPos.Y = OutPos.Z = 0.f;
OutSize.X = OutSize.Y = OutSize.Z = 0.f;
ovrpBoundsf bounds;
const ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().GetSpaceBoundingBox3D(&Space, &bounds);
if (OVRP_SUCCESS(Result))
{
// Convert from OpenXR's right-handed to Unreal's left-handed coordinate system.
// OpenXR Unreal
// | y | z
// | |
//z <----+ +----> x
// / /
// x/ y/
//
OutPos.X = -bounds.Pos.z;
OutPos.Y = bounds.Pos.x;
OutPos.Z = bounds.Pos.y;
// The position represents the corner of the volume which has the lowest value
// of each axis. Since we flipped the sign of one of the axes we need to adjust
// the position to the other side of the volume
OutPos.X -= bounds.Size.d;
// We keep the size positive for all dimensions
OutSize.X = bounds.Size.d;
OutSize.Y = bounds.Size.w;
OutSize.Z = bounds.Size.h;
}
return static_cast<EOculusXRAnchorResult::Type>(Result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::GetSpaceSemanticClassification(uint64 Space, TArray<FString>& OutSemanticClassifications)
{
OutSemanticClassifications.Empty();
const int32 maxByteSize = 1024;
char labelsChars[maxByteSize];
ovrpSemanticLabels labels;
labels.byteCapacityInput = maxByteSize;
labels.labels = labelsChars;
const ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().GetSpaceSemanticLabels(&Space, &labels);
if (OVRP_SUCCESS(Result))
{
FString labelsStr(labels.byteCountOutput, labels.labels);
labelsStr.ParseIntoArray(OutSemanticClassifications, TEXT(","));
}
return static_cast<EOculusXRAnchorResult::Type>(Result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::GetSpaceContainer(uint64 Space, TArray<FOculusXRUUID>& OutContainerUuids)
{
OutContainerUuids.Empty();
ovrpSpaceContainer container;
ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().GetSpaceContainer(&Space, &container);
if (OVRP_SUCCESS(Result))
{
TArray<ovrpUuid> uuids;
size_t size = container.uuidCountOutput;
uuids.InsertZeroed(0, size);
container.uuidCapacityInput = size;
container.uuids = uuids.GetData();
Result = FOculusXRHMDModule::GetPluginWrapper().GetSpaceContainer(&Space, &container);
if (OVRP_SUCCESS(Result))
{
OutContainerUuids.InsertZeroed(0, size);
for (size_t i = 0; i < size; i++)
{
OutContainerUuids[i] = FOculusXRUUID(uuids[i].data);
}
}
}
return static_cast<EOculusXRAnchorResult::Type>(Result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::GetSpaceBoundary2D(uint64 Space, TArray<FVector2f>& OutVertices)
{
TArray<ovrpVector2f> vertices;
// Get the number of elements in the container
ovrpBoundary2D boundary;
boundary.vertexCapacityInput = 0;
boundary.vertexCountOutput = 0;
boundary.vertices = nullptr;
ovrpResult result = FOculusXRHMDModule::GetPluginWrapper().GetSpaceBoundary2D(&Space, &boundary);
if (OVRP_FAILURE(result))
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to get space boundary 2d %d"), result);
return static_cast<EOculusXRAnchorResult::Type>(result);
}
// Retrieve the actual array of vertices
vertices.SetNum(boundary.vertexCountOutput);
boundary.vertexCapacityInput = boundary.vertexCountOutput;
boundary.vertices = vertices.GetData();
result = FOculusXRHMDModule::GetPluginWrapper().GetSpaceBoundary2D(&Space, &boundary);
if (OVRP_FAILURE(result))
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to get space boundary 2d %d"), result);
return static_cast<EOculusXRAnchorResult::Type>(result);
}
// Write out the vertices
OutVertices.Reserve(vertices.Num());
for (const auto& it : vertices)
{
OutVertices.Add(FVector2f(it.x, it.y));
}
return EOculusXRAnchorResult::Success;
}
} // namespace OculusXRAnchors