SW 중심대학 OSS GIT 서버 박건태, 이승준, 고기완, 이준호 새로운 배포
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

349 lines
13 KiB

using System;
using System.Collections.Generic;
using Unity.Collections;
using UnityEngine.XR.ARSubsystems;
namespace UnityEngine.XR.ARFoundation
{
/// <summary>
/// Manages the lifetime of the <c>XRCameraSubsystem</c>. Add one of these to a <c>Camera</c> in your scene
/// if you want camera texture and light estimation information to be available.
/// </summary>
[DefaultExecutionOrder(ARUpdateOrder.k_CameraManager)]
[DisallowMultipleComponent]
[RequireComponent(typeof(Camera))]
[HelpURL("https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@3.0/api/UnityEngine.XR.ARFoundation.ARCameraManager.html")]
public sealed class ARCameraManager : SubsystemLifecycleManager<XRCameraSubsystem, XRCameraSubsystemDescriptor>
{
[SerializeField]
[Tooltip("The focus mode to request on the (physical) AR camera.")]
CameraFocusMode m_FocusMode = CameraFocusMode.Auto;
/// <summary>
/// The <c>CameraFocusMode</c> for the camera.
/// </summary>
/// <value>
/// The focus mode for the camera.
/// </value>
public CameraFocusMode focusMode
{
get
{
if (subsystem != null)
{
return subsystem.focusMode;
}
else
{
return m_FocusMode;
}
}
set
{
m_FocusMode = value;
if (enabled && subsystem != null)
{
subsystem.focusMode = value;
}
}
}
[SerializeField]
[Tooltip("The light estimation mode for the AR camera.")]
LightEstimationMode m_LightEstimationMode = LightEstimationMode.Disabled;
/// <summary>
/// The <c>LightEstimationMode</c> for the camera.
/// </summary>
/// <value>
/// The light estimation mode for the camera.
/// </value>
public LightEstimationMode lightEstimationMode
{
get { return m_LightEstimationMode; }
set
{
m_LightEstimationMode = value;
if (enabled && subsystem != null)
subsystem.lightEstimationMode = value;
}
}
/// <summary>
/// Determines whether camera permission has been granted.
/// </summary>
/// <value>
/// <c>true</c> if permission has been granted. Otherwise, <c>false</c>.
/// </value>
public bool permissionGranted
{
get
{
if (subsystem != null)
return subsystem.permissionGranted;
return false;
}
}
/// <summary>
/// An event which fires each time a new camera frame is received.
/// </summary>
public event Action<ARCameraFrameEventArgs> frameReceived;
/// <summary>
/// The material used in background rendering.
/// </summary>
/// <value>
/// The material used in background rendering.
/// </value>
public Material cameraMaterial { get => (subsystem == null) ? null : subsystem.cameraMaterial; }
/// <summary>
/// Tries to get camera intrinsics. Camera intrinsics refers to properties
/// of a physical camera which may be useful when performing additional
/// computer vision processing on the camera image.
/// </summary>
/// <param name="cameraIntrinsics">The camera intrinsics to be populated if the camera supports intrinsics
/// </param>
/// <returns>
/// <c>true</c> if <paramref name="cameraIntrinsics"/> was populated. Otherwise, <c>false</c>.
/// </returns>
public bool TryGetIntrinsics(out XRCameraIntrinsics cameraIntrinsics)
{
if (subsystem == null)
{
cameraIntrinsics = default(XRCameraIntrinsics);
return false;
}
return subsystem.TryGetIntrinsics(out cameraIntrinsics);
}
/// <summary>
/// Get the camera configurations currently supported for the implementation.
/// </summary>
/// <param name="allocator">The allocation strategy to use for the returned data.</param>
/// <returns>
/// The supported camera configurations.
/// </returns>
public NativeArray<XRCameraConfiguration> GetConfigurations(Allocator allocator)
{
return ((subsystem == null) ? new NativeArray<XRCameraConfiguration>(0, allocator)
: subsystem.GetConfigurations(allocator));
}
/// <summary>
/// The current camera configuration.
/// </summary>
/// <value>
/// The current camera configuration, if it exists. Otherise, <c>null</c>.
/// </value>
/// <exception cref="System.NotSupportedException">Thrown when setting the current configuration if the
/// implementation does not support camera configurations.</exception>
/// <exception cref="System.ArgumentNullException">Thrown when setting the current configuration if the given
/// configuration is <c>null</c>.</exception>
/// <exception cref="System.ArgumentException">Thrown when setting the current configuration if the given
/// configuration is not a supported camera configuration.</exception>
/// <exception cref="System.InvalidOperationException">Thrown when setting the current configuration if the
/// implementation is unable to set the current camera configuration.</exception>
public XRCameraConfiguration? currentConfiguration
{
get { return (subsystem == null) ? null : subsystem.currentConfiguration; }
set
{
if (subsystem != null)
{
subsystem.currentConfiguration = value;
}
}
}
/// <summary>
/// Attempt to get the latest camera image. This provides directly access to the raw pixel data, as well as
/// utilities to convert to RGB and Grayscale formats.
/// </summary>
/// <remarks>
/// The <c>XRCameraImage</c> must be disposed to avoid resource leaks.
/// </remarks>
/// <param name="cameraImage">A valid <c>XRCameraImage</c> if this method returns <c>true</c>.</param>
/// <returns>
/// <c>true</c> if the image was acquired. Otherwise, <c>false</c>.
/// </returns>
public bool TryGetLatestImage(out XRCameraImage cameraImage)
{
if (subsystem == null)
{
cameraImage = default(XRCameraImage);
return false;
}
return subsystem.TryGetLatestImage(out cameraImage);
}
void Awake()
{
m_Camera = GetComponent<Camera>();
}
/// <summary>
/// Callback before the subsystem is started (but after it is created).
/// </summary>
protected override void OnBeforeStart()
{
subsystem.focusMode = m_FocusMode;
subsystem.lightEstimationMode = m_LightEstimationMode;
}
/// <summary>
/// Callback when the manager is disabled.
/// </summary>
protected override void OnDisable()
{
base.OnDisable();
foreach (var textureInfo in m_TextureInfos)
{
textureInfo.Dispose();
}
m_TextureInfos.Clear();
}
void Update()
{
if (subsystem == null)
return;
var cameraParams = new XRCameraParams
{
zNear = m_Camera.nearClipPlane,
zFar = m_Camera.farClipPlane,
screenWidth = Screen.width,
screenHeight = Screen.height,
screenOrientation = Screen.orientation
};
XRCameraFrame frame;
if (subsystem.TryGetLatestFrame(cameraParams, out frame))
{
UpdateTexturesInfos(frame);
if (frameReceived != null)
InvokeFrameReceivedEvent(frame);
}
}
/// <summary>
/// Pull the texture descriptors from the camera subsystem, and update the texture information maintained by
/// this component.
/// </summary>
/// <param name="frame">The latest updated camera frame.</param>
void UpdateTexturesInfos(XRCameraFrame frame)
{
var textureDescriptors = subsystem.GetTextureDescriptors(Allocator.Temp);
try
{
int numUpdated = Math.Min(m_TextureInfos.Count, textureDescriptors.Length);
// Update the existing textures that are in common between the two arrays.
for (int i = 0; i < numUpdated; ++i)
{
m_TextureInfos[i] = ARTextureInfo.GetUpdatedTextureInfo(m_TextureInfos[i], textureDescriptors[i]);
}
// If there are fewer textures in the current frame than we had previously, destroy any remaining unneeded
// textures.
if (numUpdated < m_TextureInfos.Count)
{
for (int i = numUpdated; i < m_TextureInfos.Count; ++i)
{
m_TextureInfos[i].Reset();
}
m_TextureInfos.RemoveRange(numUpdated, (m_TextureInfos.Count - numUpdated));
}
// Else, if there are more textures in the current frame than we have previously, add new textures for any
// additional descriptors.
else if (textureDescriptors.Length > m_TextureInfos.Count)
{
for (int i = numUpdated; i < textureDescriptors.Length; ++i)
{
m_TextureInfos.Add(new ARTextureInfo(textureDescriptors[i]));
}
}
}
finally
{
if (textureDescriptors.IsCreated)
textureDescriptors.Dispose();
}
}
/// <summary>
/// Invoke the camera frame received event packing the frame information into the event argument.
/// <summary>
/// <param name="frame">The camera frame raising the event.</param>
void InvokeFrameReceivedEvent(XRCameraFrame frame)
{
var lightEstimation = new ARLightEstimationData();
if (frame.hasAverageBrightness)
lightEstimation.averageBrightness = frame.averageBrightness;
if (frame.hasAverageIntensityInLumens)
lightEstimation.averageIntensityInLumens = frame.averageIntensityInLumens;
if (frame.hasAverageColorTemperature)
lightEstimation.averageColorTemperature = frame.averageColorTemperature;
if (frame.hasColorCorrection)
lightEstimation.colorCorrection = frame.colorCorrection;
var eventArgs = new ARCameraFrameEventArgs();
eventArgs.lightEstimation = lightEstimation;
if (frame.hasTimestamp)
eventArgs.timestampNs = frame.timestampNs;
if (frame.hasProjectionMatrix)
eventArgs.projectionMatrix = frame.projectionMatrix;
if (frame.hasDisplayMatrix)
eventArgs.displayMatrix = frame.displayMatrix;
if (frame.hasExposureDuration)
eventArgs.exposureDuration = frame.exposureDuration;
if (frame.hasExposureOffset)
eventArgs.exposureOffset = frame.exposureOffset;
s_Textures.Clear();
s_PropertyIds.Clear();
foreach (var textureInfo in m_TextureInfos)
{
s_Textures.Add(textureInfo.texture);
s_PropertyIds.Add(textureInfo.descriptor.propertyNameId);
}
subsystem.GetMaterialKeywords(out List<string> enabledMaterialKeywords, out List<string>disabledMaterialKeywords);
eventArgs.textures = s_Textures;
eventArgs.propertyNameIds = s_PropertyIds;
eventArgs.enabledMaterialKeywords = enabledMaterialKeywords;
eventArgs.disabledMaterialKeywords = disabledMaterialKeywords;
frameReceived(eventArgs);
}
static List<Texture2D> s_Textures = new List<Texture2D>();
static List<int> s_PropertyIds = new List<int>();
readonly List<ARTextureInfo> m_TextureInfos = new List<ARTextureInfo>();
Camera m_Camera;
bool m_PreRenderInvertCullingValue;
}
}