GSXREye.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. using UnityEngine;
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. public class GSXREye : MonoBehaviour, IComparable<GSXREye>
  6. {
  7. public static List<GSXREye> Instances = new List<GSXREye>();
  8. public enum eSide
  9. {
  10. Left = 1,
  11. Right = 2,
  12. Both = 3,
  13. [HideInInspector]
  14. Count = Both
  15. };
  16. public enum eType
  17. {
  18. RenderTexture = 0,
  19. StandardTexture = 1,
  20. EglTexture = 2,
  21. };
  22. public delegate void OnPostRenderCallback(int sideMask, int layerMask);
  23. public OnPostRenderCallback OnPostRenderListener;
  24. public delegate void OnPreRenderCallback(int sideMask, int textureId, int previousId);
  25. public OnPreRenderCallback OnPreRenderListener;
  26. [Tooltip("Layer depth stack")]
  27. public int layerDepth = 0;
  28. [Tooltip("Image display transform")]
  29. public Camera imageCamera;
  30. [Tooltip("Image type: 0/Camera render target, 1/Texture 2d, 2/External egl")]
  31. public eType imageType = eType.RenderTexture;
  32. [Tooltip("Image texture used when ImageType is StandardTexture")]
  33. public Texture imageTexture;
  34. [Tooltip("Image transform for scale, rotation and position (optional)")]
  35. public Transform imageTransform;
  36. [Tooltip("Image display region (camera clip space)")]
  37. public Vector4 clipLowerLeft = new Vector4(-1, -1, 0, 1);
  38. public Vector4 clipUpperLeft = new Vector4(-1, 1, 0, 1);
  39. public Vector4 clipUpperRight = new Vector4(1, 1, 0, 1);
  40. public Vector4 clipLowerRight = new Vector4(1, -1, 0, 1);
  41. [Tooltip("Image source region (texture uv space)")]
  42. public Vector2 uvLowerLeft = new Vector2(0, 0);
  43. public Vector2 uvUpperLeft = new Vector2(0, 1);
  44. public Vector2 uvUpperRight = new Vector2(1, 1);
  45. public Vector2 uvLowerRight = new Vector2(1, 0);
  46. [Tooltip("Side mask")]
  47. public eSide side = eSide.Both;
  48. private float fovMargin = 0f;
  49. private RenderTextureFormat format = RenderTextureFormat.Default;
  50. private Vector2 resolution = new Vector2(1920, 1080);
  51. private float resolutionScaleFactor = 1.0f;
  52. private int antiAliasing = 1;
  53. private int depth = 24;
  54. private int frustumType = 0;
  55. private const int bufferCount = 3;
  56. private RenderTexture[] eyeTextures = new RenderTexture[bufferCount];
  57. private int[] eyeTextureIds = new int[bufferCount];
  58. private int currentTextureIndex = 0;
  59. private Camera[] mainCameras = null;
  60. private bool dirty = false;
  61. private Coroutine recreateBuffersCoroutine = null;
  62. public int CompareTo(GSXREye that)
  63. {
  64. return this.layerDepth.CompareTo(that.layerDepth);
  65. }
  66. public float FovMargin
  67. {
  68. get { return fovMargin; }
  69. set { fovMargin = value; }
  70. }
  71. public int FrustumType
  72. {
  73. get { return frustumType; }
  74. set { frustumType = value; }
  75. }
  76. public void SetImage(Texture2D texture)
  77. {
  78. imageTexture = texture;
  79. InitializeBuffers();
  80. }
  81. public eType ImageType
  82. {
  83. get { return imageType; }
  84. set { imageType = value; }
  85. }
  86. public eSide Side
  87. {
  88. get { return side; }
  89. set { side = value; }
  90. }
  91. public RenderTextureFormat Format
  92. {
  93. get { return format; }
  94. set { SetDirty(format != value); format = value; }
  95. }
  96. public int AntiAliasing
  97. {
  98. get { return antiAliasing; }
  99. set { SetDirty(antiAliasing != value); antiAliasing = value; }
  100. }
  101. public int Depth
  102. {
  103. get { return depth; }
  104. set { SetDirty(depth != value); depth = value; }
  105. }
  106. public Vector2 Resolution
  107. {
  108. get { return resolution; }
  109. set { SetDirty(!Mathf.Approximately(resolution.x, value.x) || !Mathf.Approximately(resolution.y, value.y)); resolution = value; }
  110. }
  111. public float ResolutionScaleFactor
  112. {
  113. get { return resolutionScaleFactor; }
  114. set { SetDirty(!Mathf.Approximately(resolutionScaleFactor, value)); resolutionScaleFactor = value; }
  115. }
  116. void SetDirty(bool value)
  117. {
  118. dirty = dirty == true ? true : value;
  119. }
  120. public int TextureId
  121. {
  122. get { return eyeTextureIds[currentTextureIndex]; }
  123. set { eyeTextureIds[currentTextureIndex] = value; }
  124. }
  125. public int PreviousId
  126. {
  127. get { return eyeTextureIds[(currentTextureIndex + bufferCount - 1) % bufferCount]; }
  128. }
  129. public Texture TexturePtr
  130. {
  131. get { return (imageTexture != null ? imageTexture : (Texture)eyeTextures[currentTextureIndex]); }
  132. }
  133. void Awake()
  134. {
  135. Instances.Add(this);
  136. AcquireComponents();
  137. InitializeCoords();
  138. }
  139. void OnDestroy()
  140. {
  141. Instances.Remove(this);
  142. }
  143. void AcquireComponents()
  144. {
  145. if (imageCamera == null) imageCamera = gameObject.GetComponent<Camera>();
  146. Debug.Assert(imageCamera != null, "ImageCamera object required");
  147. mainCameras = imageCamera.GetComponentsInChildren<Camera>();
  148. foreach(var item in mainCameras){
  149. item.enabled = false;
  150. }
  151. }
  152. IEnumerator WaitSlam() {
  153. yield return new WaitUntil(()=> GSXRManager.Instance.IsRunning);
  154. foreach (var item in mainCameras) {
  155. item.enabled = true;
  156. //if (API_Module_Device.Current.XRType == SC.XR.Unity.XRType.VR) {
  157. // item.clearFlags = CameraClearFlags.Skybox;
  158. //} else if (API_Module_Device.Current.XRType == SC.XR.Unity.XRType.AR || API_Module_Device.Current.XRType == SC.XR.Unity.XRType.MR) {
  159. // item.clearFlags = CameraClearFlags.Color;
  160. //}
  161. }
  162. }
  163. void Start()
  164. {
  165. //Initialize(); Called by GSXRManager.InitializeEyes()
  166. StartCoroutine(WaitSlam()) ;
  167. }
  168. void LateUpdate()
  169. {
  170. UpdateCoords();
  171. }
  172. public void Initialize()
  173. {
  174. InitializeBuffers();
  175. InitializeCameras();
  176. }
  177. void InitializeBuffers()
  178. {
  179. for (int i = 0; i < bufferCount; ++i)
  180. {
  181. if (eyeTextures[i] != null)
  182. eyeTextures[i].Release();
  183. switch(imageType)
  184. {
  185. case eType.RenderTexture:
  186. eyeTextures[i] = new RenderTexture((int)(resolution.x * resolutionScaleFactor), (int)(resolution.y * resolutionScaleFactor), depth, format);
  187. eyeTextures[i].antiAliasing = antiAliasing;
  188. eyeTextures[i].Create();
  189. eyeTextureIds[i] = eyeTextures[i].GetNativeTexturePtr().ToInt32();
  190. //Debug.Log("Create Render Texture with ID: " + eyeTextureIds[i] + " Width: " + eyeTextures[i].width + " Height: " + eyeTextures[i].height + " AA: " + eyeTextures[i].antiAliasing);
  191. break;
  192. case eType.StandardTexture:
  193. if (imageTexture) eyeTextureIds[i] = imageTexture.GetNativeTexturePtr().ToInt32();
  194. break;
  195. case eType.EglTexture:
  196. eyeTextureIds[i] = 0;
  197. break;
  198. }
  199. }
  200. dirty = false;
  201. }
  202. void InitializeCameras()
  203. {
  204. var deviceInfo = GSXRPlugin.Instance.deviceInfo;
  205. var deviceFov = new Vector2(deviceInfo.targetFovXRad, deviceInfo.targetFovYRad) * Mathf.Rad2Deg;
  206. var frustum = side == eSide.Right ? deviceInfo.targetFrustumRight : deviceInfo.targetFrustumLeft;
  207. foreach (var mainCamera in mainCameras)
  208. {
  209. if (frustumType == (int)GSXRManager.SvrSettings.eFrustumType.Camera)
  210. {
  211. mainCamera.fieldOfView = deviceFov.y + FovMargin * deviceFov.y;
  212. mainCamera.aspect = deviceFov.x / deviceFov.y;
  213. }
  214. else if (frustumType == (int)GSXRManager.SvrSettings.eFrustumType.Device)
  215. {
  216. mainCamera.fieldOfView = deviceFov.y;
  217. mainCamera.aspect = deviceFov.x / deviceFov.y;
  218. mainCamera.projectionMatrix = GSXRManager.Perspective(frustum.left, frustum.right, frustum.bottom, frustum.top, frustum.near, mainCamera.farClipPlane);
  219. }
  220. }
  221. }
  222. void InitializeCoords()
  223. {
  224. clipLowerLeft.Set(-1, -1, 0, 1);
  225. clipUpperLeft.Set(-1, 1, 0, 1);
  226. clipUpperRight.Set(1, 1, 0, 1);
  227. clipLowerRight.Set(1, -1, 0, 1);
  228. }
  229. void UpdateCoords()
  230. {
  231. if (imageTransform == null)
  232. return;
  233. var viewCamera = mainCameras[0];
  234. if (viewCamera == null)
  235. return;
  236. var extents = 0.5f * Vector3.one;
  237. var center = Vector3.zero;
  238. var worldLowerLeft = new Vector4(center.x - extents.x, center.y - extents.y, 0, 1);
  239. var worldUpperLeft = new Vector4(center.x - extents.x, center.y + extents.y, 0, 1);
  240. var worldUpperRight = new Vector4(center.x + extents.x, center.y + extents.y, 0, 1);
  241. var worldLowerRight = new Vector4(center.x + extents.x, center.y - extents.y, 0, 1);
  242. Matrix4x4 MVP = viewCamera.projectionMatrix * viewCamera.worldToCameraMatrix * imageTransform.localToWorldMatrix;
  243. clipLowerLeft = MVP * worldLowerLeft;
  244. clipUpperLeft = MVP * worldUpperLeft;
  245. clipUpperRight = MVP * worldUpperRight;
  246. clipLowerRight = MVP * worldLowerRight;
  247. }
  248. void OnPreRender()
  249. {
  250. if (imageType != eType.RenderTexture) return;
  251. SwapBuffers();
  252. if (OnPreRenderListener != null)
  253. {
  254. OnPreRenderListener((int)side, TextureId, PreviousId);
  255. }
  256. }
  257. void SwapBuffers()
  258. {
  259. if (imageType != eType.RenderTexture) return;
  260. currentTextureIndex = ++currentTextureIndex % bufferCount;
  261. var targetTexture = eyeTextures[currentTextureIndex];
  262. if (targetTexture == null) return;
  263. for (int i = 0; i < mainCameras.Length; i++)
  264. {
  265. mainCameras[i].targetTexture = targetTexture;
  266. }
  267. targetTexture.DiscardContents();
  268. }
  269. void OnPostRender()
  270. {
  271. RecreateBuffersIfDirty();
  272. if (OnPostRenderListener != null)
  273. {
  274. OnPostRenderListener((int)side, 0x0);
  275. }
  276. }
  277. void RecreateBuffersIfDirty()
  278. {
  279. if (dirty)
  280. {
  281. if (recreateBuffersCoroutine != null)
  282. {
  283. StopCoroutine(recreateBuffersCoroutine);
  284. recreateBuffersCoroutine = null;
  285. }
  286. recreateBuffersCoroutine = StartCoroutine(RecreateBuffersDeferred());
  287. dirty = false;
  288. }
  289. }
  290. IEnumerator RecreateBuffersDeferred()
  291. {
  292. int i = 0;
  293. while (i < bufferCount)
  294. {
  295. int index = currentTextureIndex - 1;
  296. index = index >= 0 ? index : bufferCount - 1;
  297. if (eyeTextures[index] != null)
  298. eyeTextures[index].Release();
  299. switch (imageType)
  300. {
  301. case eType.RenderTexture:
  302. eyeTextures[index] = new RenderTexture((int)(resolution.x * resolutionScaleFactor), (int)(resolution.y * resolutionScaleFactor), depth, format);
  303. eyeTextures[index].antiAliasing = antiAliasing;
  304. eyeTextures[index].Create();
  305. eyeTextureIds[index] = eyeTextures[index].GetNativeTexturePtr().ToInt32();
  306. Debug.Log("Re-create Render Texture with ID: " + eyeTextureIds[index] + " Width: " + eyeTextures[index].width + " Height: " + eyeTextures[index].height + " AA: " + eyeTextures[index].antiAliasing);
  307. break;
  308. case eType.StandardTexture:
  309. if (imageTexture) eyeTextureIds[index] = imageTexture.GetNativeTexturePtr().ToInt32();
  310. break;
  311. case eType.EglTexture:
  312. eyeTextureIds[index] = 0;
  313. break;
  314. }
  315. int prevTextureIndex = currentTextureIndex;
  316. yield return new WaitUntil(() => currentTextureIndex != prevTextureIndex);
  317. i++;
  318. }
  319. yield break;
  320. }
  321. }