IncrementalMeshController.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. using EZXR.Glass.SixDof;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.ComponentModel;
  5. using System.Runtime.InteropServices;
  6. using UnityEngine;
  7. using UnityEngine.UI;
  8. using System.IO;
  9. using System.Threading;
  10. using UnityEngine.AI;
  11. using System;
  12. namespace EZXR.Glass.SpatialMesh
  13. {
  14. public enum IncrementalMeshState { NONE = 0, GETTING = 1, GETTED, STOPING = 2, STOPED = 3, INIT = 4 };
  15. [DefaultExecutionOrder(-200)]
  16. public class IncrementalMeshController : MonoBehaviour
  17. {
  18. public Text meshStatus;
  19. public Text pointsNum;
  20. public Button meshButton;
  21. public Button stopMeshButton;
  22. public Button meshOC;
  23. public Button disableMesh;
  24. public Button SaveMesh;
  25. //private List<GameObject> meshGameObjects;
  26. private Dictionary<Vector3Int, GameObject> meshGameObjects;
  27. private List<Vector3Int> beUpdated;
  28. private GameObject meshRoot;
  29. private EZVIOBackendIncrementalMesh incrementalMesh = new EZVIOBackendIncrementalMesh();
  30. // private bool isGettingMesh = false;
  31. private bool isMeshGet = false;
  32. //private bool isMeshGetDone = false;
  33. private bool isShowMesh = true;
  34. //private bool beSaveMesh = false;
  35. private Dictionary<Vector3Int, int> chunkStatus;
  36. IncrementalMeshState incre_meshState;
  37. Thread meshThread;
  38. private Mutex mutex = new Mutex();
  39. // private List<MeshFilter> m_Meshes;
  40. private List<Vector3[]> m_Meshes_vs;
  41. private List<int[]> m_Meshes_ts;
  42. public static List<MeshFilter> nav_Meshes = new List<MeshFilter>();
  43. PhysicMaterial pm;
  44. public int BlockUpdateLimitation = 5;
  45. public int index_current = 0;
  46. // Start is called before the first frame update
  47. void Start()
  48. {
  49. meshRoot = new GameObject();
  50. meshRoot.name = "backendmesh";
  51. meshGameObjects = new Dictionary<Vector3Int, GameObject>();
  52. beUpdated = new List<Vector3Int>();
  53. chunkStatus = new Dictionary<Vector3Int, int>();
  54. // m_Meshes = new List<MeshFilter>();
  55. m_Meshes_vs = new List<Vector3[]>();
  56. m_Meshes_ts = new List<int[]>();
  57. meshButton.onClick.AddListener(HandleMeshButtonClick);
  58. stopMeshButton.onClick.AddListener(HandleStopMeshGetClick);
  59. SaveMesh.onClick.AddListener(HandleSaveMeshClick);
  60. meshOC.onClick.AddListener(HandleMeshOCClick);
  61. disableMesh.onClick.AddListener(HandleDisableMeshClick);
  62. Debug.Log("==========UNITY LOG : Start Init Mesh");
  63. meshButton.enabled = true;
  64. meshButton.interactable = true;
  65. stopMeshButton.enabled = false;
  66. stopMeshButton.interactable = false;
  67. incre_meshState = IncrementalMeshState.NONE;
  68. pm = new PhysicMaterial();
  69. pm.staticFriction = 0.9f;//设置Mesh通用物理材质
  70. #if UNITY_EDITOR
  71. #elif UNITY_ANDROID
  72. //@buqing 默认一开始就开始开启mesh
  73. HandleMeshButtonClick();
  74. #endif
  75. }
  76. // Update is called once per frame
  77. void Update()
  78. {
  79. meshStatus.text = "MeshStatus : " + isMeshGet;
  80. if (mutex.WaitOne())
  81. {
  82. if (/*isMeshGetDone &&*/incre_meshState != IncrementalMeshState.NONE && meshRoot.activeSelf)
  83. {
  84. if (beUpdated.Count <= 0)
  85. {
  86. index_current = 0;
  87. beUpdated.Clear();
  88. m_Meshes_vs.Clear();
  89. m_Meshes_ts.Clear();
  90. GetBackEndMesh();
  91. }
  92. else
  93. {
  94. int count = Math.Min(beUpdated.Count, BlockUpdateLimitation);
  95. for (int i = 0; i < count; i++)
  96. {
  97. UpdateMesh(beUpdated[i], i + index_current);
  98. }
  99. index_current += count;
  100. beUpdated.RemoveRange(0, count);
  101. }
  102. // for (int i = 0; i < beUpdated.Count; i++)
  103. // {
  104. // UpdateMesh(beUpdated[i], i);
  105. // }
  106. }
  107. mutex.ReleaseMutex();
  108. }
  109. if (incre_meshState == IncrementalMeshState.STOPED)
  110. {
  111. incre_meshState = IncrementalMeshState.NONE;
  112. nav_Meshes.Clear();
  113. foreach (var item in meshGameObjects)
  114. {
  115. nav_Meshes.Add(item.Value.GetComponent<MeshFilter>());
  116. }
  117. //for(int i = 0; i < meshGameObjects.Count; i ++)
  118. //{
  119. // m_Meshes.Add(meshGameObjects[i].GetComponent<MeshFilter>());
  120. //}
  121. }
  122. }
  123. private void UpdateMesh(Vector3Int idx, int update_idx)
  124. {
  125. if (!meshGameObjects.ContainsKey(idx))
  126. {
  127. GameObject newMesh = new GameObject();
  128. newMesh.name = "backendmesh" + idx;
  129. MeshFilter mf = newMesh.AddComponent<MeshFilter>();
  130. MeshRenderer mr = newMesh.AddComponent<MeshRenderer>();
  131. MeshCollider mc = newMesh.AddComponent<MeshCollider>();
  132. Material material = new Material(Shader.Find("SuperSystems/SpatialMapping"));//new Material(Shader.Find("SuperSystems /Wireframe"));//new Material(Shader.Find("VR/SpatialMapping/Wireframe"));////new Material(Shader.Find("Unlit/Color"));
  133. // material.renderQueue = 2000;
  134. mf.mesh = new UnityEngine.Mesh();
  135. mr.material = material;
  136. mr.allowOcclusionWhenDynamic = true;
  137. newMesh.layer = LayerMask.NameToLayer("Mesh");
  138. newMesh.transform.parent = meshRoot.transform;
  139. meshGameObjects.Add(idx, newMesh);
  140. }
  141. // MeshFilter tmp = m_Meshes[update_idx];
  142. meshGameObjects[idx].GetComponent<MeshFilter>().sharedMesh.Clear();
  143. meshGameObjects[idx].GetComponent<MeshFilter>().sharedMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
  144. meshGameObjects[idx].GetComponent<MeshFilter>().sharedMesh.vertices = /*tmp.sharedMesh.vertices*/m_Meshes_vs[update_idx];
  145. meshGameObjects[idx].GetComponent<MeshFilter>().sharedMesh.triangles = /*tmp.sharedMesh.triangles*/m_Meshes_ts[update_idx];
  146. meshGameObjects[idx].GetComponent<MeshCollider>().sharedMesh = meshGameObjects[idx].GetComponent<MeshFilter>().sharedMesh;
  147. meshGameObjects[idx].GetComponent<MeshCollider>().material = pm;
  148. }
  149. public void GetMeshData(EZVIOBackendIncrementalMesh backendMesh)
  150. {
  151. // int vetexNum = backendMesh.vertexCount;
  152. // int faceNum = backendMesh.facesCount;
  153. // int normalNum = backendMesh.normalCount;
  154. int chunkNum = backendMesh.chunksCount;
  155. // Debug.Log("===========UNITY LOG chunks num: " + chunkNum);
  156. EZVIOChunkInfo[] chunkInfo = new EZVIOChunkInfo[chunkNum];
  157. IntPtr p = backendMesh.chunks;
  158. for (int i = 0; i < chunkNum; i++)
  159. {
  160. // Marshal.PtrToStructure(p, chunkInfo[i]);
  161. chunkInfo[i] = (EZVIOChunkInfo)Marshal.PtrToStructure(p, typeof(EZVIOChunkInfo));
  162. p += Marshal.SizeOf(typeof(EZVIOChunkInfo));
  163. // chunkInfo[i] = new EZVIOChunkInfo();
  164. // IntPtr chunkPtr = (IntPtr)((UInt32)backendMesh.chunks + i * Marshal.SizeOf(typeof(EZVIOChunkInfo)));
  165. // chunkInfo[i] = (EZVIOChunkInfo)Marshal.PtrToStructure(chunkPtr, typeof(EZVIOChunkInfo));
  166. }
  167. // Debug.Log("===========UNITY LOG : chunks info : " + chunkInfo[0].id_x + " " + chunkInfo[0].id_y + " " +
  168. // chunkInfo[0].id_z + " " + chunkInfo[0].nv + " " + chunkInfo[0].sv + " " + chunkInfo[0].ni + " " +
  169. // chunkInfo[0].si + " " + chunkInfo[0].a );
  170. float[] vertexes = new float[backendMesh.mesh.vertexCount * 3];
  171. int[] ts = new int[backendMesh.mesh.facesCount * 3];
  172. Marshal.Copy(backendMesh.mesh.vertex, vertexes, 0, backendMesh.mesh.vertexCount * 3);
  173. Marshal.Copy(backendMesh.mesh.faces, ts, 0, backendMesh.mesh.facesCount * 3);
  174. // for(int i = 0; i < 5; i ++){
  175. // Debug.Log("===========UNITY LOG : incre mesh info : " + vertexes[i*3] + ", "
  176. // + vertexes[i*3+1] + ", " + vertexes[i*3+2] );
  177. // }
  178. if (mutex.WaitOne())
  179. {
  180. incre_meshState = IncrementalMeshState.GETTING;
  181. // m_Meshes.Clear();
  182. m_Meshes_vs.Clear();
  183. m_Meshes_ts.Clear();
  184. beUpdated.Clear();
  185. for (int i = 0; i < chunkNum; i++)
  186. {
  187. EZVIOChunkInfo tmp = chunkInfo[i];
  188. Vector3Int chunkPos = new Vector3Int(tmp.id_x, tmp.id_y, tmp.id_z);
  189. if (chunkStatus.ContainsKey(chunkPos))
  190. {
  191. if (chunkStatus[chunkPos] >= tmp.a)
  192. {
  193. continue;
  194. }
  195. else
  196. {
  197. //update ori value
  198. chunkStatus[chunkPos] = tmp.a;
  199. }
  200. }
  201. else
  202. {
  203. //add new chunk
  204. chunkStatus.Add(chunkPos, tmp.a);
  205. // Debug.Log("========add new chunk");
  206. }
  207. //MeshFilter meshFilter = new MeshFilter();
  208. // Mesh mesh_tmp = new Mesh();
  209. // meshFilter.sharedMesh = mesh_tmp;
  210. // meshFilter.sharedMesh.vertices = new Vector3[tmp.nv];
  211. // meshFilter.sharedMesh.triangles = new int[tmp.ni];
  212. Vector3[] vs_tmp = new Vector3[tmp.nv];
  213. int[] ts_tmp = new int[tmp.ni];
  214. for (int j = 0; j < tmp.nv; j++)
  215. {
  216. int oriIdx = (tmp.sv + j) * 3;
  217. // Debug.Log("========vertex pose");
  218. // meshFilter.sharedMesh.vertices[j] = new Vector3(vertexes[oriIdx], vertexes[oriIdx + 2], vertexes[oriIdx + 1]);
  219. vs_tmp[j] = new Vector3(vertexes[oriIdx], vertexes[oriIdx + 2], vertexes[oriIdx + 1]); // yz互换
  220. // Debug.Log("========vertex pose : " + vs_tmp[j]);
  221. }
  222. for (int j = 0; j < tmp.ni / 3; j++)
  223. {
  224. // meshFilter.sharedMesh.triangles[j*3] = ts[tmp.si + j*3];
  225. // meshFilter.sharedMesh.triangles[j*3 + 1] = ts[tmp.si + j*3+2];
  226. // meshFilter.sharedMesh.triangles[j*3 + 2] = ts[tmp.si + j*3+1];
  227. ts_tmp[j * 3] = ts[tmp.si + j * 3];
  228. ts_tmp[j * 3 + 1] = ts[tmp.si + j * 3 + 2];
  229. ts_tmp[j * 3 + 2] = ts[tmp.si + j * 3 + 1];
  230. // Debug.Log("========vertex index : " + ts_tmp[j*3] + " " + ts_tmp[j*3+1] + " " + ts_tmp[j*3+2]);
  231. }
  232. // m_Meshes.Add(meshFilter);
  233. m_Meshes_vs.Add(vs_tmp);
  234. m_Meshes_ts.Add(ts_tmp);
  235. beUpdated.Add(chunkPos);
  236. }
  237. //isMeshGetDone = true;
  238. incre_meshState = IncrementalMeshState.GETTED;
  239. mutex.ReleaseMutex();
  240. }
  241. // Debug.Log("===========Get Mesh Once Time");
  242. }
  243. private void GetBackEndMesh()
  244. {
  245. // int collect_num = 0;
  246. // while (true)
  247. // {
  248. if (!meshRoot.activeSelf)
  249. {
  250. // continue;
  251. return;
  252. }
  253. // if (isGettingMesh)
  254. // {
  255. // collect_num++;
  256. // Debug.Log("==========UNITY LOG : Mesh Get incre start");
  257. isMeshGet = SpatialMeshDetectorWrapper.getBackendIncrementalMeshData(ref incrementalMesh);
  258. // Debug.Log("==========UNITY LOG : Mesh Get " + isMeshGet);
  259. if (isMeshGet)
  260. {
  261. GetMeshData(incrementalMesh);
  262. }
  263. return;
  264. // }
  265. // else
  266. // {
  267. // meshButton.enabled = true;
  268. // meshButton.interactable = true;
  269. // stopMeshButton.enabled = false;
  270. // stopMeshButton.interactable = false;
  271. // //isMeshGet = NativeTracking.GetBackendSmoothedMesh(ref backendMesh);
  272. // // isMeshGet = NativeTracking.GetBackendIncrementalMeshData(ref incrementalMesh);
  273. // // if (isMeshGet)
  274. // // {
  275. // // GetMeshData(incrementalMesh);
  276. // // }
  277. // NativeTracking.RunPauseMeshAndDFS();
  278. // // meshState = MeshState.STOPED;
  279. // // Thread.CurrentThread.Abort();
  280. // return;
  281. // }
  282. //@buqing 优化获取数据的频率,不影响实时渲染的情况下,最优化速度
  283. // Thread.CurrentThread.Join(100);
  284. // }
  285. }
  286. public void HandleMeshButtonClick()
  287. {
  288. // Debug.Log("==========UNITY LOG : Mesh Button Clicked");
  289. //if (!CheckInitPlane()) return;
  290. //if (isGettingMesh) return;
  291. meshButton.enabled = false;
  292. meshButton.interactable = false;
  293. stopMeshButton.enabled = true;
  294. stopMeshButton.interactable = true;
  295. // isGettingMesh = true;
  296. incre_meshState = IncrementalMeshState.INIT;
  297. //NativeTracking.RunResumeMeshAndDFS();
  298. // meshThread = new Thread(GetBackEndMesh);
  299. // meshThread.Start();
  300. }
  301. public void HandleStopMeshGetClick()
  302. {
  303. // isGettingMesh = false;
  304. meshButton.enabled = true;
  305. meshButton.interactable = true;
  306. stopMeshButton.enabled = false;
  307. stopMeshButton.interactable = false;
  308. //NativeTracking.RunPauseMeshAndDFS();
  309. incre_meshState = IncrementalMeshState.STOPED;
  310. }
  311. public void HandleMeshOCClick()
  312. {
  313. if (isShowMesh)
  314. {
  315. isShowMesh = false;
  316. meshOC.transform.Find("Text").GetComponent<Text>().text = "Show Mesh";
  317. foreach (var item in meshGameObjects)
  318. {
  319. MeshRenderer mr = item.Value.GetComponent<MeshRenderer>();
  320. mr.material.SetInt("_alpha", 0);
  321. }
  322. }
  323. else
  324. {
  325. isShowMesh = true;
  326. meshOC.transform.Find("Text").GetComponent<Text>().text = "Hide Mesh";
  327. foreach (var item in meshGameObjects)
  328. {
  329. MeshRenderer mr = item.Value.GetComponent<MeshRenderer>();
  330. mr.material.SetInt("_alpha", 1);
  331. }
  332. }
  333. }
  334. public void HandleSaveMeshClick()
  335. {
  336. //beSaveMesh = true;
  337. }
  338. public void HandleDisableMeshClick()
  339. {
  340. if (meshRoot.activeSelf)
  341. {
  342. meshRoot.SetActive(false);
  343. disableMesh.transform.Find("Text").GetComponent<Text>().text = "Enable Mesh";
  344. }
  345. else
  346. {
  347. meshRoot.SetActive(true);
  348. disableMesh.transform.Find("Text").GetComponent<Text>().text = "Disable Mesh";
  349. }
  350. }
  351. public static void Collect(ref List<NavMeshBuildSource> sources)
  352. {
  353. sources.Clear();
  354. for (var i = 0; i < nav_Meshes.Count; ++i)
  355. {
  356. var mf = nav_Meshes[i];
  357. if (mf == null) continue;
  358. var m = mf.sharedMesh;
  359. if (m == null) continue;
  360. var s = new NavMeshBuildSource();
  361. s.shape = NavMeshBuildSourceShape.Mesh;
  362. s.sourceObject = m;
  363. s.transform = mf.transform.localToWorldMatrix;
  364. s.area = 0;
  365. sources.Add(s);
  366. }
  367. }
  368. }
  369. }