123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380 |
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Runtime.InteropServices;
- using UnityEngine;
- using UnityEngine.Rendering;
- using UnityEngine.XR;
- using UnityEngine.XR.iOS;
- namespace UnityARInterface
- {
- public class ARKitInterface : ARInterface
- {
- private Material m_ClearMaterial;
- private UnityARSessionNativeInterface nativeInterface
- { get { return UnityARSessionNativeInterface.GetARSessionNativeInterface(); } }
- private bool m_TexturesInitialized;
- private int m_CurrentFrameIndex;
- private int m_CameraWidth;
- private int m_CameraHeight;
- private byte[] m_TextureYBytes;
- private byte[] m_TextureUVBytes;
- private byte[] m_TextureYBytes2;
- private byte[] m_TextureUVBytes2;
- private ARBackgroundRenderer m_BackgroundRenderer;
- private Texture2D _videoTextureY;
- private Texture2D _videoTextureCbCr;
- private GCHandle m_PinnedYArray;
- private GCHandle m_PinnedUVArray;
- private Vector3[] m_PointCloudData;
- private LightEstimate m_LightEstimate;
- private Matrix4x4 m_DisplayTransform;
- private ARKitWorldTrackingSessionConfiguration m_SessionConfig;
- private Dictionary<string, ARAnchor> m_Anchors = new Dictionary<string, ARAnchor>();
- private bool m_BackgroundRendering;
- private bool m_CanRenderBackground;
- private Camera m_Camera;
- private float m_CurrentNearZ;
- private float m_CurrentFarZ;
- public override bool IsSupported
- {
- get
- {
- return m_SessionConfig.IsSupported;
- }
- }
- public override bool BackgroundRendering
- {
- get
- {
- return m_BackgroundRendering && m_CanRenderBackground;
- }
- set
- {
- if (m_BackgroundRenderer == null)
- return;
- m_BackgroundRendering = value;
- m_BackgroundRenderer.mode = m_BackgroundRendering && m_CanRenderBackground ?
- ARRenderMode.MaterialAsBackground : ARRenderMode.StandardBackground;
- m_Camera.clearFlags = CameraClearFlags.SolidColor;
- m_Camera.backgroundColor = Color.black;
- }
- }
- // Use this for initialization
- public override IEnumerator StartService(Settings settings)
- {
- m_SessionConfig = new ARKitWorldTrackingSessionConfiguration(
- UnityARAlignment.UnityARAlignmentGravity,
- settings.enablePlaneDetection ? UnityARPlaneDetection.Horizontal : UnityARPlaneDetection.None,
- settings.enablePointCloud,
- settings.enableLightEstimation);
- if (!IsSupported)
- {
- Debug.LogError("The requested ARKit session configuration is not supported");
- return null;
- }
- UnityARSessionRunOption runOptions =
- UnityARSessionRunOption.ARSessionRunOptionRemoveExistingAnchors |
- UnityARSessionRunOption.ARSessionRunOptionResetTracking;
- nativeInterface.RunWithConfigAndOptions(
- m_SessionConfig, runOptions);
- // Register for plane detection
- UnityARSessionNativeInterface.ARAnchorAddedEvent += AddAnchor;
- UnityARSessionNativeInterface.ARAnchorUpdatedEvent += UpdateAnchor;
- UnityARSessionNativeInterface.ARAnchorRemovedEvent += RemoveAnchor;
- UnityARSessionNativeInterface.ARFrameUpdatedEvent += UpdateFrame;
- UnityARSessionNativeInterface.ARUserAnchorUpdatedEvent += UpdateUserAnchor;
- IsRunning = true;
- return null;
- }
- private Vector3 GetWorldPosition(ARPlaneAnchor arPlaneAnchor)
- {
- return UnityARMatrixOps.GetPosition(arPlaneAnchor.transform) +
- new Vector3(arPlaneAnchor.center.x, arPlaneAnchor.center.y, -arPlaneAnchor.center.z);
- }
- private BoundedPlane GetBoundedPlane(ARPlaneAnchor arPlaneAnchor)
- {
- return new BoundedPlane()
- {
- id = arPlaneAnchor.identifier,
- center = GetWorldPosition(arPlaneAnchor),
- rotation = UnityARMatrixOps.GetRotation(arPlaneAnchor.transform),
- extents = new Vector2(arPlaneAnchor.extent.x, arPlaneAnchor.extent.z)
- };
- }
- void UpdateFrame(UnityARCamera camera)
- {
- if (!m_TexturesInitialized)
- {
- m_CameraWidth = camera.videoParams.yWidth;
- m_CameraHeight = camera.videoParams.yHeight;
- int numYBytes = camera.videoParams.yWidth * camera.videoParams.yHeight;
- int numUVBytes = camera.videoParams.yWidth * camera.videoParams.yHeight / 2; //quarter resolution, but two bytes per pixel
- m_TextureYBytes = new byte[numYBytes];
- m_TextureUVBytes = new byte[numUVBytes];
- m_TextureYBytes2 = new byte[numYBytes];
- m_TextureUVBytes2 = new byte[numUVBytes];
- m_PinnedYArray = GCHandle.Alloc(m_TextureYBytes);
- m_PinnedUVArray = GCHandle.Alloc(m_TextureUVBytes);
- m_TexturesInitialized = true;
- }
- m_PointCloudData = camera.pointCloudData;
- m_LightEstimate.capabilities = LightEstimateCapabilities.AmbientColorTemperature | LightEstimateCapabilities.AmbientIntensity;
- m_LightEstimate.ambientColorTemperature = camera.lightData.arLightEstimate.ambientColorTemperature;
- // Convert ARKit intensity to Unity intensity
- // ARKit ambient intensity ranges 0-2000
- // Unity ambient intensity ranges 0-8 (for over-bright lights)
- m_LightEstimate.ambientIntensity = camera.lightData.arLightEstimate.ambientIntensity / 1000f;
- //get display transform matrix sent up from sdk
- m_DisplayTransform.SetColumn(0, camera.displayTransform.column0);
- m_DisplayTransform.SetColumn(1, camera.displayTransform.column1);
- m_DisplayTransform.SetColumn(2, camera.displayTransform.column2);
- m_DisplayTransform.SetColumn(3, camera.displayTransform.column3);
- }
- IntPtr PinByteArray(ref GCHandle handle, byte[] array)
- {
- handle.Free();
- handle = GCHandle.Alloc(array, GCHandleType.Pinned);
- return handle.AddrOfPinnedObject();
- }
- byte[] ByteArrayForFrame(int frame, byte[] array0, byte[] array1)
- {
- return frame == 1 ? array1 : array0;
- }
- byte[] YByteArrayForFrame(int frame)
- {
- return ByteArrayForFrame(frame, m_TextureYBytes, m_TextureYBytes2);
- }
- byte[] UVByteArrayForFrame(int frame)
- {
- return ByteArrayForFrame(frame, m_TextureUVBytes, m_TextureUVBytes2);
- }
- private void AddAnchor(ARPlaneAnchor arPlaneAnchor)
- {
- OnPlaneAdded(GetBoundedPlane(arPlaneAnchor));
- }
- private void RemoveAnchor(ARPlaneAnchor arPlaneAnchor)
- {
- OnPlaneRemoved(GetBoundedPlane(arPlaneAnchor));
- }
- private void UpdateAnchor(ARPlaneAnchor arPlaneAnchor)
- {
- OnPlaneUpdated(GetBoundedPlane(arPlaneAnchor));
- }
- private void UpdateUserAnchor(ARUserAnchor anchorData)
- {
- ARAnchor anchor;
- if (m_Anchors.TryGetValue(anchorData.identifier, out anchor))
- {
- anchor.transform.position = anchorData.transform.GetColumn(3);
- anchor.transform.rotation = anchorData.transform.rotation;
- }
- }
- public override void StopService()
- {
- var anchors = m_Anchors.Values;
- foreach (var anchor in anchors)
- {
- DestroyAnchor(anchor);
- }
- UnityARSessionNativeInterface.ARAnchorAddedEvent -= AddAnchor;
- UnityARSessionNativeInterface.ARAnchorUpdatedEvent -= UpdateAnchor;
- UnityARSessionNativeInterface.ARAnchorRemovedEvent -= RemoveAnchor;
- UnityARSessionNativeInterface.ARFrameUpdatedEvent -= UpdateFrame;
- UnityARSessionNativeInterface.ARUserAnchorUpdatedEvent -= UpdateUserAnchor;
- UnityARSessionNativeInterface.GetARSessionNativeInterface().Pause();
- nativeInterface.SetCapturePixelData(false, IntPtr.Zero, IntPtr.Zero);
- m_PinnedYArray.Free();
- m_PinnedUVArray.Free();
- m_TexturesInitialized = false;
- BackgroundRendering = false;
- m_CanRenderBackground = false;
- m_BackgroundRenderer.backgroundMaterial = null;
- m_BackgroundRenderer.camera = null;
- m_BackgroundRenderer = null;
- IsRunning = false;
- }
- public override bool TryGetUnscaledPose(ref Pose pose)
- {
- Matrix4x4 matrix = nativeInterface.GetCameraPose();
- pose.position = UnityARMatrixOps.GetPosition(matrix);
- pose.rotation = UnityARMatrixOps.GetRotation(matrix);
- return true;
- }
- public override bool TryGetCameraImage(ref CameraImage cameraImage)
- {
- ARTextureHandles handles = nativeInterface.GetARVideoTextureHandles();
- if (handles.textureY == System.IntPtr.Zero || handles.textureCbCr == System.IntPtr.Zero)
- return false;
- if (!m_TexturesInitialized)
- return false;
- m_CurrentFrameIndex = (m_CurrentFrameIndex + 1) % 2;
- nativeInterface.SetCapturePixelData(true,
- PinByteArray(ref m_PinnedYArray, YByteArrayForFrame(m_CurrentFrameIndex)),
- PinByteArray(ref m_PinnedUVArray, UVByteArrayForFrame(m_CurrentFrameIndex)));
- cameraImage.y = YByteArrayForFrame(1 - m_CurrentFrameIndex);
- cameraImage.uv = UVByteArrayForFrame(1 - m_CurrentFrameIndex);
- cameraImage.width = m_CameraWidth;
- cameraImage.height = m_CameraHeight;
- return true;
- }
- public override bool TryGetPointCloud(ref PointCloud pointCloud)
- {
- if (m_PointCloudData == null)
- return false;
- if (pointCloud.points == null)
- pointCloud.points = new List<Vector3>();
- pointCloud.points.Clear();
- pointCloud.points.AddRange(m_PointCloudData);
- return true;
- }
- public override LightEstimate GetLightEstimate()
- {
- return m_LightEstimate;
- }
- public override Matrix4x4 GetDisplayTransform()
- {
- return m_DisplayTransform;
- }
- public override void SetupCamera(Camera camera)
- {
- m_Camera = camera;
- m_ClearMaterial = Resources.Load("YUVMaterial", typeof(Material)) as Material;
- m_BackgroundRenderer = new ARBackgroundRenderer();
- m_BackgroundRenderer.backgroundMaterial = m_ClearMaterial;
- m_BackgroundRenderer.camera = camera;
- }
- public override void UpdateCamera(Camera camera)
- {
- camera.projectionMatrix = nativeInterface.GetCameraProjection();
- if (!m_BackgroundRendering)
- return;
- ARTextureHandles handles = UnityARSessionNativeInterface.GetARSessionNativeInterface().GetARVideoTextureHandles();
- if (handles.textureY == System.IntPtr.Zero || handles.textureCbCr == System.IntPtr.Zero)
- {
- m_CanRenderBackground = false;
- return;
- }
- m_CanRenderBackground = true;
- BackgroundRendering = m_BackgroundRendering;
- Resolution currentResolution = Screen.currentResolution;
- // Texture Y
- if (_videoTextureY == null)
- {
- _videoTextureY = Texture2D.CreateExternalTexture(currentResolution.width, currentResolution.height,
- TextureFormat.R8, false, false, (System.IntPtr)handles.textureY);
- _videoTextureY.filterMode = FilterMode.Bilinear;
- _videoTextureY.wrapMode = TextureWrapMode.Repeat;
- m_ClearMaterial.SetTexture("_textureY", _videoTextureY);
- }
- // Texture CbCr
- if (_videoTextureCbCr == null)
- {
- _videoTextureCbCr = Texture2D.CreateExternalTexture(currentResolution.width, currentResolution.height,
- TextureFormat.RG16, false, false, (System.IntPtr)handles.textureCbCr);
- _videoTextureCbCr.filterMode = FilterMode.Bilinear;
- _videoTextureCbCr.wrapMode = TextureWrapMode.Repeat;
- m_ClearMaterial.SetTexture("_textureCbCr", _videoTextureCbCr);
- }
- _videoTextureY.UpdateExternalTexture(handles.textureY);
- _videoTextureCbCr.UpdateExternalTexture(handles.textureCbCr);
- m_ClearMaterial.SetMatrix("_DisplayTransform", m_DisplayTransform);
- }
- public override void Update()
- {
- if (m_CurrentNearZ != m_Camera.nearClipPlane || m_CurrentFarZ != m_Camera.farClipPlane)
- {
- m_CurrentNearZ = m_Camera.nearClipPlane;
- m_CurrentFarZ = m_Camera.farClipPlane;
- UnityARSessionNativeInterface.GetARSessionNativeInterface().SetCameraClipPlanes(m_CurrentNearZ, m_CurrentFarZ);
- }
- }
- public override void ApplyAnchor(ARAnchor arAnchor)
- {
- if (!IsRunning)
- return;
- Matrix4x4 matrix = Matrix4x4.TRS(arAnchor.transform.position, arAnchor.transform.rotation, arAnchor.transform.localScale);
- UnityARUserAnchorData anchorData = new UnityARUserAnchorData();
- anchorData.transform.column0 = matrix.GetColumn(0);
- anchorData.transform.column1 = matrix.GetColumn(1);
- anchorData.transform.column2 = matrix.GetColumn(2);
- anchorData.transform.column3 = matrix.GetColumn(3);
- anchorData = UnityARSessionNativeInterface.GetARSessionNativeInterface().AddUserAnchor(anchorData);
- arAnchor.anchorID = anchorData.identifierStr;
- m_Anchors[arAnchor.anchorID] = arAnchor;
- }
- public override void DestroyAnchor(ARAnchor arAnchor)
- {
- if (!string.IsNullOrEmpty(arAnchor.anchorID))
- {
- UnityARSessionNativeInterface.GetARSessionNativeInterface().RemoveUserAnchor(arAnchor.anchorID);
- if (m_Anchors.ContainsKey(arAnchor.anchorID))
- {
- m_Anchors.Remove(arAnchor.anchorID);
- }
- arAnchor.anchorID = null;
- }
- }
- }
- }
|