// @lint-ignore-every LICENSELINT // Copyright Epic Games, Inc. All Rights Reserved. #include "OculusXRFunctionLibrary.h" #include "OculusXRHMDPrivate.h" #include "OculusXRHMD.h" #include "Logging/MessageLog.h" #define LOCTEXT_NAMESPACE "OculusFunctionLibrary" //------------------------------------------------------------------------------------------------- // UOculusXRFunctionLibrary //------------------------------------------------------------------------------------------------- UOculusXRFunctionLibrary::UOculusXRFunctionLibrary(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { } OculusXRHMD::FOculusXRHMD* UOculusXRFunctionLibrary::GetOculusXRHMD() { return OculusXRHMD::FOculusXRHMD::GetOculusXRHMD(); } void UOculusXRFunctionLibrary::GetPose(FRotator& DeviceRotation, FVector& DevicePosition, FVector& NeckPosition, bool bUseOrienationForPlayerCamera, bool bUsePositionForPlayerCamera, const FVector PositionScale) { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD && OculusXRHMD->IsHeadTrackingAllowed()) { FQuat HeadOrientation = FQuat::Identity; FVector HeadPosition = FVector::ZeroVector; OculusXRHMD->GetCurrentPose(OculusXRHMD->HMDDeviceId, HeadOrientation, HeadPosition); DeviceRotation = HeadOrientation.Rotator(); DevicePosition = HeadPosition; NeckPosition = OculusXRHMD->GetNeckPosition(HeadOrientation, HeadPosition); } else #endif // #if OCULUS_HMD_SUPPORTED_PLATFORMS { DeviceRotation = FRotator::ZeroRotator; DevicePosition = FVector::ZeroVector; NeckPosition = FVector::ZeroVector; } } void UOculusXRFunctionLibrary::SetBaseRotationAndBaseOffsetInMeters(FRotator Rotation, FVector BaseOffsetInMeters, EOrientPositionSelector::Type Options) { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { if ((Options == EOrientPositionSelector::Orientation) || (Options == EOrientPositionSelector::OrientationAndPosition)) { OculusXRHMD->SetBaseRotation(Rotation); } if ((Options == EOrientPositionSelector::Position) || (Options == EOrientPositionSelector::OrientationAndPosition)) { OculusXRHMD->SetBaseOffsetInMeters(BaseOffsetInMeters); } } #endif // OCULUS_HMD_SUPPORTED_PLATFORMS } void UOculusXRFunctionLibrary::GetBaseRotationAndBaseOffsetInMeters(FRotator& OutRotation, FVector& OutBaseOffsetInMeters) { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { OutRotation = OculusXRHMD->GetBaseRotation(); OutBaseOffsetInMeters = OculusXRHMD->GetBaseOffsetInMeters(); } else { OutRotation = FRotator::ZeroRotator; OutBaseOffsetInMeters = FVector::ZeroVector; } #endif // OCULUS_HMD_SUPPORTED_PLATFORMS } void UOculusXRFunctionLibrary::GetRawSensorData(FVector& AngularAcceleration, FVector& LinearAcceleration, FVector& AngularVelocity, FVector& LinearVelocity, float& TimeInSeconds, EOculusXRTrackedDeviceType DeviceType) { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr && OculusXRHMD->IsHMDActive()) { ovrpPoseStatef state; if (OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().GetNodePoseState3(ovrpStep_Render, OVRP_CURRENT_FRAMEINDEX, OculusXRHMD::ToOvrpNode(DeviceType), &state))) { AngularAcceleration = OculusXRHMD::ToFVector(state.AngularAcceleration); LinearAcceleration = OculusXRHMD::ToFVector(state.Acceleration); AngularVelocity = OculusXRHMD::ToFVector(state.AngularVelocity); LinearVelocity = OculusXRHMD::ToFVector(state.Velocity); TimeInSeconds = state.Time; } } #endif // OCULUS_HMD_SUPPORTED_PLATFORMS } bool UOculusXRFunctionLibrary::IsDeviceTracked(EOculusXRTrackedDeviceType DeviceType) { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr && OculusXRHMD->IsHMDActive()) { ovrpBool Present; if (OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().GetNodePresent2(OculusXRHMD::ToOvrpNode(DeviceType), &Present))) { return Present != ovrpBool_False; } else { return false; } } #endif // OCULUS_HMD_SUPPORTED_PLATFORMS return false; } void UOculusXRFunctionLibrary::GetSuggestedCpuAndGpuPerformanceLevels(EOculusXRProcessorPerformanceLevel& CpuPerfLevel, EOculusXRProcessorPerformanceLevel& GpuPerfLevel) { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr && OculusXRHMD->IsHMDActive()) { OculusXRHMD->GetSuggestedCpuAndGpuPerformanceLevels(CpuPerfLevel, GpuPerfLevel); } #endif // OCULUS_HMD_SUPPORTED_PLATFORMS } void UOculusXRFunctionLibrary::SetSuggestedCpuAndGpuPerformanceLevels(EOculusXRProcessorPerformanceLevel CpuPerfLevel, EOculusXRProcessorPerformanceLevel GpuPerfLevel) { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr && OculusXRHMD->IsHMDActive()) { OculusXRHMD->SetSuggestedCpuAndGpuPerformanceLevels(CpuPerfLevel, GpuPerfLevel); } #endif // OCULUS_HMD_SUPPORTED_PLATFORMS } void UOculusXRFunctionLibrary::SetCPUAndGPULevels(int CPULevel, int GPULevel) { // Deprecated. Please use Get/SetSuggestedCpuAndGpuPerformanceLevels instead. } bool UOculusXRFunctionLibrary::GetUserProfile(FOculusXRHmdUserProfile& Profile) { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { OculusXRHMD::FOculusXRHMD::UserProfile Data; if (OculusXRHMD->GetUserProfile(Data)) { Profile.Name = ""; Profile.Gender = "Unknown"; Profile.PlayerHeight = 0.0f; Profile.EyeHeight = Data.EyeHeight; Profile.IPD = Data.IPD; Profile.NeckToEyeDistance = FVector2D(Data.EyeDepth, 0.0f); return true; } } #endif // OCULUS_HMD_SUPPORTED_PLATFORMS return false; } void UOculusXRFunctionLibrary::SetBaseRotationAndPositionOffset(FRotator BaseRot, FVector PosOffset, EOrientPositionSelector::Type Options) { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { if (Options == EOrientPositionSelector::Orientation || Options == EOrientPositionSelector::OrientationAndPosition) { OculusXRHMD->SetBaseRotation(BaseRot); } } #endif // OCULUS_HMD_SUPPORTED_PLATFORMS } void UOculusXRFunctionLibrary::GetBaseRotationAndPositionOffset(FRotator& OutRot, FVector& OutPosOffset) { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { OutRot = OculusXRHMD->GetBaseRotation(); OutPosOffset = FVector::ZeroVector; } #endif // OCULUS_HMD_SUPPORTED_PLATFORMS } void UOculusXRFunctionLibrary::AddLoadingSplashScreen(class UTexture2D* Texture, FVector TranslationInMeters, FRotator Rotation, FVector2D SizeInMeters, FRotator DeltaRotation, bool bClearBeforeAdd) { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { OculusXRHMD::FSplash* Splash = OculusXRHMD->GetSplash(); if (Splash) { if (bClearBeforeAdd) { Splash->ClearSplashes(); } FOculusXRSplashDesc Desc; Desc.LoadingTexture = Texture; Desc.QuadSizeInMeters = SizeInMeters; Desc.TransformInMeters = FTransform(Rotation, TranslationInMeters); Desc.DeltaRotation = FQuat(DeltaRotation); Splash->AddSplash(Desc); } } #endif // OCULUS_HMD_SUPPORTED_PLATFORMS } void UOculusXRFunctionLibrary::ClearLoadingSplashScreens() { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { OculusXRHMD::FSplash* Splash = OculusXRHMD->GetSplash(); if (Splash) { Splash->ClearSplashes(); } } #endif // OCULUS_HMD_SUPPORTED_PLATFORMS } bool UOculusXRFunctionLibrary::HasInputFocus() { #if OCULUS_HMD_SUPPORTED_PLATFORMS const OculusXRHMD::FOculusXRHMD* const OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr && OculusXRHMD->IsHMDActive()) { ovrpBool HasFocus; if (OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().GetAppHasInputFocus(&HasFocus))) { return HasFocus != ovrpBool_False; } } #endif // OCULUS_HMD_SUPPORTED_PLATFORMS return false; } bool UOculusXRFunctionLibrary::HasSystemOverlayPresent() { #if OCULUS_HMD_SUPPORTED_PLATFORMS const OculusXRHMD::FOculusXRHMD* const OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr && OculusXRHMD->IsHMDActive()) { ovrpBool HasFocus; if (OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().GetAppHasInputFocus(&HasFocus))) { return HasFocus == ovrpBool_False; } } #endif // OCULUS_HMD_SUPPORTED_PLATFORMS return false; } void UOculusXRFunctionLibrary::GetGPUUtilization(bool& IsGPUAvailable, float& GPUUtilization) { GPUUtilization = 0.0f; #if OCULUS_HMD_SUPPORTED_PLATFORMS const OculusXRHMD::FOculusXRHMD* const OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { ovrpBool bIsSupported = ovrpBool_False; if (OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().IsPerfMetricsSupported(ovrpPerfMetrics_System_GpuUtilPercentage_Float, &bIsSupported)) && bIsSupported == ovrpBool_True) { if (OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().GetPerfMetricsFloat(ovrpPerfMetrics_System_GpuUtilPercentage_Float, &GPUUtilization))) { IsGPUAvailable = true; GPUUtilization *= 100; } } } #endif // OCULUS_HMD_SUPPORTED_PLATFORMS } float UOculusXRFunctionLibrary::GetGPUFrameTime() { float FrameTime = 0; #if OCULUS_HMD_SUPPORTED_PLATFORMS const OculusXRHMD::FOculusXRHMD* const OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { ovrpBool bIsSupported = ovrpBool_False; if (OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().IsPerfMetricsSupported(ovrpPerfMetrics_App_GpuTime_Float, &bIsSupported)) && bIsSupported == ovrpBool_True) { if (OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().GetPerfMetricsFloat(ovrpPerfMetrics_App_GpuTime_Float, &FrameTime))) { return FrameTime * 1000; } } } #endif // OCULUS_HMD_SUPPORTED_PLATFORMS return 0.0f; } EOculusXRFoveatedRenderingMethod UOculusXRFunctionLibrary::GetFoveatedRenderingMethod() { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { ovrpBool enabled; if (OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().GetFoveationEyeTracked(&enabled))) { return enabled == ovrpBool_True ? EOculusXRFoveatedRenderingMethod::EyeTrackedFoveatedRendering : EOculusXRFoveatedRenderingMethod::FixedFoveatedRendering; } } #endif // OCULUS_HMD_SUPPORTED_PLATFORMS return EOculusXRFoveatedRenderingMethod::FixedFoveatedRendering; } void UOculusXRFunctionLibrary::SetFoveatedRenderingMethod(EOculusXRFoveatedRenderingMethod Method) { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { OculusXRHMD->SetFoveatedRenderingMethod(Method); } #endif // OCULUS_HMD_SUPPORTED_PLATFORMS } void UOculusXRFunctionLibrary::SetFoveatedRenderingLevel(EOculusXRFoveatedRenderingLevel level, bool isDynamic) { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { OculusXRHMD->SetFoveatedRenderingLevel(level, isDynamic); } #endif // OCULUS_HMD_SUPPORTED_PLATFORMS } EOculusXRFoveatedRenderingLevel UOculusXRFunctionLibrary::GetFoveatedRenderingLevel() { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { ovrpTiledMultiResLevel Lvl; if (OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().GetTiledMultiResLevel(&Lvl))) { return (EOculusXRFoveatedRenderingLevel)Lvl; } } #endif // OCULUS_HMD_SUPPORTED_PLATFORMS return EOculusXRFoveatedRenderingLevel::Off; } bool UOculusXRFunctionLibrary::GetEyeTrackedFoveatedRenderingSupported() { #if OCULUS_HMD_SUPPORTED_PLATFORMS // Always return false on other engine releases, since they don't have FDM offset support #ifdef WITH_OCULUS_BRANCH OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { ovrpBool Supported; if (OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().GetFoveationEyeTrackedSupported(&Supported))) { return Supported == ovrpBool_True; } } #endif // WITH_OCULUS_BRANCH #endif // OCULUS_HMD_SUPPORTED_PLATFORMS return false; } FString UOculusXRFunctionLibrary::GetDeviceName() { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { const char* NameString; if (OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().GetSystemProductName2(&NameString)) && NameString) { return FString(NameString); } } #endif return FString(); } EOculusXRDeviceType UOculusXRFunctionLibrary::GetDeviceType() { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { if (OculusXRHMD->GetSettings()) { switch (OculusXRHMD->GetSettings()->SystemHeadset) { case ovrpSystemHeadset_Oculus_Quest: return EOculusXRDeviceType::OculusQuest_Deprecated; case ovrpSystemHeadset_Oculus_Quest_2: return EOculusXRDeviceType::OculusQuest2; case ovrpSystemHeadset_Meta_Quest_Pro: return EOculusXRDeviceType::MetaQuestPro; case ovrpSystemHeadset_Meta_Quest_3: return EOculusXRDeviceType::MetaQuest3; case ovrpSystemHeadset_Rift_CV1: return EOculusXRDeviceType::Rift; case ovrpSystemHeadset_Rift_S: return EOculusXRDeviceType::Rift_S; case ovrpSystemHeadset_Oculus_Link_Quest: return EOculusXRDeviceType::Quest_Link_Deprecated; case ovrpSystemHeadset_Oculus_Link_Quest_2: return EOculusXRDeviceType::Quest2_Link; case ovrpSystemHeadset_Meta_Link_Quest_Pro: return EOculusXRDeviceType::MetaQuestProLink; case ovrpSystemHeadset_Meta_Link_Quest_3: return EOculusXRDeviceType::MetaQuest3Link; default: break; } } } #endif return EOculusXRDeviceType::OculusUnknown; } EOculusXRControllerType UOculusXRFunctionLibrary::GetControllerType(EControllerHand deviceHand) { #if OCULUS_HMD_SUPPORTED_PLATFORMS auto getOVRPHand = [](EControllerHand hand) { switch (hand) { case EControllerHand::Left: return ovrpHand::ovrpHand_Left; case EControllerHand::Right: return ovrpHand::ovrpHand_Right; default: return ovrpHand::ovrpHand_None; } return ovrpHand::ovrpHand_None; }; auto getEControllerType = [](ovrpInteractionProfile profile) { switch (profile) { case ovrpInteractionProfile::ovrpInteractionProfile_Touch: return EOculusXRControllerType::MetaQuestTouch; case ovrpInteractionProfile::ovrpInteractionProfile_TouchPro: return EOculusXRControllerType::MetaQuestTouchPro; case ovrpInteractionProfile::ovrpInteractionProfile_TouchPlus: return EOculusXRControllerType::MetaQuestTouchPlus; default: return EOculusXRControllerType::None; } return EOculusXRControllerType::None; }; ovrpInteractionProfile interactionProfile = ovrpInteractionProfile::ovrpInteractionProfile_None; ovrpHand hand = getOVRPHand(deviceHand); if (hand == ovrpHand::ovrpHand_None) return EOculusXRControllerType::Unknown; if (OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().GetCurrentInteractionProfile(hand, &interactionProfile))) { return getEControllerType(interactionProfile); } return EOculusXRControllerType::Unknown; #endif return EOculusXRControllerType::Unknown; } TArray UOculusXRFunctionLibrary::GetAvailableDisplayFrequencies() { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { int NumberOfFrequencies; if (OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().GetSystemDisplayAvailableFrequencies(nullptr, &NumberOfFrequencies))) { TArray freqArray; freqArray.SetNum(NumberOfFrequencies); FOculusXRHMDModule::GetPluginWrapper().GetSystemDisplayAvailableFrequencies(freqArray.GetData(), &NumberOfFrequencies); return freqArray; } } #endif return TArray(); } float UOculusXRFunctionLibrary::GetCurrentDisplayFrequency() { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { float Frequency; if (OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().GetSystemDisplayFrequency2(&Frequency))) { return Frequency; } } #endif return 0.0f; } void UOculusXRFunctionLibrary::SetDisplayFrequency(float RequestedFrequency) { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { FOculusXRHMDModule::GetPluginWrapper().SetSystemDisplayFrequency(RequestedFrequency); } #endif } void UOculusXRFunctionLibrary::EnablePositionTracking(bool bPositionTracking) { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { FOculusXRHMDModule::GetPluginWrapper().SetTrackingPositionEnabled2(bPositionTracking); } #endif } void UOculusXRFunctionLibrary::EnableOrientationTracking(bool bOrientationTracking) { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { FOculusXRHMDModule::GetPluginWrapper().SetTrackingOrientationEnabled2(bOrientationTracking); } #endif } void UOculusXRFunctionLibrary::SetColorScaleAndOffset(FLinearColor ColorScale, FLinearColor ColorOffset, bool bApplyToAllLayers) { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { OculusXRHMD->SetColorScaleAndOffset(ColorScale, ColorOffset, bApplyToAllLayers); } #endif } class IStereoLayers* UOculusXRFunctionLibrary::GetStereoLayers() { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { return OculusXRHMD; } #endif // OCULUS_HMD_SUPPORTED_PLATFORMS return nullptr; } /** Helper that converts EOculusXRBoundaryType to ovrpBoundaryType */ #if OCULUS_HMD_SUPPORTED_PLATFORMS static ovrpBoundaryType ToOvrpBoundaryType(EOculusXRBoundaryType Source) { switch (Source) { case EOculusXRBoundaryType::Boundary_PlayArea: return ovrpBoundary_PlayArea; case EOculusXRBoundaryType::Boundary_Outer: default: return ovrpBoundary_Outer; } } #endif // OCULUS_HMD_SUPPORTED_PLATFORMS bool UOculusXRFunctionLibrary::IsGuardianConfigured() { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { ovrpBool boundaryConfigured; return OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().GetBoundaryConfigured2(&boundaryConfigured)) && boundaryConfigured; } #endif return false; } bool UOculusXRFunctionLibrary::IsGuardianDisplayed() { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { ovrpBool boundaryVisible; return OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().GetBoundaryVisible2(&boundaryVisible)) && boundaryVisible; } #endif return false; } TArray UOculusXRFunctionLibrary::GetGuardianPoints(EOculusXRBoundaryType BoundaryType, bool UsePawnSpace /* = false */) { TArray BoundaryPointList; #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { ovrpBool bBoundaryConfigured = false; if (OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().GetBoundaryConfigured2(&bBoundaryConfigured)) && bBoundaryConfigured) { ovrpBoundaryType obt = ToOvrpBoundaryType(BoundaryType); int NumPoints = 0; if (OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().GetBoundaryGeometry3(obt, nullptr, &NumPoints))) { //allocate points const int BufferSize = NumPoints; ovrpVector3f* BoundaryPoints = new ovrpVector3f[BufferSize]; if (OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().GetBoundaryGeometry3(obt, BoundaryPoints, &NumPoints))) { NumPoints = FMath::Min(BufferSize, NumPoints); check(NumPoints <= BufferSize); // For static analyzer BoundaryPointList.Reserve(NumPoints); for (int i = 0; i < NumPoints; i++) { FVector point; if (UsePawnSpace) { point = OculusXRHMD->ConvertVector_M2U(BoundaryPoints[i]); } else { point = OculusXRHMD->ScaleAndMovePointWithPlayer(BoundaryPoints[i]); } BoundaryPointList.Add(point); } } delete[] BoundaryPoints; } } } #endif return BoundaryPointList; } FVector UOculusXRFunctionLibrary::GetGuardianDimensions(EOculusXRBoundaryType BoundaryType) { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { ovrpBoundaryType obt = ToOvrpBoundaryType(BoundaryType); ovrpVector3f Dimensions; if (OVRP_FAILURE(FOculusXRHMDModule::GetPluginWrapper().GetBoundaryDimensions2(obt, &Dimensions))) return FVector::ZeroVector; Dimensions.z *= -1.0; return OculusXRHMD->ConvertVector_M2U(Dimensions); } #endif return FVector::ZeroVector; } FTransform UOculusXRFunctionLibrary::GetPlayAreaTransform() { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { ovrpBool bBoundaryConfigured = false; if (OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().GetBoundaryConfigured2(&bBoundaryConfigured)) && bBoundaryConfigured) { int NumPoints = 4; ovrpVector3f BoundaryPoints[4]; if (OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().GetBoundaryGeometry3(ovrpBoundary_PlayArea, BoundaryPoints, &NumPoints))) { FVector ConvertedPoints[4]; for (int i = 0; i < NumPoints; i++) { ConvertedPoints[i] = OculusXRHMD->ScaleAndMovePointWithPlayer(BoundaryPoints[i]); } float metersScale = OculusXRHMD->GetWorldToMetersScale(); FVector Edge = ConvertedPoints[1] - ConvertedPoints[0]; float Angle = FMath::Acos((Edge).GetSafeNormal() | FVector::RightVector); FQuat Rotation(FVector::UpVector, Edge.X < 0 ? Angle : -Angle); FVector Position = (ConvertedPoints[0] + ConvertedPoints[1] + ConvertedPoints[2] + ConvertedPoints[3]) / 4; FVector Scale(FVector::Distance(ConvertedPoints[3], ConvertedPoints[0]) / metersScale, FVector::Distance(ConvertedPoints[1], ConvertedPoints[0]) / metersScale, 1.0); return FTransform(Rotation, Position, Scale); } } } #endif return FTransform(); } FOculusXRGuardianTestResult UOculusXRFunctionLibrary::GetPointGuardianIntersection(const FVector Point, EOculusXRBoundaryType BoundaryType) { FOculusXRGuardianTestResult InteractionInfo; memset(&InteractionInfo, 0, sizeof(FOculusXRGuardianTestResult)); #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { ovrpVector3f OvrpPoint = OculusXRHMD->WorldLocationToOculusPoint(Point); ovrpBoundaryType OvrpBoundaryType = ToOvrpBoundaryType(BoundaryType); ovrpBoundaryTestResult InteractionResult; if (OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().TestBoundaryPoint2(OvrpPoint, OvrpBoundaryType, &InteractionResult))) { InteractionInfo.IsTriggering = (InteractionResult.IsTriggering != 0); InteractionInfo.ClosestDistance = OculusXRHMD->ConvertFloat_M2U(InteractionResult.ClosestDistance); InteractionInfo.ClosestPoint = OculusXRHMD->ScaleAndMovePointWithPlayer(InteractionResult.ClosestPoint); InteractionInfo.ClosestPointNormal = OculusXRHMD->ConvertVector_M2U(InteractionResult.ClosestPointNormal); InteractionInfo.DeviceType = EOculusXRTrackedDeviceType::None; } } #endif return InteractionInfo; } FOculusXRGuardianTestResult UOculusXRFunctionLibrary::GetNodeGuardianIntersection(EOculusXRTrackedDeviceType DeviceType, EOculusXRBoundaryType BoundaryType) { FOculusXRGuardianTestResult InteractionInfo; memset(&InteractionInfo, 0, sizeof(FOculusXRGuardianTestResult)); #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { ovrpNode OvrpNode = OculusXRHMD::ToOvrpNode(DeviceType); ovrpBoundaryType OvrpBoundaryType = ToOvrpBoundaryType(BoundaryType); ovrpBoundaryTestResult TestResult; if (OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().TestBoundaryNode2(OvrpNode, ovrpBoundary_PlayArea, &TestResult)) && TestResult.IsTriggering) { InteractionInfo.IsTriggering = true; InteractionInfo.DeviceType = OculusXRHMD::ToEOculusXRTrackedDeviceType(OvrpNode); InteractionInfo.ClosestDistance = OculusXRHMD->ConvertFloat_M2U(TestResult.ClosestDistance); InteractionInfo.ClosestPoint = OculusXRHMD->ScaleAndMovePointWithPlayer(TestResult.ClosestPoint); InteractionInfo.ClosestPointNormal = OculusXRHMD->ConvertVector_M2U(TestResult.ClosestPointNormal); } } #endif return InteractionInfo; } void UOculusXRFunctionLibrary::SetGuardianVisibility(bool GuardianVisible) { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { FOculusXRHMDModule::GetPluginWrapper().SetBoundaryVisible2(GuardianVisible); } #endif } bool UOculusXRFunctionLibrary::GetSystemHmd3DofModeEnabled() { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { ovrpBool enabled; return OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().GetSystemHmd3DofModeEnabled(&enabled)) && enabled; } #endif return false; } EOculusXRColorSpace UOculusXRFunctionLibrary::GetHmdColorDesc() { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { ovrpColorSpace HmdColorSpace; if (OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().GetHmdColorDesc(&HmdColorSpace))) { return (EOculusXRColorSpace)HmdColorSpace; } } #endif return EOculusXRColorSpace::Unknown; } void UOculusXRFunctionLibrary::SetClientColorDesc(EOculusXRColorSpace ColorSpace) { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { ovrpColorSpace ClientColorSpace = (ovrpColorSpace)ColorSpace; #if PLATFORM_ANDROID if (ClientColorSpace == ovrpColorSpace_Unknown) { ClientColorSpace = ovrpColorSpace_Quest; } #endif FOculusXRHMDModule::GetPluginWrapper().SetClientColorDesc(ClientColorSpace); } #endif } void UOculusXRFunctionLibrary::SetLocalDimmingOn(bool LocalDimmingOn) { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { UE_LOG(LogHMD, Log, TEXT("SetLocalDimmingOn %d"), LocalDimmingOn); FOculusXRHMDModule::GetPluginWrapper().SetLocalDimming(LocalDimmingOn); } #endif } bool UOculusXRFunctionLibrary::IsPassthroughSupported() { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { ovrpInsightPassthroughCapabilityFlags capabilities; if (OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().GetPassthroughCapabilityFlags(&capabilities))) { return (capabilities & ovrpInsightPassthroughCapabilityFlags::ovrpInsightPassthroughCapabilityFlags_Passthrough) == ovrpInsightPassthroughCapabilityFlags::ovrpInsightPassthroughCapabilityFlags_Passthrough; } return false; } #endif return false; } bool UOculusXRFunctionLibrary::IsColorPassthroughSupported() { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { ovrpInsightPassthroughCapabilityFlags capabilities; if (OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().GetPassthroughCapabilityFlags(&capabilities))) { return (capabilities & ovrpInsightPassthroughCapabilityFlags::ovrpInsightPassthroughCapabilityFlags_Color) == ovrpInsightPassthroughCapabilityFlags::ovrpInsightPassthroughCapabilityFlags_Color; } return false; } #endif return false; } void UOculusXRFunctionLibrary::StartEnvironmentDepth() { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { int CreateFlags = 0; OculusXRHMD->StartEnvironmentDepth(CreateFlags); } #endif } void UOculusXRFunctionLibrary::StopEnvironmentDepth() { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { OculusXRHMD->StopEnvironmentDepth(); } #endif } bool UOculusXRFunctionLibrary::IsEnvironmentDepthStarted() { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { return OculusXRHMD->IsEnvironmentDepthStarted(); } #endif return false; } void UOculusXRFunctionLibrary::SetEnvironmentDepthHandRemoval(bool RemoveHands) { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { OculusXRHMD->SetEnvironmentDepthHandRemoval(RemoveHands); } #endif } void UOculusXRFunctionLibrary::SetXROcclusionsMode(UObject* WorldContextObject, EOculusXROcclusionsMode Mode) { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { OculusXRHMD->EnableHardOcclusions(Mode == EOculusXROcclusionsMode::HardOcclusions); } #if defined(WITH_OCULUS_BRANCH) WorldContextObject->GetWorld()->Scene->SetEnableXRPassthroughSoftOcclusions(Mode == EOculusXROcclusionsMode::SoftOcclusions); #else ensureMsgf(Mode != EOculusXROcclusionsMode::SoftOcclusions, TEXT("Soft occlusions are only supported with the Oculus branch of the Unreal Engine")); #endif // defined(WITH_OCULUS_BRANCH) #endif // OCULUS_HMD_SUPPORTED_PLATFORMS } void UOculusXRFunctionLibrary::SetEyeBufferSharpenType(EOculusXREyeBufferSharpenType EyeBufferSharpenType) { #if OCULUS_HMD_SUPPORTED_PLATFORMS OculusXRHMD::FOculusXRHMD* OculusXRHMD = GetOculusXRHMD(); if (OculusXRHMD != nullptr) { switch (EyeBufferSharpenType) { case EOculusXREyeBufferSharpenType::SLST_Normal: FOculusXRHMDModule::GetPluginWrapper().SetEyeBufferSharpenType(ovrpLayerSubmitFlag_EfficientSharpen); break; case EOculusXREyeBufferSharpenType::SLST_Quality: FOculusXRHMDModule::GetPluginWrapper().SetEyeBufferSharpenType(ovrpLayerSubmitFlag_QualitySharpen); break; case EOculusXREyeBufferSharpenType::SLST_Auto: FOculusXRHMDModule::GetPluginWrapper().SetEyeBufferSharpenType(ovrpLayerSubmitFlag_AutoLayerFilter); break; default: FOculusXRHMDModule::GetPluginWrapper().SetEyeBufferSharpenType(ovrpLayerSubmitFlags(0)); break; } } #endif } bool UOculusXRFunctionLibrary::IsPassthroughRecommended() { #if OCULUS_HMD_SUPPORTED_PLATFORMS const OculusXRHMD::FOculusXRHMD* OculusHMD = GetOculusXRHMD(); if (OculusHMD != nullptr) { ovrpPassthroughPreferences Preferences; if (OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().GetPassthroughPreferences(&Preferences))) { return (Preferences.Flags & ovrpPassthroughPreferenceFlags::ovrpPassthroughPreferenceFlags_DefaultToActive) == ovrpPassthroughPreferenceFlags::ovrpPassthroughPreferenceFlags_DefaultToActive; }; } #endif return false; } #undef LOCTEXT_NAMESPACE