using System; using System.Collections.Generic; using System.Runtime.InteropServices; using Unity.Collections; using UnityEngine.Scripting; using UnityEngine.XR.ARSubsystems; namespace UnityEngine.XR.ARKit { /// /// This subsystem provides implementing functionality for the XROcclusionSubsystem class. /// [Preserve] class ARKitOcclusionSubsystem : XROcclusionSubsystem { /// /// Register the ARKit occlusion subsystem if iOS and not the editor. /// [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] static void Register() { if (!Api.AtLeast13_0()) return; const string k_SubsystemId = "ARKit-Occlusion"; var occlusionSubsystemCinfo = new XROcclusionSubsystemCinfo() { id = k_SubsystemId, providerType = typeof(ARKitOcclusionSubsystem.ARKitProvider), subsystemTypeOverride = typeof(ARKitOcclusionSubsystem), humanSegmentationStencilImageSupportedDelegate = NativeApi.UnityARKit_OcclusionProvider_DoesSupportBodySegmentationStencil, humanSegmentationDepthImageSupportedDelegate = NativeApi.UnityARKit_OcclusionProvider_DoesSupportBodySegmentationDepth, environmentDepthImageSupportedDelegate = NativeApi.UnityARKit_OcclusionProvider_DoesSupportEnvironmentDepth, environmentDepthConfidenceImageSupportedDelegate = NativeApi.UnityARKit_OcclusionProvider_DoesSupportEnvironmentDepth, environmentDepthTemporalSmoothingSupportedDelegate = NativeApi.UnityARKit_OcclusionProvider_DoesSupportEnvironmentDepthTemporalSmoothing }; XROcclusionSubsystem.Register(occlusionSubsystemCinfo); } /// /// The implementation provider class. /// class ARKitProvider : XROcclusionSubsystem.Provider { /// /// The shader property name for the human segmentation stencil texture. /// /// /// The shader property name for the human segmentation stencil texture. /// const string k_TextureHumanStencilPropertyName = "_HumanStencil"; /// /// The shader property name for the human segmentation depth texture. /// /// /// The shader property name for the human segmentation depth texture. /// const string k_TextureHumanDepthPropertyName = "_HumanDepth"; /// /// The shader property name for the environment depth texture. /// /// /// The shader property name for the environment depth texture. /// const string k_TextureEnvironmentDepthPropertyName = "_EnvironmentDepth"; /// /// The shader property name for the environment depth confidence texture. /// /// /// The shader property name for the environment depth confidence texture. /// const string k_TextureEnvironmentDepthConfidencePropertyName = "_EnvironmentDepthConfidence"; /// /// The shader keyword for enabling human segmentation rendering. /// /// /// The shader keyword for enabling human segmentation rendering. /// const string k_HumanEnabledMaterialKeyword = "ARKIT_HUMAN_SEGMENTATION_ENABLED"; /// /// The shader keyword for enabling environment depth rendering. /// /// /// The shader keyword for enabling environment depth rendering. /// const string k_EnvironmentDepthEnabledMaterialKeyword = "ARKIT_ENVIRONMENT_DEPTH_ENABLED"; /// /// The shader property name identifier for the human segmentation stencil texture. /// /// /// The shader property name identifier for the human segmentation stencil texture. /// static readonly int k_TextureHumanStencilPropertyId = Shader.PropertyToID(k_TextureHumanStencilPropertyName); /// /// The shader property name identifier for the human segmentation depth texture. /// /// /// The shader property name identifier for the human segmentation depth texture. /// static readonly int k_TextureHumanDepthPropertyId = Shader.PropertyToID(k_TextureHumanDepthPropertyName); /// /// The shader property name identifier for the environment depth texture. /// /// /// The shader property name identifier for the environment depth texture. /// static readonly int k_TextureEnvironmentDepthPropertyId = Shader.PropertyToID(k_TextureEnvironmentDepthPropertyName); /// /// The shader property name identifier for the environment depth texture. /// /// /// The shader property name identifier for the environment depth texture. /// static readonly int k_TextureEnvironmentDepthConfidencePropertyId = Shader.PropertyToID(k_TextureEnvironmentDepthConfidencePropertyName); /// /// The shader keywords for enabling human segmentation rendering. /// /// /// The shader keywords for enabling human segmentation rendering. /// static readonly List m_HumanEnabledMaterialKeywords = new List() {k_HumanEnabledMaterialKeyword}; /// /// The shader keywords for enabling environment depth rendering. /// /// /// The shader keywords for enabling environment depth rendering. /// static readonly List m_EnvironmentDepthEnabledMaterialKeywords = new List() {k_EnvironmentDepthEnabledMaterialKeyword}; /// /// The shader keywords for enabling environment depth rendering. /// /// /// The shader keywords for enabling environment depth rendering. /// static readonly List m_AllDisabledMaterialKeywords = new List() {k_HumanEnabledMaterialKeyword, k_EnvironmentDepthEnabledMaterialKeyword}; /// /// The shader keywords for enabling environment depth rendering. /// OcclusionPreferenceMode m_OcclusionPreferenceMode; /// /// Construct the implementation provider. /// public ARKitProvider() => NativeApi.UnityARKit_OcclusionProvider_Construct(k_TextureHumanStencilPropertyId, k_TextureHumanDepthPropertyId, k_TextureEnvironmentDepthPropertyId, k_TextureEnvironmentDepthConfidencePropertyId); /// /// Start the provider. /// public override void Start() => NativeApi.UnityARKit_OcclusionProvider_Start(); /// /// Stop the provider. /// public override void Stop() => NativeApi.UnityARKit_OcclusionProvider_Stop(); /// /// Destroy the provider. /// public override void Destroy() => NativeApi.UnityARKit_OcclusionProvider_Destruct(); /// /// Property to get or set the requested human segmentation stencil mode. /// /// /// The requested human segmentation stencil mode. /// public override HumanSegmentationStencilMode requestedHumanStencilMode { get => NativeApi.UnityARKit_OcclusionProvider_GetRequestedSegmentationStencilMode(); set { NativeApi.UnityARKit_OcclusionProvider_SetRequestedSegmentationStencilMode(value); Api.SetFeatureRequested(Feature.PeopleOcclusionStencil, value.Enabled()); } } /// /// Property to get the current human segmentation stencil mode. /// public override HumanSegmentationStencilMode currentHumanStencilMode => NativeApi.UnityARKit_OcclusionProvider_GetCurrentSegmentationStencilMode(); /// /// Property to get or set the requested human segmentation depth mode. /// /// /// The requested human segmentation depth mode. /// /// Thrown when setting the human segmentation depth mode /// to `enabled` if the implementation does not support human segmentation. public override HumanSegmentationDepthMode requestedHumanDepthMode { get => NativeApi.UnityARKit_OcclusionProvider_GetRequestedSegmentationDepthMode(); set { NativeApi.UnityARKit_OcclusionProvider_SetRequestedSegmentationDepthMode(value); Api.SetFeatureRequested(Feature.PeopleOcclusionDepth, value.Enabled()); } } /// /// Property to get the current segmentation depth mode. /// public override HumanSegmentationDepthMode currentHumanDepthMode => NativeApi.UnityARKit_OcclusionProvider_GetCurrentSegmentationDepthMode(); /// /// Property to get or set the requested environment depth mode. /// /// /// The requested environment depth mode. /// public override EnvironmentDepthMode requestedEnvironmentDepthMode { get => NativeApi.UnityARKit_OcclusionProvider_GetRequestedEnvironmentDepthMode(); set { NativeApi.UnityARKit_OcclusionProvider_SetRequestedEnvironmentDepthMode(value); Api.SetFeatureRequested(Feature.EnvironmentDepth, value.Enabled()); } } /// /// Property to get the current environment depth mode. /// public override EnvironmentDepthMode currentEnvironmentDepthMode => NativeApi.UnityARKit_OcclusionProvider_GetCurrentEnvironmentDepthMode(); public override bool environmentDepthTemporalSmoothingEnabled => NativeApi.UnityARKit_OcclusionProvider_GetEnvironmentDepthTemporalSmoothingEnabled(); public override bool environmentDepthTemporalSmoothingRequested { get => Api.GetRequestedFeatures().Any(Feature.EnvironmentDepthTemporalSmoothing); set => Api.SetFeatureRequested(Feature.EnvironmentDepthTemporalSmoothing, value); } /// /// Specifies the requested occlusion preference mode. /// /// /// The requested occlusion preference mode. /// public override OcclusionPreferenceMode requestedOcclusionPreferenceMode { get => m_OcclusionPreferenceMode; set => m_OcclusionPreferenceMode = value; } /// /// Get the occlusion preference mode currently in use by the provider. /// public override OcclusionPreferenceMode currentOcclusionPreferenceMode => m_OcclusionPreferenceMode; /// /// Gets the human stencil texture descriptor. /// /// The human stencil texture descriptor to be populated, if /// available. /// /// true if the human stencil texture descriptor is available and is returned. Otherwise, /// false. /// public override bool TryGetHumanStencil(out XRTextureDescriptor humanStencilDescriptor) => NativeApi.UnityARKit_OcclusionProvider_TryGetHumanStencil(out humanStencilDescriptor); /// /// The CPU image API for interacting with the human stencil image. /// public override XRCpuImage.Api humanStencilCpuImageApi => ARKitCpuImageApi.instance; /// /// Gets the CPU construction information for a human stencil image. /// /// The CPU image construction information, on success. /// /// true if the human stencil texture is available and its CPU image construction information is /// returned. Otherwise, false. /// public override bool TryAcquireHumanStencilCpuImage(out XRCpuImage.Cinfo cinfo) => ARKitCpuImageApi.TryAcquireLatestImage(ARKitCpuImageApi.ImageType.HumanStencil, out cinfo); /// /// Get the human depth texture descriptor. /// /// The human depth texture descriptor to be populated, if available /// /// /// true if the human depth texture descriptor is available and is returned. Otherwise, /// false. /// public override bool TryGetHumanDepth(out XRTextureDescriptor humanDepthDescriptor) => NativeApi.UnityARKit_OcclusionProvider_TryGetHumanDepth(out humanDepthDescriptor); /// /// The CPU image API for interacting with the human depth image. /// public override XRCpuImage.Api humanDepthCpuImageApi => ARKitCpuImageApi.instance; /// /// Gets the CPU construction information for a human depth image. /// /// The CPU image construction information, on success. /// /// true if the human depth texture is available and its CPU image construction information is /// returned. Otherwise, false. /// public override bool TryAcquireHumanDepthCpuImage(out XRCpuImage.Cinfo cinfo) => ARKitCpuImageApi.TryAcquireLatestImage(ARKitCpuImageApi.ImageType.HumanDepth, out cinfo); /// /// Get the environment texture descriptor. /// /// The environment depth texture descriptor to be populated, if /// available. /// /// true if the environment depth texture descriptor is available and is returned. Otherwise, /// false. /// public override bool TryGetEnvironmentDepth(out XRTextureDescriptor environmentDepthDescriptor) => NativeApi.UnityARKit_OcclusionProvider_TryGetEnvironmentDepth(out environmentDepthDescriptor); /// /// Gets the CPU construction information for a environment depth image. /// /// The CPU image construction information, on success. /// /// true if the environment depth texture is available and its CPU image construction information is /// returned. Otherwise, false. /// public override bool TryAcquireEnvironmentDepthCpuImage(out XRCpuImage.Cinfo cinfo) => ARKitCpuImageApi.TryAcquireLatestImage(ARKitCpuImageApi.ImageType.EnvironmentDepth, out cinfo); public override bool TryAcquireRawEnvironmentDepthCpuImage(out XRCpuImage.Cinfo cinfo) => ARKitCpuImageApi.TryAcquireLatestImage(ARKitCpuImageApi.ImageType.RawEnvironmentDepth, out cinfo); public override bool TryAcquireSmoothedEnvironmentDepthCpuImage(out XRCpuImage.Cinfo cinfo) => ARKitCpuImageApi.TryAcquireLatestImage(ARKitCpuImageApi.ImageType.TemporallySmoothedEnvironmentDepth, out cinfo); /// /// The CPU image API for interacting with the environment depth image. /// public override XRCpuImage.Api environmentDepthCpuImageApi => ARKitCpuImageApi.instance; /// /// Get the environment depth confidence texture descriptor. /// /// The environment depth texture descriptor to be /// populated, if available. /// /// true if the environment depth confidence texture descriptor is available and is returned. /// Otherwise, false. /// public override bool TryGetEnvironmentDepthConfidence(out XRTextureDescriptor environmentDepthConfidenceDescriptor) => NativeApi.UnityARKit_OcclusionProvider_TryGetEnvironmentDepthConfidence(out environmentDepthConfidenceDescriptor); /// /// Gets the CPU construction information for a environment depth confidence image. /// /// The CPU image construction information, on success. /// /// true if the environment depth texture confidence is available and its CPU image construction information is /// returned. Otherwise, false. /// public override bool TryAcquireEnvironmentDepthConfidenceCpuImage(out XRCpuImage.Cinfo cinfo) => ARKitCpuImageApi.TryAcquireLatestImage(ARKitCpuImageApi.ImageType.EnvironmentDepthConfidence, out cinfo); /// /// The CPU image API for interacting with the environment depth confidence image. /// public override XRCpuImage.Api environmentDepthConfidenceCpuImageApi => ARKitCpuImageApi.instance; /// /// Gets the occlusion texture descriptors associated with the current AR frame. /// /// The default descriptor value. /// The allocator to use when creating the returned NativeArray. /// The occlusion texture descriptors. public override unsafe NativeArray GetTextureDescriptors(XRTextureDescriptor defaultDescriptor, Allocator allocator) { var textureDescriptors = NativeApi.UnityARKit_OcclusionProvider_AcquireTextureDescriptors(out int length, out int elementSize); try { return NativeCopyUtility.PtrToNativeArrayWithDefault(defaultDescriptor, textureDescriptors, elementSize, length, allocator); } finally { NativeApi.UnityARKit_OcclusionProvider_ReleaseTextureDescriptors(textureDescriptors); } } /// /// Get the enabled and disabled shader keywords for the material. /// /// The keywords to enable for the material. /// The keywords to disable for the material. public override void GetMaterialKeywords(out List enabledKeywords, out List disabledKeywords) { bool isEnvDepthEnabled = NativeApi.UnityARKit_OcclusionProvider_IsEnvironmentEnabled(); bool isHumanDepthEnabled = NativeApi.UnityARKit_OcclusionProvider_IsHumanEnabled(); if (isEnvDepthEnabled && (!isHumanDepthEnabled || (m_OcclusionPreferenceMode == OcclusionPreferenceMode.PreferEnvironmentOcclusion))) { enabledKeywords = m_EnvironmentDepthEnabledMaterialKeywords; disabledKeywords = m_HumanEnabledMaterialKeywords; } else if (isHumanDepthEnabled) { enabledKeywords = m_HumanEnabledMaterialKeywords; disabledKeywords = m_EnvironmentDepthEnabledMaterialKeywords; } else { enabledKeywords = null; disabledKeywords = m_AllDisabledMaterialKeywords; } } } /// /// Container to wrap the native ARKit human body APIs. /// static class NativeApi { #if UNITY_XR_ARKIT_LOADER_ENABLED [DllImport("__Internal")] public static extern void UnityARKit_OcclusionProvider_Construct(int textureHumanStencilPropertyId, int textureHumanDepthPropertyId, int textureEnvDepthPropertyId, int textureEnvDepthConfidencePropertyId); [DllImport("__Internal")] public static extern void UnityARKit_OcclusionProvider_Start(); [DllImport("__Internal")] public static extern void UnityARKit_OcclusionProvider_Stop(); [DllImport("__Internal")] public static extern void UnityARKit_OcclusionProvider_Destruct(); [DllImport("__Internal")] public static extern HumanSegmentationStencilMode UnityARKit_OcclusionProvider_GetRequestedSegmentationStencilMode(); [DllImport("__Internal")] public static extern void UnityARKit_OcclusionProvider_SetRequestedSegmentationStencilMode(HumanSegmentationStencilMode humanSegmentationStencilMode); [DllImport("__Internal")] public static extern HumanSegmentationStencilMode UnityARKit_OcclusionProvider_GetCurrentSegmentationStencilMode(); [DllImport("__Internal")] public static extern HumanSegmentationDepthMode UnityARKit_OcclusionProvider_GetRequestedSegmentationDepthMode(); [DllImport("__Internal")] public static extern void UnityARKit_OcclusionProvider_SetRequestedSegmentationDepthMode(HumanSegmentationDepthMode humanSegmentationDepthMode); [DllImport("__Internal")] public static extern HumanSegmentationDepthMode UnityARKit_OcclusionProvider_GetCurrentSegmentationDepthMode(); [DllImport("__Internal")] public static extern EnvironmentDepthMode UnityARKit_OcclusionProvider_GetRequestedEnvironmentDepthMode(); [DllImport("__Internal")] public static extern void UnityARKit_OcclusionProvider_SetRequestedEnvironmentDepthMode(EnvironmentDepthMode environmentDepthMode); [DllImport("__Internal")] public static extern EnvironmentDepthMode UnityARKit_OcclusionProvider_GetCurrentEnvironmentDepthMode(); [DllImport("__Internal")] public static extern bool UnityARKit_OcclusionProvider_GetEnvironmentDepthTemporalSmoothingEnabled(); [DllImport("__Internal")] public static extern bool UnityARKit_OcclusionProvider_TryGetHumanStencil(out XRTextureDescriptor humanStencilDescriptor); [DllImport("__Internal")] public static extern bool UnityARKit_OcclusionProvider_TryGetHumanDepth(out XRTextureDescriptor humanDepthDescriptor); [DllImport("__Internal")] public static extern bool UnityARKit_OcclusionProvider_TryGetEnvironmentDepth(out XRTextureDescriptor envDepthDescriptor); [DllImport("__Internal")] public static extern bool UnityARKit_OcclusionProvider_TryGetEnvironmentDepthConfidence(out XRTextureDescriptor envDepthConfidenceDescriptor); [DllImport("__Internal")] public static extern unsafe void* UnityARKit_OcclusionProvider_AcquireTextureDescriptors(out int length, out int elementSize); [DllImport("__Internal")] public static extern unsafe void UnityARKit_OcclusionProvider_ReleaseTextureDescriptors(void* descriptors); [DllImport("__Internal")] public static extern bool UnityARKit_OcclusionProvider_IsHumanEnabled(); [DllImport("__Internal")] public static extern bool UnityARKit_OcclusionProvider_IsEnvironmentEnabled(); [DllImport("__Internal")] public static extern Supported UnityARKit_OcclusionProvider_DoesSupportBodySegmentationStencil(); [DllImport("__Internal")] public static extern Supported UnityARKit_OcclusionProvider_DoesSupportBodySegmentationDepth(); [DllImport("__Internal")] public static extern Supported UnityARKit_OcclusionProvider_DoesSupportEnvironmentDepth(); [DllImport("__Internal")] public static extern Supported UnityARKit_OcclusionProvider_DoesSupportEnvironmentDepthTemporalSmoothing(); #else static readonly string k_ExceptionMsg = "ARKit Plugin Provider not enabled in project settings."; public static void UnityARKit_OcclusionProvider_Construct(int textureHumanStencilPropertyId, int textureHumanDepthPropertyId, int textureEnvDepthPropertyId, int textureEnvDepthConfidencePropertyId) { throw new System.NotImplementedException(k_ExceptionMsg); } public static void UnityARKit_OcclusionProvider_Start() { throw new System.NotImplementedException(k_ExceptionMsg); } public static void UnityARKit_OcclusionProvider_Stop() { throw new System.NotImplementedException(k_ExceptionMsg); } public static void UnityARKit_OcclusionProvider_Destruct() { throw new System.NotImplementedException(k_ExceptionMsg); } public static HumanSegmentationStencilMode UnityARKit_OcclusionProvider_GetRequestedSegmentationStencilMode() { throw new System.NotImplementedException(k_ExceptionMsg); } public static void UnityARKit_OcclusionProvider_SetRequestedSegmentationStencilMode(HumanSegmentationStencilMode humanSegmentationStencilMode) { throw new System.NotImplementedException(k_ExceptionMsg); } public static HumanSegmentationStencilMode UnityARKit_OcclusionProvider_GetCurrentSegmentationStencilMode() { throw new System.NotImplementedException(k_ExceptionMsg); } public static HumanSegmentationDepthMode UnityARKit_OcclusionProvider_GetRequestedSegmentationDepthMode() { throw new System.NotImplementedException(k_ExceptionMsg); } public static void UnityARKit_OcclusionProvider_SetRequestedSegmentationDepthMode(HumanSegmentationDepthMode humanSegmentationDepthMode) { throw new System.NotImplementedException(k_ExceptionMsg); } public static HumanSegmentationDepthMode UnityARKit_OcclusionProvider_GetCurrentSegmentationDepthMode() { throw new System.NotImplementedException(k_ExceptionMsg); } public static EnvironmentDepthMode UnityARKit_OcclusionProvider_GetRequestedEnvironmentDepthMode() { throw new System.NotImplementedException(k_ExceptionMsg); } public static void UnityARKit_OcclusionProvider_SetRequestedEnvironmentDepthMode(EnvironmentDepthMode environmentDepthMode) { throw new System.NotImplementedException(k_ExceptionMsg); } public static EnvironmentDepthMode UnityARKit_OcclusionProvider_GetCurrentEnvironmentDepthMode() { throw new System.NotImplementedException(k_ExceptionMsg); } public static unsafe bool UnityARKit_OcclusionProvider_TryGetHumanStencil(out XRTextureDescriptor humanStencilDescriptor) { throw new System.NotImplementedException(k_ExceptionMsg); } public static unsafe bool UnityARKit_OcclusionProvider_TryGetHumanDepth(out XRTextureDescriptor humanDepthDescriptor) { throw new System.NotImplementedException(k_ExceptionMsg); } public static unsafe bool UnityARKit_OcclusionProvider_TryGetEnvironmentDepth(out XRTextureDescriptor envDepthDescriptor) { throw new System.NotImplementedException(k_ExceptionMsg); } public static unsafe bool UnityARKit_OcclusionProvider_TryGetEnvironmentDepthConfidence(out XRTextureDescriptor envDepthConfidenceDescriptor) { throw new System.NotImplementedException(k_ExceptionMsg); } public static unsafe void* UnityARKit_OcclusionProvider_AcquireTextureDescriptors(out int length, out int elementSize) { throw new System.NotImplementedException(k_ExceptionMsg); } public static unsafe void UnityARKit_OcclusionProvider_ReleaseTextureDescriptors(void* descriptors) { throw new System.NotImplementedException(k_ExceptionMsg); } public static bool UnityARKit_OcclusionProvider_IsHumanEnabled() => false; public static bool UnityARKit_OcclusionProvider_IsEnvironmentEnabled() => false; public static Supported UnityARKit_OcclusionProvider_DoesSupportBodySegmentationStencil() => Supported.Unsupported; public static Supported UnityARKit_OcclusionProvider_DoesSupportBodySegmentationDepth() => Supported.Unsupported; public static Supported UnityARKit_OcclusionProvider_DoesSupportEnvironmentDepth() => Supported.Unsupported; public static Supported UnityARKit_OcclusionProvider_DoesSupportEnvironmentDepthTemporalSmoothing() => Supported.Unsupported; public static bool UnityARKit_OcclusionProvider_GetEnvironmentDepthTemporalSmoothingEnabled() => false; #endif } } }