ARRenderRGB.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. using UnityEngine.UI;
  6. using UnityEngine.Rendering;
  7. using System.IO;
  8. using System.Threading;
  9. using EZXR.Glass.Core;
  10. using EZXR.Glass.SixDof;
  11. using System.Runtime.InteropServices;
  12. using AOT;
  13. using EZXR.Glass.Inputs;
  14. using EZXR.Glass.Device;
  15. namespace EZXR.Glass.Recording
  16. {
  17. public class ARRenderRGB : MonoBehaviour
  18. {
  19. public static ARRenderRGB Instance
  20. {
  21. get
  22. {
  23. return _instance;
  24. }
  25. }
  26. private bool _isReady = false;
  27. public bool isReady
  28. {
  29. get
  30. {
  31. return _isReady;
  32. }
  33. }
  34. private static ARRenderRGB _instance = null;
  35. private const int RENDER_EVENT_DRAWRGB = 0x0001;
  36. /// <summary> Renders the event delegate described by eventID. </summary>
  37. /// <param name="eventID"> Identifier for the event.</param>
  38. private delegate void RenderEventDelegate(int eventID);
  39. /// <summary> Handle of the render thread. </summary>
  40. private static RenderEventDelegate RenderThreadHandle = new RenderEventDelegate(RunOnRenderThread);
  41. private static IntPtr RenderThreadHandlePtr = Marshal.GetFunctionPointerForDelegate(RenderThreadHandle);
  42. #region params
  43. private GameObject m_VideoQuad;
  44. private float previewQuadScale = 1.0f;
  45. public Material m_BackgroundMaterial;
  46. private Camera m_Camera;
  47. private Texture2D m_VideoTexture;
  48. private static float _imageWidth = 0;
  49. private static float _imageHeight = 0;
  50. private NormalRGBCameraDevice rgbCameraDevice;
  51. private Coroutine drawRgbCameraBackgroundCorotine;
  52. #endregion
  53. #region unity functions
  54. private void Awake()
  55. {
  56. _instance = this;
  57. m_Camera = GetComponent<Camera>();
  58. rgbCameraDevice = new NormalRGBCameraDevice();
  59. }
  60. private void Start()
  61. {
  62. }
  63. private void OnDisable()
  64. {
  65. }
  66. private void OnDestroy()
  67. {
  68. _instance = null;
  69. }
  70. #endregion
  71. #region custom functions
  72. public void HandleARRenderOpen()
  73. {
  74. if (drawRgbCameraBackgroundCorotine != null)
  75. return;
  76. m_Camera.enabled = true;
  77. int[] sizeRgbCamera = rgbCameraDevice.getCameraSize();
  78. _imageWidth = sizeRgbCamera[0];
  79. _imageHeight = sizeRgbCamera[1];
  80. StartCoroutine(startRGBCamera());
  81. StartCoroutine(ConfigARRenderCamera());
  82. drawRgbCameraBackgroundCorotine = StartCoroutine(CallPluginAtEndOfFrames());
  83. ConfigVideoPlane();
  84. }
  85. public void HandleARRenderClose()
  86. {
  87. m_Camera.enabled = false;
  88. if (drawRgbCameraBackgroundCorotine == null)
  89. return;
  90. StopCoroutine(drawRgbCameraBackgroundCorotine);
  91. stopRGBCamera();
  92. if (m_VideoQuad != null)
  93. {
  94. Destroy(m_VideoQuad);
  95. m_VideoQuad = null;
  96. }
  97. drawRgbCameraBackgroundCorotine = null;
  98. }
  99. public bool HandleARRenderShot()
  100. {
  101. if (!isReady) return false;
  102. if (rgbCameraDevice != null && m_VideoTexture != null)
  103. {
  104. rgbCameraDevice.DrawRGBVideoFrame(m_VideoTexture.GetNativeTexturePtr());
  105. return true;
  106. }
  107. return false;
  108. }
  109. /// <summary> Executes the 'on render thread' operation. </summary>
  110. /// <param name="eventID"> Identifier for the event.</param>
  111. [MonoPInvokeCallback(typeof(RenderEventDelegate))]
  112. private static void RunOnRenderThread(int eventID)
  113. {
  114. if (eventID == RENDER_EVENT_DRAWRGB)
  115. {
  116. if (_instance != null)
  117. _instance.drawRGBTexture();
  118. }
  119. }
  120. private void drawRGBTexture()
  121. {
  122. if (rgbCameraDevice != null)
  123. {
  124. if (m_VideoTexture != null)
  125. {
  126. rgbCameraDevice.DrawRGBVideoFrame(m_VideoTexture.GetNativeTexturePtr());
  127. }
  128. }
  129. }
  130. public static void SetRGBResolution(int imageWidth, int imageHeight)
  131. {
  132. _imageWidth = imageWidth;
  133. _imageHeight = imageHeight;
  134. Debug.Log("arrenderrgb set: " + _imageWidth + "," + _imageHeight);
  135. }
  136. private void ConfigVideoPlane()
  137. {
  138. if (m_VideoQuad != null)
  139. return;
  140. m_VideoQuad = GameObject.CreatePrimitive(PrimitiveType.Plane);
  141. m_VideoQuad.SetActive(false);
  142. Collider videoQuadCollider = m_VideoQuad.GetComponent<Collider>();
  143. if (videoQuadCollider != null)
  144. {
  145. Destroy(videoQuadCollider);
  146. }
  147. float[] intrinsic = new float[8];
  148. rgbCameraDevice.getRGBCameraIntrics(intrinsic);
  149. float fx = intrinsic[0];
  150. m_VideoQuad.transform.parent = this.transform;
  151. m_VideoQuad.transform.localRotation = Quaternion.AngleAxis(-90, Vector3.right) * Quaternion.AngleAxis(180, Vector3.up);
  152. m_VideoQuad.transform.localPosition = Vector3.forward * 50;
  153. Debug.Log("arrenderrgb: " + _imageWidth + "," + _imageHeight);
  154. Debug.Log("arrenderrgb: " + _imageWidth + "," + _imageHeight);
  155. m_VideoQuad.transform.localScale = new Vector3(_imageWidth * 5 / fx, 1.0f, _imageHeight * 5 / fx);
  156. //选择第2个空layer用于投屏
  157. string[] layerNames = new string[32];
  158. for (int i = 0; i < 32; i++)
  159. {
  160. layerNames[i] = LayerMask.LayerToName(i);
  161. }
  162. int count = 0;
  163. for (int i = 0; i < layerNames.Length; i++)
  164. {
  165. if (string.IsNullOrEmpty(layerNames[i]))
  166. {
  167. if (count == 1)
  168. {
  169. m_VideoQuad.layer = i;
  170. m_Camera.cullingMask |= 1 << i;
  171. showPreview(false);
  172. break;
  173. }
  174. else
  175. {
  176. count++;
  177. }
  178. }
  179. }
  180. if (m_BackgroundMaterial == null)
  181. {
  182. m_BackgroundMaterial = new Material(Shader.Find("Unlit/Texture"));
  183. m_BackgroundMaterial.SetTextureScale("_MainTex", new Vector2(1, -1));
  184. }
  185. //Texture 坐标和opengl图像坐标是上下颠倒的,修正方向
  186. //m_BackgroundMaterial.SetVector(
  187. // "_UvTopLeftRight",
  188. // new Vector4(
  189. // 0.0f, 1.0f, 1.0f, 1.0f));
  190. //m_BackgroundMaterial.SetVector(
  191. // "_UvBottomLeftRight",
  192. // new Vector4(0.0f, 0.0f, 1.0f, 0.0f));
  193. m_VideoQuad.GetComponent<MeshRenderer>().material = m_BackgroundMaterial;
  194. m_VideoQuad.SetActive(true);
  195. }
  196. public void showPreview(bool isShow, float scale = 1.0f)
  197. {
  198. if (m_VideoQuad == null)
  199. return;
  200. int quadLayer = m_VideoQuad.layer;
  201. if (!isShow)
  202. {
  203. if (HMDPoseTracker.Instance != null)
  204. {
  205. HMDPoseTracker.Instance.leftCamera.cullingMask = ~(~HMDPoseTracker.Instance.leftCamera.cullingMask | (1 << quadLayer));
  206. HMDPoseTracker.Instance.rightCamera.cullingMask = ~(~HMDPoseTracker.Instance.rightCamera.cullingMask | (1 << quadLayer));
  207. HMDPoseTracker.Instance.centerCamera.cullingMask = ~(~HMDPoseTracker.Instance.centerCamera.cullingMask | (1 << quadLayer));
  208. }
  209. if (m_VideoQuad != null)
  210. {
  211. m_VideoQuad.transform.localScale *= 1.0f / previewQuadScale;
  212. previewQuadScale = 1.0f;
  213. }
  214. }
  215. else
  216. {
  217. if (HMDPoseTracker.Instance != null)
  218. {
  219. HMDPoseTracker.Instance.leftCamera.cullingMask = HMDPoseTracker.Instance.leftCamera.cullingMask | (1 << quadLayer);
  220. HMDPoseTracker.Instance.rightCamera.cullingMask = HMDPoseTracker.Instance.rightCamera.cullingMask | (1 << quadLayer);
  221. HMDPoseTracker.Instance.centerCamera.cullingMask = HMDPoseTracker.Instance.centerCamera.cullingMask | (1 << quadLayer);
  222. }
  223. if (m_VideoQuad != null)
  224. {
  225. m_VideoQuad.transform.localScale *= scale;
  226. previewQuadScale = scale;
  227. }
  228. }
  229. }
  230. private IEnumerator ConfigARRenderCamera()
  231. {
  232. yield return new WaitUntil(() => rgbCameraDevice.IsStarted());
  233. Debug.Log("UNITY LOG ========= ARRenderRGB, ConfigARRenderCamera");
  234. // Create a texture
  235. m_VideoTexture = new Texture2D((int)_imageWidth, (int)_imageHeight, TextureFormat.RGBA32, false);
  236. //set Texture as Black
  237. byte[] blackByets = new byte[(int)_imageWidth * (int)_imageHeight * 4];
  238. m_VideoTexture.LoadRawTextureData(blackByets);
  239. m_VideoTexture.filterMode = FilterMode.Bilinear;
  240. m_VideoTexture.wrapMode = TextureWrapMode.Repeat;
  241. m_VideoTexture.Apply();
  242. m_BackgroundMaterial.SetTexture("_MainTex", m_VideoTexture);
  243. _isReady = true;
  244. Debug.Log("UNITY LOG ========= ARRenderRGB, _isReady = " + isReady);
  245. }
  246. private IEnumerator CallPluginAtEndOfFrames()
  247. {
  248. if (!Application.isEditor)
  249. {
  250. yield return new WaitUntil(() => rgbCameraDevice.IsStarted());
  251. while (m_Camera.enabled)
  252. {
  253. // Wait until all frame rendering is done
  254. yield return new WaitForEndOfFrame();
  255. // Issue a plugin event with arbitrary integer identifier.
  256. // The plugin can distinguish between different
  257. // things it needs to do based on this ID.
  258. // For our simple plugin, it does not matter which ID we pass here.
  259. //GL.IssuePluginEvent(rgbCameraDevice.GetDrawRGBVideoFrameFunc(), 1);
  260. GL.IssuePluginEvent(RenderThreadHandlePtr, RENDER_EVENT_DRAWRGB);
  261. }
  262. }
  263. }
  264. private IEnumerator startRGBCamera()
  265. {
  266. yield return new WaitUntil(() => SessionManager.Instance != null && SessionManager.Instance.IsInited);
  267. Debug.Log("UNITY LOG ========= ARRenderRGB, startRGBCamera");
  268. rgbCameraDevice.Open();
  269. }
  270. private void stopRGBCamera()
  271. {
  272. if (rgbCameraDevice.IsStarted())
  273. rgbCameraDevice.Close();
  274. }
  275. #endregion
  276. }
  277. }