620 lines
21 KiB
C++
620 lines
21 KiB
C++
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
|
|
#include "OculusXRSystemInfoExtensionPlugin.h"
|
|
#include "IOpenXRHMDModule.h"
|
|
#include "OculusXRAssetDirectory.h"
|
|
#include "OculusXRXRFunctions.h"
|
|
#include "OculusXROpenXRUtilities.h"
|
|
#include "OculusXRHMDRuntimeSettings.h"
|
|
|
|
DEFINE_LOG_CATEGORY(LogOculusSystemInfoExtensionPlugin);
|
|
|
|
namespace OculusXR
|
|
{
|
|
enum EOculusAsset
|
|
{
|
|
LeftTouchRiftS,
|
|
RightTouchRiftS,
|
|
LeftTouchQuest2,
|
|
RightTouchQuest2,
|
|
LeftTouchQuestPro,
|
|
RightTouchQuestPro,
|
|
LeftTouchQuest3,
|
|
RightTouchQuest3,
|
|
OculusAssetTotal
|
|
};
|
|
|
|
struct FRenderableDevice
|
|
{
|
|
FString Device;
|
|
EOculusXRDeviceType MinDeviceRange;
|
|
EOculusXRDeviceType MaxDeviceRange;
|
|
FSoftObjectPath MeshAssetRef;
|
|
};
|
|
|
|
static FRenderableDevice RenderableDevices[] = {
|
|
#if PLATFORM_ANDROID
|
|
// Quest 1 & 2
|
|
{ "/user/hand/left", EOculusXRDeviceType::OculusQuest_Deprecated, EOculusXRDeviceType::OculusQuest2, FOculusAssetDirectory::AssetListing[LeftTouchQuest2] },
|
|
{ "/user/hand/right", EOculusXRDeviceType::OculusQuest_Deprecated, EOculusXRDeviceType::OculusQuest2, FOculusAssetDirectory::AssetListing[RightTouchQuest2] },
|
|
|
|
// Quest Pro
|
|
{ "/user/hand/left", EOculusXRDeviceType::MetaQuestPro, EOculusXRDeviceType::MetaQuestPro, FOculusAssetDirectory::AssetListing[LeftTouchQuestPro] },
|
|
{ "/user/hand/right", EOculusXRDeviceType::MetaQuestPro, EOculusXRDeviceType::MetaQuestPro, FOculusAssetDirectory::AssetListing[RightTouchQuestPro] },
|
|
|
|
// Quest 3 & 3s
|
|
{ "/user/hand/left", EOculusXRDeviceType::MetaQuest3, EOculusXRDeviceType::MetaQuest3S, FOculusAssetDirectory::AssetListing[LeftTouchQuest3] },
|
|
{ "/user/hand/right", EOculusXRDeviceType::MetaQuest3, EOculusXRDeviceType::MetaQuest3S, FOculusAssetDirectory::AssetListing[RightTouchQuest3] },
|
|
#else
|
|
// PC - Rift S
|
|
{ "/user/hand/left", EOculusXRDeviceType::Rift_S, EOculusXRDeviceType::Rift_S, FOculusAssetDirectory::AssetListing[LeftTouchRiftS] },
|
|
{ "/user/hand/right", EOculusXRDeviceType::Rift_S, EOculusXRDeviceType::Rift_S, FOculusAssetDirectory::AssetListing[RightTouchRiftS] },
|
|
|
|
// PC - Quest 1 & 2
|
|
{ "/user/hand/left", EOculusXRDeviceType::Quest_Link_Deprecated, EOculusXRDeviceType::Quest2_Link, FOculusAssetDirectory::AssetListing[LeftTouchQuest2] },
|
|
{ "/user/hand/right", EOculusXRDeviceType::Quest_Link_Deprecated, EOculusXRDeviceType::Quest2_Link, FOculusAssetDirectory::AssetListing[RightTouchQuest2] },
|
|
|
|
// PC - Quest Pro
|
|
{ "/user/hand/left", EOculusXRDeviceType::MetaQuestProLink, EOculusXRDeviceType::MetaQuestProLink, FOculusAssetDirectory::AssetListing[LeftTouchQuestPro] },
|
|
{ "/user/hand/right", EOculusXRDeviceType::MetaQuestProLink, EOculusXRDeviceType::MetaQuestProLink, FOculusAssetDirectory::AssetListing[RightTouchQuestPro] },
|
|
|
|
// Quest 3 & 3s
|
|
{ "/user/hand/left", EOculusXRDeviceType::MetaQuest3Link, EOculusXRDeviceType::MetaQuest3SLink, FOculusAssetDirectory::AssetListing[LeftTouchQuest3] },
|
|
{ "/user/hand/right", EOculusXRDeviceType::MetaQuest3Link, EOculusXRDeviceType::MetaQuest3SLink, FOculusAssetDirectory::AssetListing[RightTouchQuest3] },
|
|
#endif
|
|
};
|
|
static uint32 RenderableDeviceCount = sizeof(RenderableDevices) / sizeof(RenderableDevices[0]);
|
|
|
|
FSoftObjectPath FindDeviceMesh(FString DevicePath, EOculusXRDeviceType SystemDeviceType)
|
|
{
|
|
if (DevicePath == "")
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
for (uint32 DeviceIndex = 0; DeviceIndex < RenderableDeviceCount; ++DeviceIndex)
|
|
{
|
|
const FRenderableDevice& RenderableDevice = RenderableDevices[DeviceIndex];
|
|
if (RenderableDevice.Device == DevicePath)
|
|
{
|
|
// If we have information about the current headset, load the model based of the headset information, otherwise load defaults.
|
|
if (SystemDeviceType != EOculusXRDeviceType::OculusUnknown)
|
|
{
|
|
if (SystemDeviceType >= RenderableDevice.MinDeviceRange && SystemDeviceType <= RenderableDevice.MaxDeviceRange)
|
|
{
|
|
return RenderableDevice.MeshAssetRef;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return RenderableDevice.MeshAssetRef;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
namespace // anonymous
|
|
{
|
|
void AppendToChain(XrBaseOutStructure* ToAppend, XrBaseOutStructure* Chain)
|
|
{
|
|
while (Chain->next != XR_NULL_HANDLE)
|
|
{
|
|
if (Chain->next == ToAppend)
|
|
{
|
|
return;
|
|
}
|
|
Chain = Chain->next;
|
|
}
|
|
Chain->next = ToAppend;
|
|
}
|
|
|
|
bool IsEqualUuid(const XrUuidEXT& a, const XrUuidEXT& b)
|
|
{
|
|
return FMemory::Memcmp(&a, &b, sizeof(XrUuidEXT)) == 0;
|
|
}
|
|
|
|
XrColorSpaceFB ToXrColorSpace(EOculusXRColorSpace ColorSpace)
|
|
{
|
|
XrColorSpaceFB XrColorSpace = XR_COLOR_SPACE_UNMANAGED_FB;
|
|
switch (ColorSpace)
|
|
{
|
|
case EOculusXRColorSpace::Unmanaged:
|
|
XrColorSpace = XR_COLOR_SPACE_UNMANAGED_FB;
|
|
break;
|
|
case EOculusXRColorSpace::Rec_2020:
|
|
XrColorSpace = XR_COLOR_SPACE_REC2020_FB;
|
|
break;
|
|
case EOculusXRColorSpace::Rec_709:
|
|
XrColorSpace = XR_COLOR_SPACE_REC709_FB;
|
|
break;
|
|
case EOculusXRColorSpace::Rift_CV1:
|
|
XrColorSpace = XR_COLOR_SPACE_RIFT_CV1_FB;
|
|
break;
|
|
case EOculusXRColorSpace::Rift_S:
|
|
XrColorSpace = XR_COLOR_SPACE_RIFT_S_FB;
|
|
break;
|
|
case EOculusXRColorSpace::Quest:
|
|
XrColorSpace = XR_COLOR_SPACE_QUEST_FB;
|
|
break;
|
|
case EOculusXRColorSpace::P3:
|
|
XrColorSpace = XR_COLOR_SPACE_P3_FB;
|
|
break;
|
|
case EOculusXRColorSpace::Adobe_RGB:
|
|
XrColorSpace = XR_COLOR_SPACE_ADOBE_RGB_FB;
|
|
break;
|
|
}
|
|
return XrColorSpace;
|
|
}
|
|
|
|
EOculusXRColorSpace ToOculusXRColorSpace(XrColorSpaceFB InXrColorSpace)
|
|
{
|
|
EOculusXRColorSpace ColorSpace = EOculusXRColorSpace::Unknown;
|
|
|
|
switch (InXrColorSpace)
|
|
{
|
|
case XR_COLOR_SPACE_UNMANAGED_FB:
|
|
ColorSpace = EOculusXRColorSpace::Unmanaged;
|
|
break;
|
|
case XR_COLOR_SPACE_REC2020_FB:
|
|
ColorSpace = EOculusXRColorSpace::Rec_2020;
|
|
break;
|
|
case XR_COLOR_SPACE_REC709_FB:
|
|
ColorSpace = EOculusXRColorSpace::Rec_709;
|
|
break;
|
|
case XR_COLOR_SPACE_RIFT_CV1_FB:
|
|
ColorSpace = EOculusXRColorSpace::Rift_CV1;
|
|
break;
|
|
case XR_COLOR_SPACE_RIFT_S_FB:
|
|
ColorSpace = EOculusXRColorSpace::Rift_S;
|
|
break;
|
|
case XR_COLOR_SPACE_QUEST_FB:
|
|
ColorSpace = EOculusXRColorSpace::Quest;
|
|
break;
|
|
case XR_COLOR_SPACE_P3_FB:
|
|
ColorSpace = EOculusXRColorSpace::P3;
|
|
break;
|
|
case XR_COLOR_SPACE_ADOBE_RGB_FB:
|
|
ColorSpace = EOculusXRColorSpace::Adobe_RGB;
|
|
break;
|
|
default:
|
|
ColorSpace = EOculusXRColorSpace::Unknown;
|
|
}
|
|
return ColorSpace;
|
|
}
|
|
} // namespace
|
|
|
|
FSystemInfoExtensionPlugin::FSystemInfoExtensionPlugin()
|
|
: Instance(XR_NULL_HANDLE)
|
|
, Session(XR_NULL_HANDLE)
|
|
, SystemId(XR_NULL_SYSTEM_ID)
|
|
, bExtHeadsetIdAvailable(false)
|
|
, SystemHeadsetId{}
|
|
, bSystemHeadsetIdValid(false)
|
|
, SystemProductName{}
|
|
, bExtDisplayRefreshAvailible(false)
|
|
, bExtColorspaceAvailable(false)
|
|
, bExtPassthroughAvailable(false)
|
|
, bExtPassthroughPreferencesAvailable(false)
|
|
{
|
|
}
|
|
|
|
bool FSystemInfoExtensionPlugin::GetRequiredExtensions(TArray<const ANSICHAR*>& OutExtensions)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
bool FSystemInfoExtensionPlugin::GetOptionalExtensions(TArray<const ANSICHAR*>& OutExtensions)
|
|
{
|
|
OutExtensions.Add(XR_META_HEADSET_ID_EXTENSION_NAME);
|
|
OutExtensions.Add(XR_FB_DISPLAY_REFRESH_RATE_EXTENSION_NAME);
|
|
OutExtensions.Add(XR_FB_COLOR_SPACE_EXTENSION_NAME);
|
|
OutExtensions.Add(XR_META_PASSTHROUGH_PREFERENCES_EXTENSION_NAME);
|
|
|
|
return true;
|
|
}
|
|
|
|
void FSystemInfoExtensionPlugin::PostCreateInstance(XrInstance InInstance)
|
|
{
|
|
Instance = InInstance;
|
|
}
|
|
|
|
const void* FSystemInfoExtensionPlugin::OnCreateInstance(class IOpenXRHMDModule* InModule, const void* InNext)
|
|
{
|
|
if (InModule != nullptr)
|
|
{
|
|
bExtHeadsetIdAvailable = InModule->IsExtensionEnabled(XR_META_HEADSET_ID_EXTENSION_NAME);
|
|
bExtDisplayRefreshAvailible = InModule->IsExtensionEnabled(XR_FB_DISPLAY_REFRESH_RATE_EXTENSION_NAME);
|
|
bExtColorspaceAvailable = InModule->IsExtensionEnabled(XR_FB_COLOR_SPACE_EXTENSION_NAME);
|
|
bExtPassthroughAvailable = InModule->IsExtensionEnabled(XR_FB_PASSTHROUGH_EXTENSION_NAME);
|
|
bExtPassthroughPreferencesAvailable = InModule->IsExtensionEnabled(XR_META_PASSTHROUGH_PREFERENCES_EXTENSION_NAME);
|
|
}
|
|
return IOculusXRExtensionPlugin::OnCreateInstance(InModule, InNext);
|
|
}
|
|
|
|
void FSystemInfoExtensionPlugin::PostCreateSession(XrSession InSession)
|
|
{
|
|
Session = InSession;
|
|
XrSystemGetInfo SystemGetInfo = { XR_TYPE_SYSTEM_GET_INFO };
|
|
SystemGetInfo.formFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY;
|
|
|
|
ENSURE_XRCMD(xrGetSystem(Instance, &SystemGetInfo, &SystemId));
|
|
|
|
XrSystemHeadsetIdPropertiesMETA SystemHeadsetIdProperties = { XR_TYPE_SYSTEM_HEADSET_ID_PROPERTIES_META };
|
|
|
|
XrSystemProperties SystemProperties = { XR_TYPE_SYSTEM_PROPERTIES };
|
|
|
|
if (bExtHeadsetIdAvailable)
|
|
{
|
|
AppendToChain(
|
|
reinterpret_cast<XrBaseOutStructure*>(&SystemHeadsetIdProperties),
|
|
reinterpret_cast<XrBaseOutStructure*>(&SystemProperties));
|
|
}
|
|
|
|
ENSURE_XRCMD(xrGetSystemProperties(Instance, SystemId, &SystemProperties));
|
|
|
|
if (bExtHeadsetIdAvailable)
|
|
{
|
|
SystemHeadsetId = SystemHeadsetIdProperties.id;
|
|
bSystemHeadsetIdValid = true;
|
|
}
|
|
|
|
SystemProductName = SystemProperties.systemName;
|
|
SystemDeviceType = GetSystemHeadsetType();
|
|
|
|
const UOculusXRHMDRuntimeSettings* HMDSettings = GetDefault<UOculusXRHMDRuntimeSettings>();
|
|
SetColorSpace(HMDSettings->ColorSpace);
|
|
|
|
ControllerPaths.TouchControllerPath = FOpenXRPath("/interaction_profiles/oculus/touch_controller");
|
|
ControllerPaths.TouchControllerProPath = FOpenXRPath("/interaction_profiles/facebook/touch_controller_pro");
|
|
ControllerPaths.TouchControllerPlusPath = FOpenXRPath("/interaction_profiles/meta/touch_controller_plus");
|
|
ControllerPaths.LeftHandPath = FOpenXRPath("/user/hand/left");
|
|
ControllerPaths.RightHandPath = FOpenXRPath("/user/hand/right");
|
|
}
|
|
|
|
bool FSystemInfoExtensionPlugin::GetControllerModel(XrInstance InInstance, XrPath InInteractionProfile, XrPath InDevicePath, FSoftObjectPath& OutPath)
|
|
{
|
|
if (InDevicePath == XR_NULL_PATH)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
const FString DevicePath = FOpenXRPath(InDevicePath).ToString();
|
|
OutPath = FindDeviceMesh(DevicePath, SystemDeviceType);
|
|
return OutPath.IsValid();
|
|
}
|
|
|
|
void FSystemInfoExtensionPlugin::GetControllerModelsForCooking(TArray<FSoftObjectPath>& OutPaths)
|
|
{
|
|
OutPaths.Append(FOculusAssetDirectory::AssetListing, OculusAssetTotal);
|
|
}
|
|
|
|
EOculusXRDeviceType FSystemInfoExtensionPlugin::GetDeviceType()
|
|
{
|
|
return SystemDeviceType;
|
|
}
|
|
|
|
EOculusXRDeviceType FSystemInfoExtensionPlugin::GetSystemHeadsetType()
|
|
{
|
|
// Magic legacy conversion paths from ovrplugin
|
|
|
|
#if defined(__ANDROID__)
|
|
|
|
constexpr XrUuidEXT XR_HEADSET_ID_QUEST = {
|
|
{ 0x4c, 0xa2, 0xf7, 0x94, 0xaf, 0x6a, 0x46, 0x9d, 0xbb, 0xe5, 0x1f, 0x7f, 0xce, 0xef, 0x7b, 0xad }
|
|
};
|
|
constexpr XrUuidEXT XR_HEADSET_ID_QUEST2 = {
|
|
{ 0x30, 0x64, 0xf2, 0x39, 0x15, 0xed, 0x47, 0x22, 0xa6, 0x59, 0x5e, 0xa1, 0xec, 0xd8, 0x99, 0xc2 }
|
|
};
|
|
// Quest Pro
|
|
constexpr XrUuidEXT XR_HEADSET_ID_QUEST_PRO = {
|
|
{ 0xb5, 0x84, 0x43, 0xc9, 0xdf, 0x86, 0x40, 0xcd, 0x89, 0x18, 0x2a, 0x27, 0x8e, 0x18, 0xab, 0x71 }
|
|
};
|
|
// Quest 3
|
|
constexpr XrUuidEXT XR_HEADSET_ID_QUEST_3 = {
|
|
{ 0x08, 0x27, 0x46, 0xba, 0xa0, 0x71, 0x4c, 0xf7, 0x8f, 0x87, 0xba, 0xde, 0x5c, 0xce, 0x43, 0xce }
|
|
};
|
|
// Quest 3S
|
|
constexpr XrUuidEXT XR_HEADSET_ID_QUEST_3S = {
|
|
{ 0x95, 0x10, 0x49, 0x2b, 0x0d, 0x42, 0x48, 0x72, 0xbc, 0xf4, 0xfb, 0x1a, 0x8d, 0xef, 0x6f, 0x0e }
|
|
};
|
|
#else
|
|
// PC Headsets
|
|
constexpr XrUuidEXT XR_HEADSET_ID_RIFT_CV1 = {
|
|
{ 0xbe, 0x4f, 0x8d, 0x7c, 0x8e, 0x33, 0x4d, 0xa2, 0xbf, 0x54, 0xda, 0xd9, 0xea, 0x57, 0x54, 0x9f }
|
|
};
|
|
constexpr XrUuidEXT XR_HEADSET_ID_RIFT_S = {
|
|
{ 0x0d, 0x42, 0xaa, 0xc6, 0x7f, 0x1c, 0x46, 0x27, 0x9c, 0xc5, 0x2c, 0xba, 0x8b, 0x0b, 0xaf, 0xfc }
|
|
};
|
|
constexpr XrUuidEXT XR_HEADSET_ID_QUEST_LINK = {
|
|
{ 0x2f, 0x03, 0x26, 0xc0, 0x09, 0xeb, 0x4d, 0xa9, 0x9a, 0x88, 0x4c, 0xc2, 0x93, 0x53, 0x0a, 0xb2 }
|
|
};
|
|
constexpr XrUuidEXT XR_HEADSET_ID_QUEST2_LINK = {
|
|
{ 0x52, 0x50, 0x78, 0xa5, 0x5a, 0xab, 0x4d, 0xc9, 0xb8, 0x02, 0x1e, 0xbd, 0x6c, 0x7c, 0xff, 0xf4 }
|
|
};
|
|
// Quest Pro
|
|
constexpr XrUuidEXT XR_HEADSET_ID_QUEST_PRO_LINK = {
|
|
{ 0x99, 0x09, 0x86, 0xc7, 0x9b, 0xad, 0x47, 0x5f, 0x89, 0x83, 0xc1, 0xc7, 0xbd, 0x49, 0xad, 0x51 }
|
|
};
|
|
// Quest 3
|
|
constexpr XrUuidEXT XR_HEADSET_ID_QUEST_3_LINK = {
|
|
{ 0x64, 0x09, 0xe3, 0xb3, 0x50, 0x89, 0x4e, 0xd6, 0x86, 0x8e, 0xaa, 0xed, 0x82, 0xda, 0x36, 0x76 }
|
|
};
|
|
// Quest 3S
|
|
constexpr XrUuidEXT XR_HEADSET_ID_QUEST_3S_LINK = {
|
|
{ 0x8c, 0x2e, 0xc4, 0x47, 0xac, 0x73, 0x41, 0x9f, 0x90, 0x96, 0x36, 0xa7, 0x72, 0x33, 0x78, 0x62 }
|
|
};
|
|
#endif // defined(__ANDROID__)
|
|
|
|
#if defined(__ANDROID__)
|
|
if (bSystemHeadsetIdValid)
|
|
{
|
|
UE_LOG(LogOculusSystemInfoExtensionPlugin, Log, TEXT("UID %x %x %x %x - %x %x %x %x - %x %x %x %x - %x %x %x %x"),
|
|
SystemHeadsetId.data[0],
|
|
SystemHeadsetId.data[1],
|
|
SystemHeadsetId.data[2],
|
|
SystemHeadsetId.data[3],
|
|
|
|
SystemHeadsetId.data[4],
|
|
SystemHeadsetId.data[5],
|
|
SystemHeadsetId.data[6],
|
|
SystemHeadsetId.data[7],
|
|
|
|
SystemHeadsetId.data[8],
|
|
SystemHeadsetId.data[9],
|
|
SystemHeadsetId.data[10],
|
|
SystemHeadsetId.data[11],
|
|
|
|
SystemHeadsetId.data[12],
|
|
SystemHeadsetId.data[13],
|
|
SystemHeadsetId.data[14],
|
|
SystemHeadsetId.data[15]);
|
|
|
|
if (IsEqualUuid(SystemHeadsetId, XR_HEADSET_ID_QUEST))
|
|
{
|
|
return EOculusXRDeviceType::OculusQuest_Deprecated;
|
|
}
|
|
else if (IsEqualUuid(SystemHeadsetId, XR_HEADSET_ID_QUEST2))
|
|
{
|
|
return EOculusXRDeviceType::OculusQuest2;
|
|
}
|
|
else if (IsEqualUuid(SystemHeadsetId, XR_HEADSET_ID_QUEST_PRO))
|
|
{
|
|
return EOculusXRDeviceType::MetaQuestPro;
|
|
}
|
|
else if (IsEqualUuid(SystemHeadsetId, XR_HEADSET_ID_QUEST_3))
|
|
{
|
|
return EOculusXRDeviceType::MetaQuest3;
|
|
}
|
|
else if (IsEqualUuid(SystemHeadsetId, XR_HEADSET_ID_QUEST_3S))
|
|
{
|
|
return EOculusXRDeviceType::MetaQuest3S;
|
|
}
|
|
else
|
|
{
|
|
return EOculusXRDeviceType::OculusQuest2; // return Quest 2 as the default headset type
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (SystemProductName == TEXT("Oculus Quest"))
|
|
{
|
|
return EOculusXRDeviceType::OculusQuest_Deprecated;
|
|
}
|
|
else if (SystemProductName == TEXT("Oculus Quest2"))
|
|
{
|
|
return EOculusXRDeviceType::OculusQuest2;
|
|
}
|
|
else if (SystemProductName == TEXT("Meta Quest Pro") || SystemProductName == TEXT("Oculus Headset1"))
|
|
{
|
|
return EOculusXRDeviceType::MetaQuestPro;
|
|
}
|
|
else if (SystemProductName == TEXT("Meta Quest 3") || SystemProductName == TEXT("Oculus Headset2"))
|
|
{
|
|
return EOculusXRDeviceType::MetaQuest3;
|
|
}
|
|
else if (SystemProductName == TEXT("Meta Quest 3S") || SystemProductName == TEXT("Oculus Headset3"))
|
|
{
|
|
return EOculusXRDeviceType::MetaQuest3S;
|
|
}
|
|
else
|
|
{
|
|
return EOculusXRDeviceType::OculusQuest2; // return Quest 2 as the default headset type
|
|
}
|
|
}
|
|
#else
|
|
if (bSystemHeadsetIdValid)
|
|
{
|
|
if (IsEqualUuid(SystemHeadsetId, XR_HEADSET_ID_RIFT_CV1))
|
|
{
|
|
return EOculusXRDeviceType::Rift;
|
|
}
|
|
else if (IsEqualUuid(SystemHeadsetId, XR_HEADSET_ID_RIFT_S))
|
|
{
|
|
return EOculusXRDeviceType::Rift_S;
|
|
}
|
|
else if (IsEqualUuid(SystemHeadsetId, XR_HEADSET_ID_QUEST_LINK))
|
|
{
|
|
return EOculusXRDeviceType::Quest_Link_Deprecated;
|
|
}
|
|
else if (IsEqualUuid(SystemHeadsetId, XR_HEADSET_ID_QUEST2_LINK))
|
|
{
|
|
return EOculusXRDeviceType::Quest2_Link;
|
|
}
|
|
else if (IsEqualUuid(SystemHeadsetId, XR_HEADSET_ID_QUEST_PRO_LINK))
|
|
{
|
|
return EOculusXRDeviceType::MetaQuestProLink;
|
|
}
|
|
else if (IsEqualUuid(SystemHeadsetId, XR_HEADSET_ID_QUEST_3_LINK))
|
|
{
|
|
return EOculusXRDeviceType::MetaQuest3Link;
|
|
}
|
|
else if (IsEqualUuid(SystemHeadsetId, XR_HEADSET_ID_QUEST_3S_LINK))
|
|
{
|
|
return EOculusXRDeviceType::MetaQuest3SLink;
|
|
}
|
|
else
|
|
{
|
|
return EOculusXRDeviceType::Quest2_Link; // return Quest 2 (over Link) as the default headset type
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (SystemProductName == TEXT("Oculus Rift S"))
|
|
{
|
|
return EOculusXRDeviceType::Rift_S;
|
|
}
|
|
else if (SystemProductName == TEXT("Oculus Rift CV1"))
|
|
{
|
|
return EOculusXRDeviceType::Rift;
|
|
}
|
|
else
|
|
{
|
|
return EOculusXRDeviceType::Quest2_Link; // return Quest 2 (over Link) as the default headset type
|
|
}
|
|
}
|
|
#endif // defined(__ANDROID__)
|
|
}
|
|
|
|
TArray<float> FSystemInfoExtensionPlugin::GetSystemDisplayAvailableFrequencies()
|
|
{
|
|
TArray<float> DisplayFrequencies;
|
|
|
|
if (bExtDisplayRefreshAvailible)
|
|
{
|
|
check(xrEnumerateDisplayRefreshRatesFB.GetValue() != nullptr);
|
|
|
|
uint32 TotalRates = 0;
|
|
ENSURE_XRCMD(xrEnumerateDisplayRefreshRatesFB.GetValue()(Session, 0, &TotalRates, nullptr));
|
|
|
|
DisplayFrequencies.Init(0, TotalRates);
|
|
|
|
ENSURE_XRCMD(xrEnumerateDisplayRefreshRatesFB.GetValue()(Session, TotalRates, &TotalRates, DisplayFrequencies.GetData()));
|
|
}
|
|
|
|
return DisplayFrequencies;
|
|
}
|
|
|
|
float FSystemInfoExtensionPlugin::GetSystemDisplayFrequency()
|
|
{
|
|
float Frequency = 0.0f;
|
|
|
|
if (bExtDisplayRefreshAvailible)
|
|
{
|
|
check(xrGetDisplayRefreshRateFB.GetValue() != nullptr);
|
|
ENSURE_XRCMD(xrGetDisplayRefreshRateFB.GetValue()(Session, &Frequency));
|
|
}
|
|
return Frequency;
|
|
}
|
|
|
|
void FSystemInfoExtensionPlugin::SetSystemDisplayFrequency(float DisplayFrequency)
|
|
{
|
|
if (bExtDisplayRefreshAvailible)
|
|
{
|
|
check(xrRequestDisplayRefreshRateFB.GetValue() != nullptr);
|
|
ENSURE_XRCMD(xrRequestDisplayRefreshRateFB.GetValue()(Session, DisplayFrequency));
|
|
}
|
|
}
|
|
|
|
void FSystemInfoExtensionPlugin::SetColorSpace(EOculusXRColorSpace ColorSpace)
|
|
{
|
|
if (bExtColorspaceAvailable)
|
|
{
|
|
XrColorSpaceFB XrColorSpace = ToXrColorSpace(ColorSpace);
|
|
check(xrSetColorSpaceFB.GetValue() != nullptr);
|
|
ENSURE_XRCMD(xrSetColorSpaceFB.GetValue()(Session, XrColorSpace));
|
|
}
|
|
}
|
|
|
|
EOculusXRColorSpace FSystemInfoExtensionPlugin::GetColorSpace()
|
|
{
|
|
EOculusXRColorSpace ColorSpace = EOculusXRColorSpace::Unknown;
|
|
if (bExtColorspaceAvailable)
|
|
{
|
|
XrSystemColorSpacePropertiesFB ColorSpaceProperties = { XR_TYPE_SYSTEM_COLOR_SPACE_PROPERTIES_FB };
|
|
XrSystemProperties SystemProperties = { XR_TYPE_SYSTEM_PROPERTIES, &ColorSpaceProperties };
|
|
|
|
ENSURE_XRCMD(xrGetSystemProperties(Instance, SystemId, &SystemProperties));
|
|
ColorSpace = ToOculusXRColorSpace(ColorSpaceProperties.colorSpace);
|
|
}
|
|
return ColorSpace;
|
|
}
|
|
|
|
bool FSystemInfoExtensionPlugin::IsPassthroughSupported()
|
|
{
|
|
if (bExtPassthroughAvailable)
|
|
{
|
|
XrSystemPassthroughProperties2FB PassthroughProperties = { XR_TYPE_SYSTEM_PASSTHROUGH_PROPERTIES2_FB };
|
|
XrSystemProperties SystemProperties = { XR_TYPE_SYSTEM_PROPERTIES, &PassthroughProperties };
|
|
|
|
XR_ENSURE(xrGetSystemProperties(Instance, SystemId, &SystemProperties));
|
|
|
|
return (PassthroughProperties.capabilities & XR_PASSTHROUGH_CAPABILITY_BIT_FB) == XR_PASSTHROUGH_CAPABILITY_BIT_FB;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool FSystemInfoExtensionPlugin::IsColorPassthroughSupported()
|
|
{
|
|
if (bExtPassthroughAvailable)
|
|
{
|
|
XrSystemPassthroughProperties2FB PassthroughProperties = { XR_TYPE_SYSTEM_PASSTHROUGH_PROPERTIES2_FB };
|
|
XrSystemProperties SystemProperties = { XR_TYPE_SYSTEM_PROPERTIES, &PassthroughProperties };
|
|
|
|
XR_ENSURE(xrGetSystemProperties(Instance, SystemId, &SystemProperties));
|
|
|
|
return (PassthroughProperties.capabilities & XR_PASSTHROUGH_CAPABILITY_COLOR_BIT_FB) == XR_PASSTHROUGH_CAPABILITY_COLOR_BIT_FB;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool FSystemInfoExtensionPlugin::IsPassthroughRecommended()
|
|
{
|
|
if (bExtPassthroughPreferencesAvailable && OculusXR::xrGetPassthroughPreferencesMETA.IsSet())
|
|
{
|
|
XrPassthroughPreferencesMETA PassthroughPreferences = { XR_TYPE_PASSTHROUGH_PREFERENCES_META };
|
|
|
|
ENSURE_XRCMD(OculusXR::xrGetPassthroughPreferencesMETA.GetValue()(Session, &PassthroughPreferences));
|
|
|
|
return (PassthroughPreferences.flags & XR_PASSTHROUGH_PREFERENCE_DEFAULT_TO_ACTIVE_BIT_META) == XR_PASSTHROUGH_PREFERENCE_DEFAULT_TO_ACTIVE_BIT_META;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
EOculusXRControllerType FSystemInfoExtensionPlugin::GetControllerType(EControllerHand DeviceHand)
|
|
{
|
|
EOculusXRControllerType ControllerType = EOculusXRControllerType::Unknown;
|
|
IXRTrackingSystem* TrackingSystem = GetOpenXRTrackingSystem();
|
|
|
|
if (TrackingSystem != nullptr)
|
|
{
|
|
if (DeviceHand != EControllerHand::Left || DeviceHand != EControllerHand::Right)
|
|
{
|
|
XrInteractionProfileState Profile;
|
|
Profile.type = XR_TYPE_INTERACTION_PROFILE_STATE;
|
|
Profile.next = nullptr;
|
|
const XrPath TopLevelUserPath = DeviceHand != EControllerHand::Left ? ControllerPaths.LeftHandPath : ControllerPaths.RightHandPath;
|
|
XR_ENSURE(xrGetCurrentInteractionProfile(Session, TopLevelUserPath, &Profile));
|
|
|
|
const XrPath InteractionProfile = Profile.interactionProfile;
|
|
if (InteractionProfile == ControllerPaths.TouchControllerPath)
|
|
{
|
|
ControllerType = EOculusXRControllerType::MetaQuestTouch;
|
|
}
|
|
else if (InteractionProfile == ControllerPaths.TouchControllerProPath)
|
|
{
|
|
ControllerType = EOculusXRControllerType::MetaQuestTouchPro;
|
|
}
|
|
else if (InteractionProfile == ControllerPaths.TouchControllerPlusPath)
|
|
{
|
|
ControllerType = EOculusXRControllerType::MetaQuestTouchPlus;
|
|
}
|
|
}
|
|
}
|
|
return ControllerType;
|
|
}
|
|
|
|
} // namespace OculusXR
|