LoadPagedLodFromFileManager.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. /*************************************************************************
  2. * Copyright © 2018-2023 Liwen All rights reserved.
  3. *------------------------------------------------------------------------
  4. * File : LoadPagedLodFromFileManager.cs
  5. * Description : Load root tile file and initialize child lod config.
  6. *------------------------------------------------------------------------
  7. * Author : Liwen
  8. * Version : 1.0.0
  9. * Date : 1/5/2019
  10. * Description : Initial development version.
  11. *************************************************************************/
  12. using System.Collections;
  13. using System.Collections.Generic;
  14. using UnityEngine;
  15. using System.IO;
  16. using System;
  17. using UnityEngine.EventSystems;
  18. using UnityEngine.Scripting;
  19. using System.Runtime.InteropServices;
  20. using System.Runtime.Serialization.Formatters.Binary;
  21. namespace AIPagedLod
  22. {
  23. [System.Serializable]
  24. public class LoadPagedLodFromFileConfig
  25. {
  26. /////////////////////////////editor parameter///////////////////////
  27. public string mDataName = string.Empty;
  28. public string mDataPath = string.Empty;
  29. public int mStartLevel = -1;
  30. //public int mMeshLayer = -1;
  31. public int mLoadPagedLodCount = 6;
  32. public bool mLoadStartLevelFlag = false;
  33. public int mStartLoadLevel = 17;
  34. public bool mIsDaJiangData = false;
  35. public bool mIsGenerateCollider = false;
  36. /////////////////////////////runtime parameter///////////////////////
  37. public bool mIsUpdate = true;
  38. public string mBaseUrl;
  39. }
  40. public class LoadPagedLodFromFileManager : MonoBehaviour
  41. {
  42. public LoadPagedLodFromFileConfig mConfig = new LoadPagedLodFromFileConfig();
  43. public List<PagedLod> mPagedLodList = null;
  44. public static Vector3 mCameraPosition = Vector3.zero;
  45. private void Start()
  46. {
  47. }
  48. void InitPagedLodList()
  49. {
  50. mPagedLodList = new List<PagedLod>(GetComponentsInChildren<PagedLod>(true));
  51. for (int i = 0; i < mPagedLodList.Count; ++i)
  52. {
  53. #if !UNITY_WEBGL && UNITY_ANDROID
  54. if (PagedLodConfig.mInstance.mTileDataType == TileDataType.B3DM)
  55. {
  56. mPagedLodList[i].LoadTileSetJsonFile();
  57. }
  58. #endif
  59. mPagedLodList[i].mIsRootTile = true;
  60. mPagedLodList[i].RecaculateBounds();
  61. mPagedLodList[i].InitBasicInfoDictFromList();
  62. }
  63. }
  64. public string GetDataPath()
  65. {
  66. if (PagedLodConfig.mInstance != null && PagedLodConfig.mInstance.mDataPathDict.ContainsKey(mConfig.mDataName))
  67. {
  68. return PagedLodConfig.mInstance.mDataPathDict[mConfig.mDataName].mDataPath;
  69. }
  70. string dataPath = mConfig.mDataPath;
  71. if(!Directory.Exists(dataPath)) //数据路径不存在则停止更新
  72. {
  73. mConfig.mIsUpdate = false;
  74. }
  75. return dataPath;
  76. }
  77. void Update()
  78. {
  79. if (mConfig.mIsUpdate)
  80. {
  81. if (mPagedLodList.Count == 0)
  82. {
  83. InitPagedLodList();
  84. }
  85. UpdatePagedLod(mPagedLodList);
  86. }
  87. }
  88. private void LateUpdate()
  89. {
  90. if (Input.GetKeyDown(KeyCode.Escape))
  91. {
  92. Application.Quit();
  93. }
  94. }
  95. public static int SortLodByDistance(PagedLod left, PagedLod right)
  96. {
  97. if(left.mIsVisiable && right.mIsVisiable)
  98. {
  99. float d1 = Vector3.Distance(left.mWorldCenter, mCameraPosition);
  100. float d2 = Vector3.Distance(right.mWorldCenter, mCameraPosition);
  101. if (d1 < d2)
  102. return 1;
  103. else if (d1 > d2)
  104. return -1;
  105. else
  106. return 0;
  107. }
  108. else
  109. {
  110. //根据是否可见
  111. if (left.mIsVisiable && !right.mIsVisiable)
  112. return 1;
  113. else if (!right.mIsVisiable && right.mIsVisiable)
  114. return -1;
  115. else
  116. return 0;
  117. }
  118. }
  119. public static void UpdatePagedLod(List<PagedLod> pagedLodList)
  120. {
  121. mCameraPosition = Camera.main.transform.position;
  122. if (!PagedLodUpdateController.IsUpdateEnabled()) return;
  123. #if UNITY_WEBGL || UNITY_ANDROID
  124. pagedLodList.Sort(SortLodByDistance);
  125. TraverseUpdateDepthFirst(pagedLodList);
  126. #else
  127. PagedLodThreadPool.RunAsync(() =>
  128. {
  129. pagedLodList.Sort(SortLodByDistance);
  130. PagedLodThreadPool.QueueOnMainThread(() =>
  131. {
  132. TraverseUpdateDepthFirst(pagedLodList);
  133. });
  134. });
  135. #endif
  136. }
  137. public static void TraverseUpdateBreadthFirst(List<PagedLod> pagedLodList)
  138. {
  139. Queue<PagedLod> tileQueue = new Queue<PagedLod>();
  140. for (int i = 0; i < pagedLodList.Count; ++i)
  141. {
  142. tileQueue.Enqueue(pagedLodList[i]);
  143. }
  144. while (tileQueue.Count > 0)
  145. {
  146. PagedLod currentTile = tileQueue.Dequeue();
  147. bool isUpdateChild = currentTile.UpdatePagedLod();
  148. if (isUpdateChild)
  149. {
  150. for (int i = 0; i < currentTile.mChildTileList.Count; ++i)
  151. {
  152. PagedLod childPagedLod = currentTile.mChildTileList[i].mPagedLod;
  153. if (childPagedLod != null)
  154. {
  155. tileQueue.Enqueue(childPagedLod);
  156. }
  157. }
  158. }
  159. }
  160. }
  161. //深度优先遍历四叉树
  162. public static void TraverseUpdateDepthFirst(List<PagedLod> pagedLodList)
  163. {
  164. Stack<PagedLod> tileStack =new Stack<PagedLod>();
  165. for (int i = 0; i < pagedLodList.Count; ++i)
  166. {
  167. tileStack.Push(pagedLodList[i]);
  168. }
  169. while (tileStack.Count > 0)
  170. {
  171. PagedLod currentTile = tileStack.Pop();
  172. bool isUpdateChild = currentTile.UpdatePagedLod();
  173. if (isUpdateChild)
  174. {
  175. for (int i = 0; i < currentTile.mChildTileList.Count; ++i)
  176. {
  177. PagedLod childPagedLod = currentTile.mChildTileList[i].mPagedLod;
  178. if (childPagedLod != null)
  179. {
  180. tileStack.Push(childPagedLod);
  181. }
  182. }
  183. }
  184. }
  185. }
  186. public static int GetTileFileLevel(string tileDirName, string tileFileName)
  187. {
  188. string tileFileBaseName = tileFileName.Replace(PagedLodConfig.mInstance.GetFileSufix(), "");
  189. if (tileFileBaseName == tileDirName) return -1;
  190. string tempTileDirName = tileDirName + "_";
  191. if (tileFileBaseName.Contains(tempTileDirName))
  192. {
  193. string strLevel = tileFileBaseName.Replace(tempTileDirName, "");
  194. strLevel = strLevel.Replace("L", "");
  195. string[] tempArray = strLevel.Split('_');
  196. if (tempArray.Length > 0)
  197. {
  198. return int.Parse(tempArray[0]);
  199. }
  200. }
  201. return -1;
  202. }
  203. public static int GetDataStartLevel(string dataPath)
  204. {
  205. #if !UNITY_WEBGL && !UNITY_ANDROID
  206. if (!Directory.Exists(dataPath)) return 0;
  207. DirectoryInfo dataDir = new DirectoryInfo(dataPath);
  208. List<DirectoryInfo> dirInfos = new List<DirectoryInfo>(dataDir.GetDirectories());
  209. foreach (var tileDir in dirInfos)
  210. {
  211. foreach (var fileInfo in tileDir.GetFiles("*"+ PagedLodConfig.mInstance.GetFileSufix()))
  212. {
  213. int level = GetTileFileLevel(tileDir.Name, fileInfo.Name);
  214. if (level > 0)
  215. {
  216. return level - 1;
  217. }
  218. }
  219. }
  220. #endif
  221. return -1;
  222. }
  223. //编辑器初始化加载数据
  224. //运行时初始化加载数据
  225. public static PagedLod LoadPagedLod(PagedLodFileLoader loader,Transform parent)
  226. {
  227. GameObject tileObj = new GameObject();
  228. tileObj.name = loader.mTileName;
  229. tileObj.transform.SetParent(parent);
  230. tileObj.transform.localPosition = Vector3.zero;
  231. tileObj.transform.localRotation = Quaternion.identity;
  232. tileObj.transform.localScale = Vector3.one;
  233. PagedLod pagedLod = tileObj.AddComponent<PagedLod>();
  234. pagedLod.mSelfLevel = loader.mLevel;
  235. pagedLod.mTileDirPath = loader.mTileDirPath;
  236. pagedLod.LoadRenderNode(loader);
  237. return pagedLod;
  238. }
  239. public static void GenerateColliderObject(PagedLod pagedLod)
  240. {
  241. GameObject tileCollider = new GameObject("TileCollider");
  242. tileCollider.transform.SetParent(pagedLod.transform);
  243. tileCollider.transform.localPosition = Vector3.zero;
  244. tileCollider.transform.localRotation = Quaternion.identity;
  245. tileCollider.transform.localScale = Vector3.one;
  246. MeshFilter[] meshFilters = pagedLod.GetComponentsInChildren<MeshFilter>();
  247. for (int i = 0; i < meshFilters.Length; ++i)
  248. {
  249. GameObject meshColliderObj = new GameObject("MeshCollider");
  250. meshColliderObj.transform.SetParent(tileCollider.transform);
  251. meshColliderObj.transform.localPosition = Vector3.zero;
  252. meshColliderObj.transform.localRotation = Quaternion.identity;
  253. meshColliderObj.transform.localScale = Vector3.one;
  254. MeshCollider meshCollider = meshColliderObj.AddComponent<MeshCollider>();
  255. meshCollider.sharedMesh = meshFilters[i].sharedMesh;
  256. meshColliderObj.layer = PagedLodConfig.mInstance == null ? 8 : PagedLodConfig.mInstance.mMeshLayer;
  257. }
  258. }
  259. }
  260. }