-
-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
233 additions
and
227 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,230 @@ | ||
// Converted from UnityScript to C# at http://www.M2H.nl/files/js_to_c.php - by Mike Hergaarden | ||
// C # manual conversion work by Yun Kyu Choi | ||
|
||
using System; | ||
using System.Globalization; | ||
using System.IO; | ||
using System.Text; | ||
using System.Threading; | ||
using UnityEditor; | ||
using UnityEngine; | ||
|
||
namespace UniRecast.Editor | ||
{ | ||
enum SaveFormat | ||
{ | ||
Triangles, | ||
Quads | ||
} | ||
|
||
enum SaveResolution | ||
{ | ||
Full = 0, | ||
Half, | ||
Quarter, | ||
Eighth, | ||
Sixteenth | ||
} | ||
|
||
public class UniRcTerrainObjExporter : EditorWindow | ||
{ | ||
SaveFormat saveFormat = SaveFormat.Triangles; | ||
SaveResolution saveResolution = SaveResolution.Half; | ||
|
||
static TerrainData terrain; | ||
static Vector3 terrainPos; | ||
|
||
int tCount; | ||
int counter; | ||
int totalCount; | ||
int progressUpdateInterval = 10000; | ||
|
||
[MenuItem("Terrain/Export To Obj...")] | ||
static void Init() | ||
{ | ||
terrain = null; | ||
Terrain terrainObject = Selection.activeObject as Terrain; | ||
if (!terrainObject) | ||
{ | ||
terrainObject = Terrain.activeTerrain; | ||
} | ||
|
||
if (terrainObject) | ||
{ | ||
terrain = terrainObject.terrainData; | ||
terrainPos = terrainObject.transform.position; | ||
} | ||
|
||
GetWindow<UniRcTerrainObjExporter>().Show(); | ||
} | ||
|
||
void OnGUI() | ||
{ | ||
if (!terrain) | ||
{ | ||
GUILayout.Label("No terrain found"); | ||
if (GUILayout.Button("Cancel")) | ||
{ | ||
GetWindow<UniRcTerrainObjExporter>().Close(); | ||
} | ||
|
||
return; | ||
} | ||
|
||
saveFormat = (SaveFormat)EditorGUILayout.EnumPopup("Export Format", saveFormat); | ||
|
||
saveResolution = (SaveResolution)EditorGUILayout.EnumPopup("Resolution", saveResolution); | ||
|
||
if (GUILayout.Button("Export")) | ||
{ | ||
Export(); | ||
} | ||
} | ||
|
||
void Export() | ||
{ | ||
string fileName = EditorUtility.SaveFilePanel("Export .obj file", "", "Terrain", "obj"); | ||
int w = terrain.heightmapResolution; | ||
int h = terrain.heightmapResolution; | ||
Vector3 meshScale = terrain.size; | ||
int tRes = (int)Mathf.Pow(2, (int)saveResolution); | ||
meshScale = new Vector3(meshScale.x / (w - 1) * tRes, meshScale.y, meshScale.z / (h - 1) * tRes); | ||
Vector2 uvScale = new Vector2(1.0f / (w - 1), 1.0f / (h - 1)); | ||
float[,] tData = terrain.GetHeights(0, 0, w, h); | ||
|
||
w = (w - 1) / tRes + 1; | ||
h = (h - 1) / tRes + 1; | ||
Vector3[] tVertices = new Vector3[w * h]; | ||
Vector2[] tUV = new Vector2[w * h]; | ||
|
||
int[] tPolys; | ||
|
||
if (saveFormat == SaveFormat.Triangles) | ||
{ | ||
tPolys = new int[(w - 1) * (h - 1) * 6]; | ||
} | ||
else | ||
{ | ||
tPolys = new int[(w - 1) * (h - 1) * 4]; | ||
} | ||
|
||
// Build vertices and UVs | ||
for (int y = 0; y < h; y++) | ||
{ | ||
for (int x = 0; x < w; x++) | ||
{ | ||
tVertices[y * w + x] = Vector3.Scale(meshScale, new Vector3(-y, tData[x * tRes, y * tRes], x)) + terrainPos; | ||
tUV[y * w + x] = Vector2.Scale(new Vector2(x * tRes, y * tRes), uvScale); | ||
} | ||
} | ||
|
||
int index = 0; | ||
if (saveFormat == SaveFormat.Triangles) | ||
{ | ||
// Build triangle indices: 3 indices into vertex array for each triangle | ||
for (int y = 0; y < h - 1; y++) | ||
{ | ||
for (int x = 0; x < w - 1; x++) | ||
{ | ||
// For each grid cell output two triangles | ||
tPolys[index++] = (y * w) + x; | ||
tPolys[index++] = ((y + 1) * w) + x; | ||
tPolys[index++] = (y * w) + x + 1; | ||
|
||
tPolys[index++] = ((y + 1) * w) + x; | ||
tPolys[index++] = ((y + 1) * w) + x + 1; | ||
tPolys[index++] = (y * w) + x + 1; | ||
} | ||
} | ||
} | ||
else | ||
{ | ||
// Build quad indices: 4 indices into vertex array for each quad | ||
for (int y = 0; y < h - 1; y++) | ||
{ | ||
for (int x = 0; x < w - 1; x++) | ||
{ | ||
// For each grid cell output one quad | ||
tPolys[index++] = (y * w) + x; | ||
tPolys[index++] = ((y + 1) * w) + x; | ||
tPolys[index++] = ((y + 1) * w) + x + 1; | ||
tPolys[index++] = (y * w) + x + 1; | ||
} | ||
} | ||
} | ||
|
||
// Export to .obj | ||
StreamWriter sw = new StreamWriter(fileName); | ||
try | ||
{ | ||
sw.WriteLine("# Unity terrain OBJ File"); | ||
|
||
// Write vertices | ||
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); | ||
counter = tCount = 0; | ||
totalCount = (tVertices.Length * 2 + (saveFormat == SaveFormat.Triangles ? tPolys.Length / 3 : tPolys.Length / 4)) / progressUpdateInterval; | ||
for (int i = 0; i < tVertices.Length; i++) | ||
{ | ||
UpdateProgress(); | ||
StringBuilder sb = new StringBuilder("v ", 20); | ||
// StringBuilder stuff is done this way because it's faster than using the "{0} {1} {2}"etc. format | ||
// Which is important when you're exporting huge terrains. | ||
sb.Append(tVertices[i].x.ToString()).Append(" ").Append(tVertices[i].y.ToString()).Append(" ").Append(tVertices[i].z.ToString()); | ||
sw.WriteLine(sb); | ||
} | ||
|
||
// Write UVs | ||
for (int i = 0; i < tUV.Length; i++) | ||
{ | ||
UpdateProgress(); | ||
StringBuilder sb = new StringBuilder("vt ", 22); | ||
sb.Append(tUV[i].x.ToString()).Append(" ").Append(tUV[i].y.ToString()); | ||
sw.WriteLine(sb); | ||
} | ||
|
||
if (saveFormat == SaveFormat.Triangles) | ||
{ | ||
// Write triangles | ||
for (int i = 0; i < tPolys.Length; i += 3) | ||
{ | ||
UpdateProgress(); | ||
StringBuilder sb = new StringBuilder("f ", 43); | ||
sb.Append(tPolys[i] + 1).Append("/").Append(tPolys[i] + 1).Append(" ").Append(tPolys[i + 1] + 1).Append("/").Append(tPolys[i + 1] + 1).Append(" ").Append(tPolys[i + 2] + 1).Append("/").Append(tPolys[i + 2] + 1); | ||
sw.WriteLine(sb); | ||
} | ||
} | ||
else | ||
{ | ||
// Write quads | ||
for (int i = 0; i < tPolys.Length; i += 4) | ||
{ | ||
UpdateProgress(); | ||
StringBuilder sb = new StringBuilder("f ", 57); | ||
sb.Append(tPolys[i] + 1).Append("/").Append(tPolys[i] + 1).Append(" ").Append(tPolys[i + 1] + 1).Append("/").Append(tPolys[i + 1] + 1).Append(" ").Append(tPolys[i + 2] + 1).Append("/").Append(tPolys[i + 2] + 1).Append(" ").Append(tPolys[i + 3] + 1).Append("/").Append(tPolys[i + 3] + 1); | ||
sw.WriteLine(sb); | ||
} | ||
} | ||
} | ||
catch (Exception err) | ||
{ | ||
Debug.Log("Error saving file: " + err.Message); | ||
} | ||
|
||
sw.Close(); | ||
|
||
terrain = null; | ||
EditorUtility.DisplayProgressBar("Saving file to disc.", "This might take a while...", 1f); | ||
GetWindow<UniRcTerrainObjExporter>().Close(); | ||
EditorUtility.ClearProgressBar(); | ||
} | ||
|
||
void UpdateProgress() | ||
{ | ||
if (counter++ == progressUpdateInterval) | ||
{ | ||
counter = 0; | ||
EditorUtility.DisplayProgressBar("Saving...", "", Mathf.InverseLerp(0, totalCount, ++tCount)); | ||
} | ||
} | ||
} | ||
} |
File renamed without changes.
Oops, something went wrong.