ObjModelLoader.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. using UnityEngine;
  2. using System.IO;
  3. using System.Text;
  4. using System.Collections.Generic;
  5. using System.Threading;
  6. namespace Nxr.Internal
  7. {
  8. public class ObjModelLoader : MonoBehaviour
  9. {
  10. public enum FileType
  11. {
  12. OBJ, MTL, PNG
  13. }
  14. private Vector3 modelScaleSize = Vector3.one;
  15. private Transform parentTransform;
  16. private string objFilePath;
  17. public void LoadObjFile(string objPath, Transform parent) {
  18. LoadObjFile(objPath, Vector3.one, parent);
  19. }
  20. public void LoadObjFile(string objPath, Vector3 scaleSize, Transform parent)
  21. {
  22. FileDict.Clear();
  23. loaded = false;
  24. IsObjModelLoaded = false;
  25. parentTransform = parent;
  26. modelScaleSize = scaleSize;
  27. objFilePath = objPath;
  28. Thread readFileThread = new Thread(new ParameterizedThreadStart(ReadFiles));
  29. readFileThread.Start(objPath);
  30. }
  31. private Dictionary<FileType, byte[]> FileDict = new Dictionary<FileType, byte[]>();
  32. private bool loaded = false;
  33. private void Update()
  34. {
  35. if (FileDict.Count == 3 && !loaded)
  36. {
  37. CreateModelObject(/*objFilePath*/ null, "OBJ_Model");
  38. loaded = true;
  39. }
  40. }
  41. public GameObject GetObjModel()
  42. {
  43. return ObjModel;
  44. }
  45. ObjMesh objInstace = null;
  46. void ReadFiles(object objPath)
  47. {
  48. ReadFileCore(FileType.OBJ, (string)objPath);
  49. string objtext = System.Text.Encoding.Default.GetString(FileDict[FileType.OBJ]);
  50. objInstace = Nxr.Internal.NxrSDKApi.Instance.GetObjMesh((string)objPath);
  51. if(objInstace == null)
  52. {
  53. objInstace = new ObjMesh();
  54. objInstace = objInstace.LoadFromObj(objtext);
  55. Nxr.Internal.NxrSDKApi.Instance.AddObjMesh((string)objPath, objInstace);
  56. Debug.Log("Create ObjMesh : " + (string)objPath);
  57. } else
  58. {
  59. Debug.Log("Use Cache ObjMesh : " + (string)objPath);
  60. }
  61. FileDict[FileType.OBJ] = null;
  62. ReadFileCore(FileType.MTL, ((string)objPath).Replace("obj", "mtl"));
  63. ReadFileCore(FileType.PNG, ((string)objPath).Replace("obj", "png"));
  64. }
  65. void ReadFileCore(FileType fileType, string filePath)
  66. {
  67. FileStream fileStream = new FileStream(filePath, FileMode.Open, System.IO.FileAccess.Read);
  68. fileStream.Seek(0, SeekOrigin.Begin);
  69. byte[] binary = new byte[fileStream.Length];
  70. fileStream.Read(binary, 0, (int)fileStream.Length);
  71. if (!FileDict.ContainsKey(fileType))
  72. {
  73. FileDict.Add(fileType, binary);
  74. }
  75. else
  76. {
  77. FileDict[fileType] = binary;
  78. }
  79. fileStream.Close();
  80. fileStream.Dispose();
  81. fileStream = null;
  82. }
  83. GameObject ObjModel = null;
  84. public bool IsObjModelLoaded = false;
  85. void CreateModelObject(string objFilePath, string objName)
  86. {
  87. Debug.Log("CreateModelObject=" + objName + "," + objFilePath + ".");
  88. //解析内容
  89. //计算网格
  90. Mesh mesh = new Mesh();
  91. mesh.Clear();
  92. mesh.name = "ObjMesh";
  93. mesh.vertices = objInstace.VertexArray;
  94. mesh.triangles = objInstace.TriangleArray;
  95. if (objInstace.UVArray.Length > 0)
  96. mesh.uv = objInstace.UVArray;
  97. if (objInstace.NormalArray.Length > 0)
  98. mesh.normals = objInstace.NormalArray;
  99. mesh.RecalculateBounds();
  100. //生成物体
  101. ObjModel = new GameObject(objName);
  102. if (parentTransform != null)
  103. {
  104. ObjModel.transform.SetParent(parentTransform);
  105. }
  106. ObjModel.transform.localScale = modelScaleSize;
  107. ObjModel.transform.localPosition = Vector3.zero;
  108. ObjModel.transform.localRotation = Quaternion.identity;
  109. MeshFilter meshFilter = ObjModel.AddComponent<MeshFilter>();
  110. meshFilter.mesh = mesh;
  111. MeshRenderer meshRenderer = ObjModel.AddComponent<MeshRenderer>();
  112. string directory = objFilePath == null ? null : Path.GetDirectoryName(objFilePath);
  113. string mtltext = System.Text.Encoding.Default.GetString(FileDict[FileType.MTL]);
  114. Material[] materials = ObjMaterial.Instance.LoadFormMtl(mtltext, directory, FileDict[FileType.PNG]);
  115. meshRenderer.materials = materials;
  116. IsObjModelLoaded = true;
  117. }
  118. //public void LoadFormFile(string objName, string modelFilePath, string texturePath)
  119. //{
  120. // if (!File.Exists(modelFilePath))
  121. // Debug.Log("请确认obj模型文件是否存在!");
  122. // if (!modelFilePath.EndsWith(".obj"))
  123. // Debug.Log("请确认这是一个obj模型文件");
  124. // //读取内容
  125. // StreamReader reader = new StreamReader(modelFilePath, Encoding.Default);
  126. // string content = reader.ReadToEnd();
  127. // reader.Close();
  128. // //解析内容
  129. // ObjMesh objInstace = new ObjMesh();
  130. // objInstace = objInstace.LoadFromObj(content);
  131. // //计算网格
  132. // Mesh mesh = new Mesh();
  133. // mesh.vertices = objInstace.VertexArray;
  134. // mesh.triangles = objInstace.TriangleArray;
  135. // if (objInstace.UVArray.Length > 0)
  136. // mesh.uv = objInstace.UVArray;
  137. // if (objInstace.NormalArray.Length > 0)
  138. // mesh.normals = objInstace.NormalArray;
  139. // mesh.RecalculateBounds();
  140. // //生成物体
  141. // GameObject go = new GameObject(objName);
  142. // MeshFilter meshFilter = go.AddComponent<MeshFilter>();
  143. // meshFilter.mesh = mesh;
  144. // MeshRenderer meshRenderer = go.AddComponent<MeshRenderer>();
  145. // //获取mtl文件路径
  146. // string mtlFilePath = modelFilePath.Replace(".obj", ".mtl");
  147. // StreamReader mtlReader = new StreamReader(mtlFilePath, Encoding.Default);
  148. // string mtlContent = mtlReader.ReadToEnd();
  149. // mtlReader.Close();
  150. // //从mtl文件中加载材质
  151. // Material[] materials = ObjMaterial.Instance.LoadFormMtl(mtlContent, texturePath, null);
  152. // meshRenderer.materials = materials;
  153. //}
  154. //IEnumerator LoadFileAsync(FileType fileType, string filePath)
  155. //{
  156. // WWW www = new WWW(filePath);
  157. // yield return null;
  158. // yield return www;
  159. // Debug.Log("Load." + filePath + ",isDone=" + www.isDone);
  160. // if ((www.error == null || www.error.Length == 0) && www.isDone)
  161. // {
  162. // // 保持顺序
  163. // if (!FileDict.ContainsKey(fileType))
  164. // {
  165. // FileDict.Add(fileType, Encoding.Default.GetBytes((www.text)));
  166. // }
  167. // else
  168. // {
  169. // FileDict[fileType] = Encoding.Default.GetBytes(www.text);
  170. // }
  171. // www.Dispose();
  172. // switch (fileType)
  173. // {
  174. // case FileType.OBJ:
  175. // StartCoroutine(LoadFileAsync(FileType.MTL, filePath.Replace("obj", "mtl")));
  176. // break;
  177. // case FileType.MTL:
  178. // StartCoroutine(LoadFileAsync(FileType.PNG, filePath.Replace("mtl", "png")));
  179. // break;
  180. // case FileType.PNG:
  181. // StartCoroutine(CreateModelObject(filePath, "Model"));
  182. // break;
  183. // default: break;
  184. // }
  185. // }
  186. // else
  187. // {
  188. // Debug.LogError("Load Error :" + www.error + "," + www.text);
  189. // }
  190. // Debug.Log("LoadFileAsync finish " + fileType);
  191. //}
  192. }
  193. }