// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using Microsoft.MixedReality.Toolkit.SpatialAwareness; using Microsoft.MixedReality.Toolkit.Utilities; using UnityEngine; #if MSFT_OPENXR && (UNITY_STANDALONE_WIN || UNITY_WSA) using Microsoft.MixedReality.OpenXR; using Unity.Profiling; using UnityEngine.XR.OpenXR; #endif // MSFT_OPENXR && (UNITY_STANDALONE_WIN || UNITY_WSA) namespace Microsoft.MixedReality.Toolkit.XRSDK.OpenXR { [MixedRealityDataProvider( typeof(IMixedRealitySpatialAwarenessSystem), SupportedPlatforms.WindowsStandalone | SupportedPlatforms.WindowsUniversal, "OpenXR Spatial Mesh Observer", "Profiles/DefaultMixedRealitySpatialAwarenessMeshObserverProfile.asset", "MixedRealityToolkit.SDK", true, SupportedUnityXRPipelines.XRSDK)] [HelpURL("https://docs.microsoft.com/windows/mixed-reality/mrtk-unity/features/spatial-awareness/spatial-awareness-getting-started")] public class OpenXRSpatialAwarenessMeshObserver : GenericXRSDKSpatialMeshObserver { /// /// Constructor. /// /// The instance that loaded the service. /// Friendly name of the service. /// Service priority. Used to determine order of instantiation. /// The service's configuration profile. public OpenXRSpatialAwarenessMeshObserver( IMixedRealitySpatialAwarenessSystem spatialAwarenessSystem, string name = null, uint priority = DefaultPriority, BaseMixedRealityProfile profile = null) : base(spatialAwarenessSystem, name, priority, profile) { } protected override bool? IsActiveLoader => #if MSFT_OPENXR && (UNITY_STANDALONE_WIN || UNITY_WSA) LoaderHelpers.IsLoaderActive(); #else false; #endif // MSFT_OPENXR && (UNITY_STANDALONE_WIN || UNITY_WSA) #if MSFT_OPENXR && (UNITY_STANDALONE_WIN || UNITY_WSA) private static readonly ProfilerMarker ApplyUpdatedMeshDisplayOptionPerfMarker = new ProfilerMarker($"[MRTK] {nameof(OpenXRSpatialAwarenessMeshObserver)}.ApplyUpdatedMeshDisplayOption"); /// protected override void ApplyUpdatedMeshDisplayOption(SpatialAwarenessMeshDisplayOptions option) { using (ApplyUpdatedMeshDisplayOptionPerfMarker.Auto()) { SetMeshComputeSettings(option, LevelOfDetail); base.ApplyUpdatedMeshDisplayOption(option); } } private static readonly ProfilerMarker LookupTriangleDensityPerfMarker = new ProfilerMarker($"[MRTK] {nameof(OpenXRSpatialAwarenessMeshObserver)}.LookupTriangleDensity"); /// protected override int LookupTriangleDensity(SpatialAwarenessMeshLevelOfDetail levelOfDetail) { using (LookupTriangleDensityPerfMarker.Auto()) { if (Application.isPlaying && SetMeshComputeSettings(DisplayOption, levelOfDetail)) { return (int)levelOfDetail; } else { return base.LookupTriangleDensity(levelOfDetail); } } } private bool SetMeshComputeSettings(SpatialAwarenessMeshDisplayOptions option, SpatialAwarenessMeshLevelOfDetail levelOfDetail) { MeshComputeSettings settings = new MeshComputeSettings { #if !MSFT_OPENXR_1_4_0_OR_NEWER MeshType = (option == SpatialAwarenessMeshDisplayOptions.Visible) ? MeshType.Visual : MeshType.Collider, #endif VisualMeshLevelOfDetail = MapMRTKLevelOfDetailToOpenXR(levelOfDetail), MeshComputeConsistency = MeshComputeConsistency.OcclusionOptimized, }; return MeshSettings.TrySetMeshComputeSettings(settings); } private VisualMeshLevelOfDetail MapMRTKLevelOfDetailToOpenXR(SpatialAwarenessMeshLevelOfDetail levelOfDetail) { switch (levelOfDetail) { case SpatialAwarenessMeshLevelOfDetail.Coarse: return VisualMeshLevelOfDetail.Coarse; case SpatialAwarenessMeshLevelOfDetail.Medium: return VisualMeshLevelOfDetail.Medium; case SpatialAwarenessMeshLevelOfDetail.Fine: return VisualMeshLevelOfDetail.Fine; case SpatialAwarenessMeshLevelOfDetail.Unlimited: return VisualMeshLevelOfDetail.Unlimited; case SpatialAwarenessMeshLevelOfDetail.Custom: default: Debug.LogError($"Unsupported LevelOfDetail value {levelOfDetail}. Defaulting to {VisualMeshLevelOfDetail.Coarse}"); return VisualMeshLevelOfDetail.Coarse; } } #endif // MSFT_OPENXR && (UNITY_STANDALONE_WIN || UNITY_WSA) } }