ProjectionManager.cs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. using AOT;
  2. using EZXR.Glass.Core;
  3. using EZXR.Glass.Device;
  4. using EZXR.Glass.Recording;
  5. using EZXR.Glass.SixDof;
  6. using System;
  7. using System.Collections;
  8. using System.IO;
  9. using System.Runtime.InteropServices;
  10. using UnityEngine;
  11. namespace EZXR.Glass.Projection
  12. {
  13. public class ProjectionManager : MonoBehaviour
  14. {
  15. private static ProjectionManager instance;
  16. public static ProjectionManager Instance
  17. {
  18. get
  19. {
  20. return instance;
  21. }
  22. }
  23. public Camera projectionCamera;
  24. RenderTexture renderTexture;
  25. /// <summary>
  26. /// 0是不做任何操作,1是开始,2是正在执行投录屏,-1是被停止
  27. /// </summary>
  28. int startProjection;
  29. /// <summary> Renders the event delegate described by eventID. </summary>
  30. /// <param name="eventID"> Identifier for the event.</param>
  31. private delegate void RenderEventDelegate(int eventID);
  32. /// <summary> Handle of the render thread. </summary>
  33. private static RenderEventDelegate RenderThreadHandle = new RenderEventDelegate(RunOnRenderThread);
  34. /// <summary> The render thread handle pointer. </summary>
  35. private static IntPtr RenderThreadHandlePtr = Marshal.GetFunctionPointerForDelegate(RenderThreadHandle);
  36. /// <summary>
  37. /// 测试用,保存一张渲染的图
  38. /// </summary>
  39. bool justSaveOnePic;
  40. private GameObject cameraRigObj;
  41. private void Awake()
  42. {
  43. instance = this;
  44. ProjectionAPI.Init(OnStart, OnStop);
  45. NativeLib.CallBack_OnProjectionDetected += OnProjectionDetected;
  46. NativeLib.Resume();
  47. projectionCamera.GetComponent<PhonePoseTrackerRGB>().enabled = false;
  48. }
  49. // Start is called before the first frame update
  50. void Start()
  51. {
  52. Debug.Log("ProjectionManager ==> Init Start");
  53. StartCoroutine(Init());
  54. DontDestroyOnLoad(this.gameObject);
  55. }
  56. IEnumerator Init()
  57. {
  58. yield return new WaitForEndOfFrame();
  59. yield return new WaitForEndOfFrame();
  60. yield return new WaitForEndOfFrame();
  61. Debug.Log("ProjectionManager ==> Init 0");
  62. while (!NativeTracking.GetIsARSessionInited())
  63. {
  64. yield return new WaitForEndOfFrame();
  65. }
  66. Debug.Log("ProjectionManager ==> Init 1");
  67. CameraResolution cameraResolution = new CameraResolution();
  68. #if UNITY_EDITOR
  69. cameraResolution.width = 1280;
  70. cameraResolution.height = 960;
  71. StartCoroutine(WaitEndOfFrame());
  72. #else
  73. Debug.Log("ProjectionManager ==> Init 2");
  74. NormalRGBCameraDevice rgbCameraDevice = new NormalRGBCameraDevice();
  75. int[] sizeRgbCamera = rgbCameraDevice.getCameraSize();
  76. cameraResolution.width = sizeRgbCamera[0];
  77. cameraResolution.height = sizeRgbCamera[1];
  78. #endif
  79. Debug.Log("ProjectionManager ==> Init 3");
  80. renderTexture = new RenderTexture(cameraResolution.width, cameraResolution.height, 24, RenderTextureFormat.DefaultHDR);
  81. projectionCamera.targetTexture = renderTexture;
  82. Debug.Log("ProjectionManager ==> Init renderTexture size: " + renderTexture.width + "," + renderTexture.height + "; GetNativeTexturePtr: " + renderTexture.GetNativeTexturePtr().ToInt32());
  83. }
  84. // Update is called once per frame
  85. void Update()
  86. {
  87. //if (Input.GetKeyDown(KeyCode.Escape))
  88. //{
  89. // Debug.Log("ProjectionManager ==> justSaveOnePic: true");
  90. // justSaveOnePic = true;
  91. //}
  92. if (NativeTracking.GetIsARSessionInited())
  93. {
  94. if (startProjection == 1)
  95. {
  96. if (renderTexture != null)
  97. {
  98. startProjection = 2;
  99. Debug.Log("ProjectionManager ==> Start: " + renderTexture.GetNativeTexturePtr().ToInt32());
  100. projectionCamera.enabled = true;
  101. projectionCamera.GetComponent<PhonePoseTrackerRGB>().enabled = true;
  102. ProjectionAPI.Start(renderTexture.GetNativeTexturePtr().ToInt32(), 1280, 960);
  103. StartCoroutine(WaitEndOfFrame());
  104. }
  105. }
  106. else if (startProjection == -1)
  107. {
  108. StopProjection();
  109. }
  110. }
  111. if (cameraRigObj == null) {
  112. cameraRigObj = HMDPoseTracker.Instance.gameObject;
  113. }
  114. if (cameraRigObj != null && cameraRigObj.transform.parent != null)
  115. {
  116. Transform bodyRig = cameraRigObj.transform.parent;
  117. if (cameraRigObj.transform.parent != null && bodyRig.name != "XRMan")
  118. {
  119. this.transform.position = bodyRig.position;
  120. this.transform.rotation = bodyRig.rotation;
  121. }
  122. }
  123. else
  124. {
  125. this.transform.position = Vector3.zero;
  126. this.transform.rotation = Quaternion.identity;
  127. }
  128. }
  129. void StopProjection()
  130. {
  131. Debug.Log("ProjectionManager ==> StopProjection");
  132. projectionCamera.enabled = false;
  133. projectionCamera.GetComponent<PhonePoseTrackerRGB>().enabled = false;
  134. startProjection = 0;
  135. StopAllCoroutines();
  136. }
  137. private void OnDestroy()
  138. {
  139. Debug.Log("ProjectionManager ==> OnDestroy startProjection=" + startProjection);
  140. ProjectionAPI.DeInit();
  141. }
  142. private void OnApplicationPause(bool pause)
  143. {
  144. if (pause)
  145. {
  146. Debug.Log("ProjectionManager OnApplicationPause 0");
  147. if (startProjection == 2)
  148. {
  149. Debug.Log("ProjectionManager OnApplicationPause 1");
  150. StopProjection();
  151. Debug.Log("ProjectionManager OnApplicationPause 2");
  152. NativeLib.Pause();
  153. ProjectionAPI.Stop();
  154. }
  155. }
  156. else
  157. {
  158. Debug.Log("ProjectionManager OnApplicationPause 3");
  159. NativeLib.Resume();
  160. Debug.Log("ProjectionManager OnApplicationPause 4");
  161. }
  162. }
  163. /// <summary>
  164. /// 开始投屏或录屏
  165. /// </summary>
  166. /// <param name="type">0投屏 1录屏 2截屏</param>
  167. void OnStart(int type)
  168. {
  169. Debug.Log("ProjectionManager ==> OnStart: " + type);
  170. startProjection = 1;
  171. }
  172. /// <summary>
  173. /// 投屏或录屏结束了(是一个被动通知,应用收到后只需要处理好自身停止录屏的逻辑不需要调用stop接口。整个投录屏功能结束才会回调此处,应用退出或者到后台都不会回调这里)
  174. /// </summary>
  175. void OnStop()
  176. {
  177. Debug.Log("ProjectionManager ==> OnStop");
  178. startProjection = -1;
  179. }
  180. void OnProjectionDetected()
  181. {
  182. Debug.Log("ProjectionManager ==> OnProjectionDetected");
  183. startProjection = 1;
  184. }
  185. IEnumerator WaitEndOfFrame()
  186. {
  187. //camera刚开启的当前帧是不渲染的
  188. yield return new WaitForEndOfFrame();
  189. while (true)
  190. {
  191. yield return new WaitForEndOfFrame();
  192. if (justSaveOnePic)
  193. {
  194. Debug.Log("ProjectionManager ==> SaveRenderTexture");
  195. justSaveOnePic = false;
  196. SaveRenderTexture();
  197. }
  198. #if !UNITY_EDITOR
  199. GL.IssuePluginEvent(RenderThreadHandlePtr, 0);
  200. #endif
  201. }
  202. }
  203. void SaveRenderTexture()
  204. {
  205. Debug.Log("ProjectionManager ==> SaveRenderTexture 0");
  206. RenderTexture.active = renderTexture;
  207. Texture2D texture = new Texture2D(renderTexture.width, renderTexture.height, TextureFormat.ARGB32, false);
  208. texture.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
  209. texture.Apply();
  210. Debug.Log("ProjectionManager ==> SaveRenderTexture 1");
  211. byte[] bytes = texture.EncodeToPNG();
  212. Debug.Log("ProjectionManager ==> SaveRenderTexture size: " + bytes.Length);
  213. string path = Path.Combine(Application.persistentDataPath, "saved.png");
  214. Debug.Log("ProjectionManager ==> SaveRenderTexture path: " + path);
  215. File.WriteAllBytes(path, bytes);
  216. Debug.Log("ProjectionManager ==> SaveRenderTexture 2");
  217. }
  218. /// <summary> Executes the 'on render thread' operation. </summary>
  219. /// <param name="eventID"> Identifier for the event.</param>
  220. [MonoPInvokeCallback(typeof(RenderEventDelegate))]
  221. private static void RunOnRenderThread(int eventID)
  222. {
  223. long timeStamp = (long)(ARFrame.HeadPoseRgbTimestamp * 1e9);
  224. //Debug.Log("ProjectionManager ==> RunOnRenderThread HeadPoseRgbTimestamp: " + timeStamp);
  225. ProjectionAPI.NotifyNewFrame(timeStamp);
  226. }
  227. }
  228. }