SpatialMeshManager.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. using System;
  2. using UnityEngine;
  3. using UnityEngine.UI;
  4. using System.Collections;
  5. using System.Collections.Generic;
  6. using EZXR.Glass.SixDof;
  7. using UnityEngine.SceneManagement;
  8. using System.Runtime.InteropServices;
  9. using System.Threading;
  10. using EZXR.Glass.Core;
  11. namespace EZXR.Glass.SpatialMesh
  12. {
  13. public class SpatialMeshManager : MonoBehaviour
  14. {
  15. #region singleton
  16. private static SpatialMeshManager instance;
  17. public static SpatialMeshManager Instance
  18. {
  19. get
  20. {
  21. return instance;
  22. }
  23. }
  24. #endregion
  25. public bool IsMeshDetecting
  26. {
  27. get
  28. {
  29. return isMeshDetecting;
  30. }
  31. }
  32. private bool isMeshDetecting = false;
  33. public int DetectedMeshChunksCount
  34. {
  35. get
  36. {
  37. return m_MeshGameObjects == null ? 0 : m_MeshGameObjects.Count;
  38. }
  39. }
  40. public bool incrementalMeshVisible
  41. {
  42. set
  43. {
  44. if (m_MeshRoot != null)
  45. {
  46. m_MeshRoot.SetActive(value);
  47. }
  48. }
  49. }
  50. public bool smoothedMeshVisible
  51. {
  52. set
  53. {
  54. if (m_SmoothedMeshes != null)
  55. {
  56. m_SmoothedMeshes.SetActive(value);
  57. }
  58. }
  59. }
  60. public uint meshExtractFrame = 30;
  61. public uint chunkUpdateLimitation = 5;
  62. //vertex array
  63. private Vector3[] smoothedMeshVertexs = null;
  64. //normal
  65. private Vector3[] smoothedMeshNormals = null;
  66. //faces array
  67. private int[] smoothedMeshFaces = null;
  68. private GameObject m_MeshRoot;
  69. private GameObject m_SmoothedMeshes;
  70. private Dictionary<Vector3Int, GameObject> m_MeshGameObjects;
  71. private ulong m_FrameCount = 0;
  72. private EZVIOBackendIncrementalMesh m_IncrementalMesh = new EZVIOBackendIncrementalMesh();
  73. private bool isNewSmoothMesh = false;
  74. private Thread meshHandleThread;
  75. private const int MESH_HANDLE_EVENT_UPDATE_INCREMENTAL = 0x0001;
  76. private const int MESH_HANDLE_EVENT_UPDATE_SMOOTHED = 0x0002;
  77. private const int MESH_HANDLE_EVENT_SAVE_SMOOTHED = 0x0003;
  78. private List<int> meshHandleEventList = new List<int>();
  79. private void Awake()
  80. {
  81. instance = this;
  82. ARConfig.DefaultConfig.MeshFindingMode = MeshFindingMode.Enable;
  83. Application.targetFrameRate = 60;
  84. }
  85. private void OnEnable()
  86. {
  87. // 注册回调
  88. ARFrame.trackableManager.recenterIncrementalMeshesListener += RecenterMeshes;
  89. resumeMeshDetecting();
  90. }
  91. private void OnDisable()
  92. {
  93. pauseMeshDetecting();
  94. // 注销回调
  95. ARFrame.trackableManager.recenterIncrementalMeshesListener -= RecenterMeshes;
  96. }
  97. private void OnDestroy()
  98. {
  99. if (meshHandleThread != null)
  100. meshHandleThread.Abort();
  101. }
  102. // Use this for initialization
  103. void Start()
  104. {
  105. if (chunkUpdateLimitation == 0)
  106. chunkUpdateLimitation = 5;
  107. if (meshExtractFrame == 0)
  108. {
  109. meshExtractFrame = 30;
  110. }
  111. m_MeshRoot = new GameObject();
  112. m_MeshRoot.name = "backendmesh";
  113. m_MeshRoot.transform.position = new Vector3(0, 0, 0);
  114. m_MeshRoot.transform.rotation = new Quaternion(0, 0, 0, 1);
  115. m_MeshGameObjects = new Dictionary<Vector3Int, GameObject>();
  116. meshHandleThread = new Thread(this.MeshHandleRun);
  117. meshHandleThread.Start();
  118. meshHandleEventList.Add(MESH_HANDLE_EVENT_UPDATE_INCREMENTAL);
  119. }
  120. public void resumeMeshDetecting()
  121. {
  122. Debug.Log("SpatialMeshManager resumeMeshDetecting");
  123. ARConfig.DefaultConfig.MeshFindingMode = MeshFindingMode.Enable;
  124. SessionManager.Instance.ResumeSession();
  125. isMeshDetecting = true;
  126. InvokeRepeating("postUpdateIncrementalMeshEvent", 1.0f, 0.05f);
  127. }
  128. public void pauseMeshDetecting()
  129. {
  130. Debug.Log("SpatialMeshManager pauseMeshDetecting");
  131. CancelInvoke("postUpdateIncrementalMeshEvent");
  132. ARConfig.DefaultConfig.MeshFindingMode = MeshFindingMode.Disable;
  133. SessionManager.Instance.ResumeSession();
  134. isMeshDetecting = false;
  135. }
  136. // Update is called once per frame
  137. void Update()
  138. {
  139. }
  140. private void postUpdateIncrementalMeshEvent()
  141. {
  142. meshHandleEventList.Add(MESH_HANDLE_EVENT_UPDATE_INCREMENTAL);
  143. }
  144. private void MeshHandleRun()
  145. {
  146. while (true)
  147. {
  148. if (meshHandleEventList.Count < 1)
  149. {
  150. Thread.Sleep(50);
  151. continue;
  152. }
  153. int eventID = meshHandleEventList[0];
  154. meshHandleEventList.RemoveAt(0);
  155. switch (eventID)
  156. {
  157. case MESH_HANDLE_EVENT_UPDATE_INCREMENTAL:
  158. if (isMeshDetecting && ARFrame.SessionStatus == EZVIOState.EZVIOCameraState_Tracking)
  159. {
  160. bool getMeshResult = SpatialMeshDetectorWrapper.getBackendIncrementalMeshData(ref m_IncrementalMesh);
  161. if (getMeshResult)
  162. ARFrame.trackableManager.UpdateIncrementalMeshes(m_IncrementalMesh);
  163. }
  164. break;
  165. case MESH_HANDLE_EVENT_UPDATE_SMOOTHED:
  166. updateSmoothedMeshesData();
  167. break;
  168. case MESH_HANDLE_EVENT_SAVE_SMOOTHED:
  169. updateSmoothedMeshesData();
  170. //Save Smoothed to SDCard/Download/backendSmoothedMesh_xxx.ply
  171. SpatialMeshDetectorWrapper.SaveBackendSmoothedMeshData();
  172. break;
  173. default:
  174. break;
  175. }
  176. }
  177. }
  178. public void SaveBackendSmoothedMesh()
  179. {
  180. Debug.Log("SpatialMeshManager -- SaveBackendSmoothedMesh add event");
  181. meshHandleEventList.Add(MESH_HANDLE_EVENT_UPDATE_SMOOTHED);
  182. meshHandleEventList.Add(MESH_HANDLE_EVENT_SAVE_SMOOTHED);
  183. }
  184. public void UpdateSmoothedMeshes()
  185. {
  186. Debug.Log("SpatialMeshManager -- UpdateSmoothedMeshes add event");
  187. meshHandleEventList.Add(MESH_HANDLE_EVENT_UPDATE_SMOOTHED);
  188. }
  189. public void ShowSmoothedMeshes()
  190. {
  191. if (!isNewSmoothMesh) {
  192. return;
  193. }
  194. if (m_SmoothedMeshes == null) {
  195. m_SmoothedMeshes = new GameObject();
  196. m_SmoothedMeshes.name = "smoothedmesh";
  197. m_SmoothedMeshes.transform.position = Vector3.zero;
  198. m_SmoothedMeshes.transform.rotation = Quaternion.identity;
  199. MeshFilter mf = m_SmoothedMeshes.AddComponent<MeshFilter>();
  200. MeshRenderer mr = m_SmoothedMeshes.AddComponent<MeshRenderer>();
  201. MeshCollider mc = m_SmoothedMeshes.AddComponent<MeshCollider>();
  202. Material material = new Material(Shader.Find("SuperSystems/SpatialMapping"));
  203. mf.mesh = new UnityEngine.Mesh();
  204. mr.material = material;
  205. mr.allowOcclusionWhenDynamic = true;
  206. m_SmoothedMeshes.layer = LayerMask.NameToLayer("Mesh");
  207. m_SmoothedMeshes.transform.parent = m_SmoothedMeshes.transform;
  208. PhysicMaterial pm = new PhysicMaterial();
  209. pm.staticFriction = 0.9f;//设置Mesh通用物理材质
  210. mc.material = pm;
  211. }
  212. m_SmoothedMeshes.SetActive(true);
  213. if (smoothedMeshFaces != null && smoothedMeshFaces.Length > 0)
  214. {
  215. m_SmoothedMeshes.GetComponent<MeshFilter>().sharedMesh.Clear();
  216. m_SmoothedMeshes.GetComponent<MeshFilter>().sharedMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
  217. m_SmoothedMeshes.GetComponent<MeshFilter>().sharedMesh.vertices = smoothedMeshVertexs;
  218. m_SmoothedMeshes.GetComponent<MeshFilter>().sharedMesh.triangles = smoothedMeshFaces;
  219. m_SmoothedMeshes.GetComponent<MeshCollider>().sharedMesh = m_SmoothedMeshes.GetComponent<MeshFilter>().sharedMesh;
  220. smoothedMeshFaces = null;
  221. }
  222. isNewSmoothMesh = false;
  223. }
  224. public void ShowIncrementalMeshes()
  225. {
  226. m_MeshRoot.SetActive(true);
  227. if (ARFrame.trackableManager.chunksToUpdate.Count > 0)
  228. {
  229. List<Vector3Int> chunksToUpdate = ARFrame.trackableManager.chunksToUpdate;
  230. List<Vector3[]> cachedVSToUpdate = ARFrame.trackableManager.cachedVSToUpdate;
  231. List<int[]> cachedTSToUpdate = ARFrame.trackableManager.cachedTSTupUpdate;
  232. int count = Math.Min(chunksToUpdate.Count, (int)chunkUpdateLimitation);
  233. Debug.Log("SpatialMeshManager ShowIncrementalMeshes " + chunksToUpdate.Count + " tobeupdate, really use " + count);
  234. Debug.Log("SpatialMeshManager ShowIncrementalMeshes BEFORE chunkstoupdate totally " + m_MeshGameObjects.Count + " gameobjects");
  235. for (int i = 0; i < count; i++)
  236. {
  237. Vector3Int chunkIdx = chunksToUpdate[i];
  238. if (!m_MeshGameObjects.ContainsKey(chunkIdx))
  239. {
  240. GameObject newMesh = new GameObject();
  241. newMesh.name = "backendmesh" + chunkIdx;
  242. //newMesh.tag = "NoInteraction";
  243. newMesh.transform.position = new Vector3(0, 0, 0);
  244. newMesh.transform.rotation = new Quaternion(0, 0, 0, 1);
  245. MeshFilter mf = newMesh.AddComponent<MeshFilter>();
  246. MeshRenderer mr = newMesh.AddComponent<MeshRenderer>();
  247. MeshCollider mc = newMesh.AddComponent<MeshCollider>();
  248. Material material = new Material(Shader.Find("SuperSystems/SpatialMapping"));
  249. mf.mesh = new UnityEngine.Mesh();
  250. mr.material = material;
  251. mr.allowOcclusionWhenDynamic = true;
  252. newMesh.layer = LayerMask.NameToLayer("Mesh");
  253. newMesh.transform.parent = m_MeshRoot.transform;
  254. m_MeshGameObjects.Add(chunkIdx, newMesh);
  255. }
  256. m_MeshGameObjects[chunkIdx].GetComponent<MeshFilter>().sharedMesh.Clear();
  257. m_MeshGameObjects[chunkIdx].GetComponent<MeshFilter>().sharedMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
  258. m_MeshGameObjects[chunkIdx].GetComponent<MeshFilter>().sharedMesh.vertices = cachedVSToUpdate[i];
  259. m_MeshGameObjects[chunkIdx].GetComponent<MeshFilter>().sharedMesh.triangles = cachedTSToUpdate[i];
  260. m_MeshGameObjects[chunkIdx].GetComponent<MeshCollider>().sharedMesh = m_MeshGameObjects[chunkIdx].GetComponent<MeshFilter>().sharedMesh;
  261. PhysicMaterial pm = new PhysicMaterial();
  262. pm.staticFriction = 0.9f;//设置Mesh通用物理材质
  263. m_MeshGameObjects[chunkIdx].GetComponent<MeshCollider>().material = pm;
  264. }
  265. ARFrame.trackableManager.CommitCachedChunksUse(count);
  266. Debug.Log("SpatialMeshManager ShowIncrementalMeshes AFTER chunkstoupdate totally " + m_MeshGameObjects.Count + " gameobjects");
  267. }
  268. }
  269. private void RecenterMeshes(Matrix4x4 recenterOffset)
  270. {
  271. if (m_MeshGameObjects != null)
  272. {
  273. foreach (var item in m_MeshGameObjects)
  274. {
  275. for (int i = 0; i < item.Value.GetComponent<MeshFilter>().sharedMesh.vertices.Length; i++)
  276. {
  277. Vector3 tmp = item.Value.GetComponent<MeshFilter>().sharedMesh.vertices[i];
  278. item.Value.GetComponent<MeshFilter>().sharedMesh.vertices[i] = recenterOffset.MultiplyPoint3x4(tmp);
  279. }
  280. }
  281. }
  282. if (m_SmoothedMeshes != null)
  283. {
  284. MeshFilter[] allOldMeshes = m_SmoothedMeshes.GetComponentsInChildren<MeshFilter>();
  285. if (allOldMeshes != null)
  286. {
  287. foreach (MeshFilter item in allOldMeshes)
  288. {
  289. for (int i = 0; i < item.sharedMesh.vertices.Length; i++)
  290. {
  291. Vector3 tmp = item.sharedMesh.vertices[i];
  292. item.sharedMesh.vertices[i] = recenterOffset.MultiplyPoint3x4(tmp);
  293. }
  294. }
  295. }
  296. }
  297. }
  298. private void updateSmoothedMeshesData()
  299. {
  300. EZVIOBackendMesh smoothedMesh = new EZVIOBackendMesh();
  301. isNewSmoothMesh = SpatialMeshDetectorWrapper.getBackendSmoothedMeshData(ref smoothedMesh);
  302. if (!isNewSmoothMesh)
  303. {
  304. Debug.Log("SpatialMeshManager -- updateSmoothedMeshesData failed");
  305. UpdateSmoothedMeshes();
  306. return;
  307. }
  308. Debug.Log("SpatialMeshManager -- updateSmoothedMeshesData vertex Count " + smoothedMesh.vertexCount);
  309. //vertex
  310. float[] smoothedMeshVertexArrays = new float[smoothedMesh.vertexCount * 3];
  311. Marshal.Copy(smoothedMesh.vertex, smoothedMeshVertexArrays, 0, smoothedMesh.vertexCount * 3);
  312. smoothedMeshVertexs = new Vector3[smoothedMesh.vertexCount];
  313. for (int i = 0; i < smoothedMesh.vertexCount; i++)
  314. {
  315. Vector3 tmp = new Vector3(
  316. smoothedMeshVertexArrays[i * 3 + 0], smoothedMeshVertexArrays[i * 3 + 2],
  317. smoothedMeshVertexArrays[i * 3 + 1]); // yz互换
  318. smoothedMeshVertexs[i] = ARFrame.accumulatedRecenterOffset4x4.MultiplyPoint3x4(tmp);
  319. }
  320. //normal
  321. float[] smoothedMeshNormalArrays = new float[smoothedMesh.normalCount * 3];
  322. Marshal.Copy(smoothedMesh.normal, smoothedMeshNormalArrays, 0, smoothedMesh.normalCount * 3);
  323. smoothedMeshNormals = new Vector3[smoothedMesh.normalCount];
  324. for (int i = 0; i < smoothedMesh.normalCount; i++)
  325. {
  326. Vector3 tmp = new Vector3(
  327. smoothedMeshNormalArrays[i * 3 + 0], smoothedMeshNormalArrays[i * 3 + 2],
  328. smoothedMeshNormalArrays[i * 3 + 1]); // yz互换
  329. smoothedMeshNormals[i] = ARFrame.accumulatedRecenterOffset4x4.MultiplyPoint3x4(tmp);
  330. }
  331. //faces
  332. int[] smoothedMeshFaceArrays = new int[smoothedMesh.facesCount * 3];
  333. Marshal.Copy(smoothedMesh.faces, smoothedMeshFaceArrays, 0, smoothedMesh.facesCount * 3);
  334. smoothedMeshFaces = new int[smoothedMesh.facesCount * 3];
  335. for (int i = 0; i < smoothedMesh.facesCount; i++)
  336. {
  337. smoothedMeshFaces[i * 3 + 0] = smoothedMeshFaceArrays[i * 3 + 0];
  338. smoothedMeshFaces[i * 3 + 1] = smoothedMeshFaceArrays[i * 3 + 2];
  339. smoothedMeshFaces[i * 3 + 2] = smoothedMeshFaceArrays[i * 3 + 1];
  340. }
  341. }
  342. }
  343. }