ExporterTerrain.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. using UnityEngine;
  2. using UnityEditor;
  3. using System;
  4. using System.Collections;
  5. using System.IO;
  6. using System.Text;
  7. using BabylonExport.Entities;
  8. class ExporterTerrain : EditorWindow
  9. {
  10. BabylonTerrainFormat saveFormat = BabylonTerrainFormat.Triangles;
  11. BabylonTerrainResolution saveResolution = BabylonTerrainResolution.HighResolution;
  12. static TerrainData terrain;
  13. static Terrain terrainObject;
  14. int tCount;
  15. int counter;
  16. int totalCount;
  17. bool flipNormals = true;
  18. int progressUpdateInterval = 10000;
  19. [MenuItem("BabylonJS/Terrain Exporter", false, 100)]
  20. static void InitTerrain()
  21. {
  22. ExporterTerrain terrains = ScriptableObject.CreateInstance<ExporterTerrain>();
  23. terrains.OnInitialize();
  24. terrains.ShowUtility();
  25. }
  26. public void OnInitialize()
  27. {
  28. maxSize = new Vector2(512, 85);
  29. minSize = this.maxSize;
  30. terrain = null;
  31. terrainObject = Selection.activeObject as Terrain;
  32. if (!terrainObject)
  33. {
  34. terrainObject = Terrain.activeTerrain;
  35. }
  36. if (terrainObject)
  37. {
  38. terrain = terrainObject.terrainData;
  39. }
  40. }
  41. void OnGUI()
  42. {
  43. if (!terrain)
  44. {
  45. GUILayout.Label("No terrain found");
  46. if (GUILayout.Button("Cancel"))
  47. {
  48. this.Close();
  49. }
  50. return;
  51. }
  52. saveFormat = (BabylonTerrainFormat)EditorGUILayout.EnumPopup("Export Format", saveFormat);
  53. saveResolution = (BabylonTerrainResolution)EditorGUILayout.EnumPopup("Mesh Resolution", saveResolution);
  54. flipNormals = EditorGUILayout.Toggle("Reverse Normals", flipNormals);
  55. if (GUILayout.Button("Export"))
  56. {
  57. Export();
  58. }
  59. }
  60. void Export()
  61. {
  62. int index = 0;
  63. string fileName = EditorUtility.SaveFilePanel("Export Terrain File", "", "Terrain", "obj");
  64. BabylonMesh babylonMesh = new BabylonMesh();
  65. BabylonTerrainData terrainData = Unity3D2Babylon.Tools.CreateTerrainData(terrain, (int)saveResolution, terrainObject.transform.localPosition, false);
  66. Unity3D2Babylon.Tools.GenerateBabylonMeshTerrainData(terrainData, babylonMesh, flipNormals);
  67. System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
  68. StreamWriter sw = new StreamWriter(fileName);
  69. try
  70. {
  71. // StringBuilder stuff is done this way because it's faster than using the "{0} {1} {2}"etc. format
  72. // Which is important when you're exporting huge terrains.
  73. sw.WriteLine("# U3D - BabylonJS - Terrain Mesh File");
  74. // Write vertices
  75. counter = tCount = 0;
  76. totalCount = ((babylonMesh.positions.Length / 3) * 2 + (babylonMesh.indices.Length / 3)) / progressUpdateInterval;
  77. for (index = 0; index < babylonMesh.positions.Length / 3; index++)
  78. {
  79. UpdateProgress();
  80. StringBuilder sb = new StringBuilder("v ", 32);
  81. sb.Append(babylonMesh.positions[index * 3].ToString()).Append(" ").
  82. Append(babylonMesh.positions[index * 3 + 1].ToString()).Append(" ").
  83. Append(babylonMesh.positions[index * 3 + 2].ToString());
  84. sw.WriteLine(sb);
  85. }
  86. // Write normals
  87. for (index = 0; index < babylonMesh.normals.Length / 3; index++)
  88. {
  89. UpdateProgress();
  90. StringBuilder sb = new StringBuilder("vn ", 32);
  91. sb.Append(babylonMesh.normals[index * 3].ToString()).Append(" ").
  92. Append(babylonMesh.normals[index * 3 + 1].ToString()).Append(" ").
  93. Append(babylonMesh.normals[index * 3 + 2].ToString());
  94. sw.WriteLine(sb);
  95. }
  96. // Write uvs
  97. for (index = 0; index < babylonMesh.uvs.Length / 2; index++)
  98. {
  99. UpdateProgress();
  100. StringBuilder sb = new StringBuilder("vt ", 32);
  101. sb.Append(babylonMesh.uvs[index * 2].ToString()).Append(" ").
  102. Append(babylonMesh.uvs[index * 2 + 1].ToString());
  103. sw.WriteLine(sb);
  104. }
  105. // Write triangles
  106. for (int i = 0; i < babylonMesh.indices.Length; i += 3)
  107. {
  108. UpdateProgress();
  109. StringBuilder sb = new StringBuilder("f ", 64);
  110. sb.Append(babylonMesh.indices[i] + 1).Append("/").Append(babylonMesh.indices[i] + 1).Append(" ").
  111. Append(babylonMesh.indices[i + 1] + 1).Append("/").Append(babylonMesh.indices[i + 1] + 1).Append(" ").
  112. Append(babylonMesh.indices[i + 2] + 1).Append("/").Append(babylonMesh.indices[i + 2] + 1);
  113. sw.WriteLine(sb);
  114. }
  115. }
  116. catch (Exception err)
  117. {
  118. Debug.Log("Error saving file: " + err.Message);
  119. }
  120. sw.Close();
  121. terrain = null;
  122. EditorUtility.DisplayProgressBar("Babylon.js", "Saving terrain mesh data... This may take a while.", 1f);
  123. AssetDatabase.Refresh();
  124. EditorUtility.ClearProgressBar();
  125. this.Close();
  126. }
  127. void UpdateProgress()
  128. {
  129. if (counter++ == progressUpdateInterval)
  130. {
  131. counter = 0;
  132. EditorUtility.DisplayProgressBar("Generating terrain mesh...", "", Mathf.InverseLerp(0, totalCount, ++tCount));
  133. }
  134. }
  135. }