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

4 years ago
  1. using System;
  2. using System.Collections.Generic;
  3. using Unity.Collections;
  4. using UnityEngine.XR.ARSubsystems;
  5. namespace UnityEngine.XR.ARFoundation
  6. {
  7. /// <summary>
  8. /// Manages the lifetime of the <c>XRCameraSubsystem</c>. Add one of these to a <c>Camera</c> in your scene
  9. /// if you want camera texture and light estimation information to be available.
  10. /// </summary>
  11. [DefaultExecutionOrder(ARUpdateOrder.k_CameraManager)]
  12. [DisallowMultipleComponent]
  13. [RequireComponent(typeof(Camera))]
  14. [HelpURL("https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@3.0/api/UnityEngine.XR.ARFoundation.ARCameraManager.html")]
  15. public sealed class ARCameraManager : SubsystemLifecycleManager<XRCameraSubsystem, XRCameraSubsystemDescriptor>
  16. {
  17. [SerializeField]
  18. [Tooltip("The focus mode to request on the (physical) AR camera.")]
  19. CameraFocusMode m_FocusMode = CameraFocusMode.Auto;
  20. /// <summary>
  21. /// The <c>CameraFocusMode</c> for the camera.
  22. /// </summary>
  23. /// <value>
  24. /// The focus mode for the camera.
  25. /// </value>
  26. public CameraFocusMode focusMode
  27. {
  28. get
  29. {
  30. if (subsystem != null)
  31. {
  32. return subsystem.focusMode;
  33. }
  34. else
  35. {
  36. return m_FocusMode;
  37. }
  38. }
  39. set
  40. {
  41. m_FocusMode = value;
  42. if (enabled && subsystem != null)
  43. {
  44. subsystem.focusMode = value;
  45. }
  46. }
  47. }
  48. [SerializeField]
  49. [Tooltip("The light estimation mode for the AR camera.")]
  50. LightEstimationMode m_LightEstimationMode = LightEstimationMode.Disabled;
  51. /// <summary>
  52. /// The <c>LightEstimationMode</c> for the camera.
  53. /// </summary>
  54. /// <value>
  55. /// The light estimation mode for the camera.
  56. /// </value>
  57. public LightEstimationMode lightEstimationMode
  58. {
  59. get { return m_LightEstimationMode; }
  60. set
  61. {
  62. m_LightEstimationMode = value;
  63. if (enabled && subsystem != null)
  64. subsystem.lightEstimationMode = value;
  65. }
  66. }
  67. /// <summary>
  68. /// Determines whether camera permission has been granted.
  69. /// </summary>
  70. /// <value>
  71. /// <c>true</c> if permission has been granted. Otherwise, <c>false</c>.
  72. /// </value>
  73. public bool permissionGranted
  74. {
  75. get
  76. {
  77. if (subsystem != null)
  78. return subsystem.permissionGranted;
  79. return false;
  80. }
  81. }
  82. /// <summary>
  83. /// An event which fires each time a new camera frame is received.
  84. /// </summary>
  85. public event Action<ARCameraFrameEventArgs> frameReceived;
  86. /// <summary>
  87. /// The material used in background rendering.
  88. /// </summary>
  89. /// <value>
  90. /// The material used in background rendering.
  91. /// </value>
  92. public Material cameraMaterial { get => (subsystem == null) ? null : subsystem.cameraMaterial; }
  93. /// <summary>
  94. /// Tries to get camera intrinsics. Camera intrinsics refers to properties
  95. /// of a physical camera which may be useful when performing additional
  96. /// computer vision processing on the camera image.
  97. /// </summary>
  98. /// <param name="cameraIntrinsics">The camera intrinsics to be populated if the camera supports intrinsics
  99. /// </param>
  100. /// <returns>
  101. /// <c>true</c> if <paramref name="cameraIntrinsics"/> was populated. Otherwise, <c>false</c>.
  102. /// </returns>
  103. public bool TryGetIntrinsics(out XRCameraIntrinsics cameraIntrinsics)
  104. {
  105. if (subsystem == null)
  106. {
  107. cameraIntrinsics = default(XRCameraIntrinsics);
  108. return false;
  109. }
  110. return subsystem.TryGetIntrinsics(out cameraIntrinsics);
  111. }
  112. /// <summary>
  113. /// Get the camera configurations currently supported for the implementation.
  114. /// </summary>
  115. /// <param name="allocator">The allocation strategy to use for the returned data.</param>
  116. /// <returns>
  117. /// The supported camera configurations.
  118. /// </returns>
  119. public NativeArray<XRCameraConfiguration> GetConfigurations(Allocator allocator)
  120. {
  121. return ((subsystem == null) ? new NativeArray<XRCameraConfiguration>(0, allocator)
  122. : subsystem.GetConfigurations(allocator));
  123. }
  124. /// <summary>
  125. /// The current camera configuration.
  126. /// </summary>
  127. /// <value>
  128. /// The current camera configuration, if it exists. Otherise, <c>null</c>.
  129. /// </value>
  130. /// <exception cref="System.NotSupportedException">Thrown when setting the current configuration if the
  131. /// implementation does not support camera configurations.</exception>
  132. /// <exception cref="System.ArgumentNullException">Thrown when setting the current configuration if the given
  133. /// configuration is <c>null</c>.</exception>
  134. /// <exception cref="System.ArgumentException">Thrown when setting the current configuration if the given
  135. /// configuration is not a supported camera configuration.</exception>
  136. /// <exception cref="System.InvalidOperationException">Thrown when setting the current configuration if the
  137. /// implementation is unable to set the current camera configuration.</exception>
  138. public XRCameraConfiguration? currentConfiguration
  139. {
  140. get { return (subsystem == null) ? null : subsystem.currentConfiguration; }
  141. set
  142. {
  143. if (subsystem != null)
  144. {
  145. subsystem.currentConfiguration = value;
  146. }
  147. }
  148. }
  149. /// <summary>
  150. /// Attempt to get the latest camera image. This provides directly access to the raw pixel data, as well as
  151. /// utilities to convert to RGB and Grayscale formats.
  152. /// </summary>
  153. /// <remarks>
  154. /// The <c>XRCameraImage</c> must be disposed to avoid resource leaks.
  155. /// </remarks>
  156. /// <param name="cameraImage">A valid <c>XRCameraImage</c> if this method returns <c>true</c>.</param>
  157. /// <returns>
  158. /// <c>true</c> if the image was acquired. Otherwise, <c>false</c>.
  159. /// </returns>
  160. public bool TryGetLatestImage(out XRCameraImage cameraImage)
  161. {
  162. if (subsystem == null)
  163. {
  164. cameraImage = default(XRCameraImage);
  165. return false;
  166. }
  167. return subsystem.TryGetLatestImage(out cameraImage);
  168. }
  169. void Awake()
  170. {
  171. m_Camera = GetComponent<Camera>();
  172. }
  173. /// <summary>
  174. /// Callback before the subsystem is started (but after it is created).
  175. /// </summary>
  176. protected override void OnBeforeStart()
  177. {
  178. subsystem.focusMode = m_FocusMode;
  179. subsystem.lightEstimationMode = m_LightEstimationMode;
  180. }
  181. /// <summary>
  182. /// Callback when the manager is disabled.
  183. /// </summary>
  184. protected override void OnDisable()
  185. {
  186. base.OnDisable();
  187. foreach (var textureInfo in m_TextureInfos)
  188. {
  189. textureInfo.Dispose();
  190. }
  191. m_TextureInfos.Clear();
  192. }
  193. void Update()
  194. {
  195. if (subsystem == null)
  196. return;
  197. var cameraParams = new XRCameraParams
  198. {
  199. zNear = m_Camera.nearClipPlane,
  200. zFar = m_Camera.farClipPlane,
  201. screenWidth = Screen.width,
  202. screenHeight = Screen.height,
  203. screenOrientation = Screen.orientation
  204. };
  205. XRCameraFrame frame;
  206. if (subsystem.TryGetLatestFrame(cameraParams, out frame))
  207. {
  208. UpdateTexturesInfos(frame);
  209. if (frameReceived != null)
  210. InvokeFrameReceivedEvent(frame);
  211. }
  212. }
  213. /// <summary>
  214. /// Pull the texture descriptors from the camera subsystem, and update the texture information maintained by
  215. /// this component.
  216. /// </summary>
  217. /// <param name="frame">The latest updated camera frame.</param>
  218. void UpdateTexturesInfos(XRCameraFrame frame)
  219. {
  220. var textureDescriptors = subsystem.GetTextureDescriptors(Allocator.Temp);
  221. try
  222. {
  223. int numUpdated = Math.Min(m_TextureInfos.Count, textureDescriptors.Length);
  224. // Update the existing textures that are in common between the two arrays.
  225. for (int i = 0; i < numUpdated; ++i)
  226. {
  227. m_TextureInfos[i] = ARTextureInfo.GetUpdatedTextureInfo(m_TextureInfos[i], textureDescriptors[i]);
  228. }
  229. // If there are fewer textures in the current frame than we had previously, destroy any remaining unneeded
  230. // textures.
  231. if (numUpdated < m_TextureInfos.Count)
  232. {
  233. for (int i = numUpdated; i < m_TextureInfos.Count; ++i)
  234. {
  235. m_TextureInfos[i].Reset();
  236. }
  237. m_TextureInfos.RemoveRange(numUpdated, (m_TextureInfos.Count - numUpdated));
  238. }
  239. // Else, if there are more textures in the current frame than we have previously, add new textures for any
  240. // additional descriptors.
  241. else if (textureDescriptors.Length > m_TextureInfos.Count)
  242. {
  243. for (int i = numUpdated; i < textureDescriptors.Length; ++i)
  244. {
  245. m_TextureInfos.Add(new ARTextureInfo(textureDescriptors[i]));
  246. }
  247. }
  248. }
  249. finally
  250. {
  251. if (textureDescriptors.IsCreated)
  252. textureDescriptors.Dispose();
  253. }
  254. }
  255. /// <summary>
  256. /// Invoke the camera frame received event packing the frame information into the event argument.
  257. /// <summary>
  258. /// <param name="frame">The camera frame raising the event.</param>
  259. void InvokeFrameReceivedEvent(XRCameraFrame frame)
  260. {
  261. var lightEstimation = new ARLightEstimationData();
  262. if (frame.hasAverageBrightness)
  263. lightEstimation.averageBrightness = frame.averageBrightness;
  264. if (frame.hasAverageIntensityInLumens)
  265. lightEstimation.averageIntensityInLumens = frame.averageIntensityInLumens;
  266. if (frame.hasAverageColorTemperature)
  267. lightEstimation.averageColorTemperature = frame.averageColorTemperature;
  268. if (frame.hasColorCorrection)
  269. lightEstimation.colorCorrection = frame.colorCorrection;
  270. var eventArgs = new ARCameraFrameEventArgs();
  271. eventArgs.lightEstimation = lightEstimation;
  272. if (frame.hasTimestamp)
  273. eventArgs.timestampNs = frame.timestampNs;
  274. if (frame.hasProjectionMatrix)
  275. eventArgs.projectionMatrix = frame.projectionMatrix;
  276. if (frame.hasDisplayMatrix)
  277. eventArgs.displayMatrix = frame.displayMatrix;
  278. if (frame.hasExposureDuration)
  279. eventArgs.exposureDuration = frame.exposureDuration;
  280. if (frame.hasExposureOffset)
  281. eventArgs.exposureOffset = frame.exposureOffset;
  282. s_Textures.Clear();
  283. s_PropertyIds.Clear();
  284. foreach (var textureInfo in m_TextureInfos)
  285. {
  286. s_Textures.Add(textureInfo.texture);
  287. s_PropertyIds.Add(textureInfo.descriptor.propertyNameId);
  288. }
  289. subsystem.GetMaterialKeywords(out List<string> enabledMaterialKeywords, out List<string>disabledMaterialKeywords);
  290. eventArgs.textures = s_Textures;
  291. eventArgs.propertyNameIds = s_PropertyIds;
  292. eventArgs.enabledMaterialKeywords = enabledMaterialKeywords;
  293. eventArgs.disabledMaterialKeywords = disabledMaterialKeywords;
  294. frameReceived(eventArgs);
  295. }
  296. static List<Texture2D> s_Textures = new List<Texture2D>();
  297. static List<int> s_PropertyIds = new List<int>();
  298. readonly List<ARTextureInfo> m_TextureInfos = new List<ARTextureInfo>();
  299. Camera m_Camera;
  300. bool m_PreRenderInvertCullingValue;
  301. }
  302. }