Unity3D中的地形转成模型

xiaoxiao2021-02-28  23

using UnityEngine;using UnityEditor; using System; using System.Collections; using System.IO;using System.Text; enum SaveFormat { Triangles, Quads }enum SaveResolution { Full=0, Half, Quarter, Eighth, Sixteenth }class ExportTerrain : 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;        }        EditorWindow.GetWindow<ExportTerrain>().Show();    }     void OnGUI()     {         if (!terrain) {             GUILayout.Label("No terrain found");             if (GUILayout.Button("Cancel"))            {                 EditorWindow.GetWindow<ExportTerrain>().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.heightmapWidth;         int h = terrain.heightmapHeight;        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            System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.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);         EditorWindow.GetWindow<ExportTerrain>().Close(); EditorUtility.ClearProgressBar();    }     void UpdateProgress()     {         if (counter++ == progressUpdateInterval)         { counter = 0; EditorUtility.DisplayProgressBar("Saving...", "", Mathf.InverseLerp(0, totalCount, ++tCount));        }     } }
转载请注明原文地址: https://www.6miu.com/read-2400153.html

最新回复(0)