using System; using System.Collections.Generic; using Unity.Collections; using UnityEngine.SubsystemsImplementation; namespace UnityEngine.XR.ARSubsystems { /// /// Provides access to a device's camera. /// /// /// The XRCameraSubsystem links a Unity Camera to a device camera for video overlay (pass-thru /// rendering). It also allows developers to query for environmental light estimation, when available. /// public class XRCameraSubsystem : SubsystemWithProvider { /// /// Construct the XRCameraSubsystem. /// public XRCameraSubsystem() { } /// /// Gets the camera currently in use. /// /// public Feature currentCamera => provider.currentCamera.Cameras(); /// /// Get or set the requested camera (that is, the bits). /// public Feature requestedCamera { get => provider.requestedCamera; set => provider.requestedCamera = value.Cameras(); } /// /// Interface for providing camera functionality for the implementation. /// public class Provider : SubsystemProvider { /// /// An instance of the used to operate on objects. /// public virtual XRCpuImage.Api cpuImageApi => null; /// /// Property to be implemented by the provder to get the material used by XRCameraSubsystem to /// render the camera texture. /// /// /// The material to render the camera texture. /// public virtual Material cameraMaterial => null; /// /// Property to be implemented by the provider to determine whether camera permission has been granted. /// /// /// true if camera permission has been granted. Otherwise, false. /// public virtual bool permissionGranted => false; /// /// True if culling should be inverted during rendering. Some front-facing /// camera modes might require this. /// public virtual bool invertCulling => false; /// /// This property should get the actual camera facing direction. /// public virtual Feature currentCamera => Feature.None; /// /// This property should get or set the requested camera facing direction, /// that is, the bits. /// public virtual Feature requestedCamera { get => Feature.None; set { } } /// /// Method to be implemented by the provider to start the camera for the subsystem. /// public override void Start() { } /// /// Method to be implemented by the provider to stop the camera for the subsystem. /// public override void Stop() { } /// /// Method to be implemented by the provider to destroy the camera for the subsystem. /// public override void Destroy() { } /// /// Method to be implemented by the provider to get the camera frame for the subsystem. /// /// The current Unity Camera parameters. /// The current camera frame returned by the method. /// /// true if the method successfully got a frame. Otherwise, false. /// public virtual bool TryGetFrame( XRCameraParams cameraParams, out XRCameraFrame cameraFrame) { cameraFrame = default(XRCameraFrame); return false; } /// /// Property to be implemented by the provider to get the current camera focus mode. /// public virtual bool autoFocusEnabled => false; /// /// Property to be implemented by the provider to get or set the focus mode for the camera. /// public virtual bool autoFocusRequested { get => false; set { } } /// /// Property to be implemented by the provider to get the current light estimation mode in use. /// public virtual Feature currentLightEstimation => Feature.None; /// /// Property to be implemented by the provider to get or set the light estimation mode. /// public virtual Feature requestedLightEstimation { get => Feature.None; set { } } /// /// Method to be implemented by the provider to get the camera intrinisics information. /// /// The camera intrinsics information returned from the method. /// /// true if the method successfully gets the camera intrinsics information. Otherwise, false. /// public virtual bool TryGetIntrinsics( out XRCameraIntrinsics cameraIntrinsics) { cameraIntrinsics = default(XRCameraIntrinsics); return false; } /// /// Method to be implemented by the provider to query the supported camera configurations. /// /// A default value used to fill the returned array before copying /// in real values. This ensures future additions to this struct are backwards compatible. /// The allocation strategy to use for the returned data. /// /// The supported camera configurations. /// public virtual NativeArray GetConfigurations(XRCameraConfiguration defaultCameraConfiguration, Allocator allocator) { return new NativeArray(0, allocator); } /// /// Property to be implemented by the provider to query or set the current camera configuration. /// /// /// The current camera configuration, if it exists. Otherise, null. /// /// Thrown when setting the current configuration if the /// implementation does not support camera configurations. /// Thrown when setting the current configuration if the given /// configuration is not a valid, supported camera configuration. /// Thrown when setting the current configuration if the /// implementation is unable to set the current camera configuration. public virtual XRCameraConfiguration? currentConfiguration { get => null; set => throw new NotSupportedException("setting current camera configuration is not supported by this implementation"); } /// /// Get the s associated with the current /// . /// /// The current texture descriptors. /// A default value which should /// be used to fill the returned array before copying in the /// real values. This ensures future additions to this struct /// are backwards compatible. /// The allocator to use when creating /// the returned NativeArray. public virtual NativeArray GetTextureDescriptors( XRTextureDescriptor defaultDescriptor, Allocator allocator) { return new NativeArray(0, allocator); } /// /// Method to be implemented by the provider to 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 virtual void GetMaterialKeywords(out List enabledKeywords, out List disabledKeywords) { enabledKeywords = null; disabledKeywords = null; } /// /// Method to be implemented by the provider to query for the latest native camera image. /// /// The metadata required to construct a /// /// true if the camera image is acquired. Otherwise, false. /// /// Thrown if the implementation does not support camera /// image. public virtual bool TryAcquireLatestCpuImage(out XRCpuImage.Cinfo cameraImageCinfo) { throw new NotSupportedException("getting camera image is not supported by this implementation"); } /// /// Create the camera material from the given camera shader name. /// /// The name of the camera shader. /// /// The created camera material shader. /// /// Thrown if the shader cannot be found or if a /// material cannot be created for the shader. protected Material CreateCameraMaterial(string cameraShaderName) { var shader = Shader.Find(cameraShaderName); if (shader == null) { throw new InvalidOperationException($"Could not find shader named '{cameraShaderName}' required " + $"for video overlay on camera subsystem."); } Material material = new Material(shader); if (material == null) { throw new InvalidOperationException($"Could not create a material for shader named " + $"'{cameraShaderName}' required for video overlay on camera " + $"subsystem."); } return material; } /// /// Method to be implemented by the provider to handle any required platform-specific functionality /// immediately before rendering the camera background. This method will always be called on the render /// thread and should only be called by the code responsible for executing background rendering on /// mobile AR platforms. /// /// Platform specific identifier. public virtual void OnBeforeBackgroundRender(int id) {} } /// /// Get the current focus mode in use by the provider. /// public bool autoFocusEnabled => provider.autoFocusEnabled; /// /// Get or set the focus mode for the camera. /// /// /// The focus mode for the camera. /// public bool autoFocusRequested { get => provider.autoFocusRequested; set => provider.autoFocusRequested = value; } /// /// Returns the current light estimation mode in use by the provider. /// /// public Feature currentLightEstimation => provider.currentLightEstimation.LightEstimation(); /// /// Get or set the requested light estimation mode. /// /// /// The light estimation mode. /// public Feature requestedLightEstimation { get => provider.requestedLightEstimation.LightEstimation(); set => provider.requestedLightEstimation = value.LightEstimation(); } /// /// Gets the s associated with the /// current frame. The caller owns the returned NativeArray /// and is responsible for calling Dispose on it. /// /// An array of texture descriptors. /// The allocator to use when creating /// the returned NativeArray. public NativeArray GetTextureDescriptors( Allocator allocator) { return provider.GetTextureDescriptors( default(XRTextureDescriptor), allocator); } /// /// Get the material used by XRCameraSubsystem to render the camera texture. /// /// /// The material to render the camera texture. /// public Material cameraMaterial => provider.cameraMaterial; /// /// Method to be called on the render thread to handle any required platform-specific functionality /// immediately before rendering the camera background. This method will always be called on the render /// thread and should only be called by the code responsible for executing background rendering on /// mobile AR platforms. /// /// Platform-specific identifier. public void OnBeforeBackgroundRender(int id) { provider.OnBeforeBackgroundRender(id); } /// /// Returns the camera intrinsics information. /// /// /// > [!NOTE] /// > The intrinsics may change each frame. You should call this each frame that you need intrinsics /// > in order to ensure you are using the intrinsics for the current frame. /// /// The camera intrinsics information returned from the method. /// /// true if the method successfully gets the camera intrinsics information. Otherwise, false. /// public bool TryGetIntrinsics(out XRCameraIntrinsics cameraIntrinsics) { return provider.TryGetIntrinsics(out cameraIntrinsics); } /// /// Queries for the supported camera configurations. /// /// The allocation strategy to use for the returned data. /// /// The supported camera configurations. /// public NativeArray GetConfigurations(Allocator allocator) { return provider.GetConfigurations(default(XRCameraConfiguration), allocator); } /// /// The current camera configuration. /// /// /// The current camera configuration, if it exists. Otherise, null. /// /// Thrown when setting the current configuration if the /// implementation does not support camera configurations. /// Thrown when setting the current configuration if the given /// configuration is null. /// Thrown when setting the current configuration if the given /// configuration is not a supported camera configuration. /// Thrown when setting the current configuration if the /// implementation is unable to set the current camera configuration. public virtual XRCameraConfiguration? currentConfiguration { get => provider.currentConfiguration; set { if (value == null) { throw new ArgumentNullException("value", "cannot set the camera configuration to null"); } provider.currentConfiguration = value; } } /// /// Set this to true to invert the culling mode during rendering. Some front-facing /// camera modes might require this. /// public bool invertCulling => provider.invertCulling; /// /// Get the latest frame from the provider. /// /// The Unity Camera parameters. /// The camera frame to be populated if the subsystem is running and successfully provides /// the latest camera frame. /// /// true if the camera frame is successfully returned. Otherwise, false. /// public bool TryGetLatestFrame( XRCameraParams cameraParams, out XRCameraFrame frame) { if (running && provider.TryGetFrame(cameraParams, out frame)) { return true; } frame = default(XRCameraFrame); return false; } /// /// Determines whether camera permission has been granted. /// /// /// true if camera permission has been granted. Otherwise, false. /// public bool permissionGranted => provider.permissionGranted; /// /// 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 void GetMaterialKeywords(out List enabledKeywords, out List disabledKeywords) => provider.GetMaterialKeywords(out enabledKeywords, out disabledKeywords); /// /// Attempts to acquire the latest camera image. This provides direct access to the raw pixel data, as well as /// to utilities to convert to RGB and Grayscale formats. This method is obsolete. Use /// instead. /// /// /// The returned must be disposed to avoid resource leaks. /// /// A valid if this method returns true. /// Returns `true` if the image was acquired. Returns `false` otherwise. /// Thrown if the implementation does not support camera image. /// [Obsolete("Use TryAcquireLatestCpuImage instead. (2020-05-19)")] public bool TryGetLatestImage(out XRCpuImage cpuImage) => TryAcquireLatestCpuImage(out cpuImage); /// /// Attempts to acquire the latest camera image. This provides direct access to the raw pixel data, as well as /// to utilities to convert to RGB and Grayscale formats. /// /// /// The returned must be disposed to avoid resource leaks. /// /// A valid if this method returns true. /// Returns `true` if the image was acquired. Returns `false` otherwise. /// Thrown if the implementation does not support camera image. /// public bool TryAcquireLatestCpuImage(out XRCpuImage cpuImage) { if (provider.cpuImageApi != null && provider.TryAcquireLatestCpuImage(out var cinfo)) { cpuImage = new XRCpuImage(provider.cpuImageApi, cinfo); return true; } cpuImage = default; return false; } /// /// Registers a camera subsystem implementation based on the given subsystem parameters. /// /// The parameters defining the camera subsystem functionality implemented /// by the subsystem provider. /// /// true if the subsystem implementation is registered. Otherwise, false. /// /// Thrown when the values specified in the /// parameter are invalid. Typically, this will occur /// /// /// if is null or empty /// /// /// if is null /// /// /// if does not derive from the /// class /// /// /// /// public static bool Register(XRCameraSubsystemCinfo cameraSubsystemParams) { XRCameraSubsystemDescriptor cameraSubsystemDescriptor = XRCameraSubsystemDescriptor.Create(cameraSubsystemParams); SubsystemDescriptorStore.RegisterDescriptor(cameraSubsystemDescriptor); return true; } } }