- 积分
- 29
- 帖子
- 4
- 主题
- 1
- 精华
- 0
- 最后登录
- 2015-10-18
- 在线时间
- 2 小时
- 私信
|
发表时间 : 2015-10-12 19:42:53
|
浏览 : 1312 评论 : 0
将下面的脚本放在你项目目录下资源文件夹的Editor里.
要导出地形,首先在你的场景中选中地形对象.如果没选,他将用于当前场景中可用的地形.从Terrain菜单下选择Export To Obj... ,在分辨率窗口,选择你要四边形还是三角形网格结构.同样也可以选择要导出地形的分辨率,有高中低等等.点击Export,选择要保存的位置和文件名.Obj文件将被导出.要注意如果选择大面积的Full地形导出,最终的Obj文件将非常大,而且也要导出很久.
下面为ExportTerrain.js脚本.
001 import System.IO;
002 import System.Text;
003 enum SaveFormat {Triangles, Quads}
004 enum SaveResolution {Full, Half, Quarter, Eighth, Sixteenth}
005 class ExportTerrain extends EditorWindow {
006 var saveFormat = SaveFormat.Triangles;
007 var saveResolution = SaveResolution.Half;
008 static var terrain : TerrainData;
009 static var terrainPos : Vector3;
010
011 var tCount : int;
012 var counter : int;
013 var totalCount : int;
014
015 @MenuItem ("Terrain/Export To Obj...")
016 static function Init () {
017 terrain = null;
018 var terrainObject : Terrain = Selection.activeObject as Terrain;
019 if (!terrainObject) {
020 terrainObject = Terrain.activeTerrain;
021 }
022 if (terrainObject) {
023 terrain = terrainObject.terrainData;
024 terrainPos = terrainObject.transform.position;
025 }
026 EditorWindow.GetWindow(ExportTerrain).Show();
027 }
028
029 function OnGUI () {
030 if (!terrain) {
031 GUILayout.Label("No terrain found");
032 if (GUILayout.Button("Cancel")) {
033 EditorWindow.GetWindow(ExportTerrain).Close();
034 }
035 return;
036 }
037 saveFormat = EditorGUILayout.EnumPopup("Export Format", saveFormat);
038 saveResolution = EditorGUILayout.EnumPopup("Resolution", saveResolution);
039
040 if (GUILayout.Button("Export")) {
041 Export();
042 }
043 }
044
045 function Export () {
046 var fileName = EditorUtility.SaveFilePanel("Export .obj file", "", "Terrain", "obj");
047 var w = terrain.heightmapWidth;
048 var h = terrain.heightmapHeight;
049 var meshScale = terrain.size;
050 var tRes = Mathf.Pow(2, parseInt(saveResolution));
051 meshScale = Vector3(meshScale.x/(w-1)*tRes, meshScale.y, meshScale.z/(h-1)*tRes);
052 var uvScale = Vector2(1.0/(w-1), 1.0/(h-1));
053 var tData = terrain.GetHeights(0, 0, w, h);
054
055 w = (w-1) / tRes + 1;
056 h = (h-1) / tRes + 1;
057 var tVertices = new Vector3[w * h];
058 var tUV = new Vector2[w * h];
059 if (saveFormat == SaveFormat.Triangles) {
060 var tPolys = new int[(w-1) * (h-1) * 6];
061 }
062 else {
063 tPolys = new int[(w-1) * (h-1) * 4];
064 }
065
066 // Build vertices and UVs
067 for (y = 0; y < h; y++) {
068 for (x = 0; x < w; x++) {
069 tVertices[y*w + x] = Vector3.Scale(meshScale, Vector3(x, tData[x*tRes,y*tRes], y)) + terrainPos;
070 tUV[y*w + x] = Vector2.Scale(Vector2(x*tRes, y*tRes), uvScale);
071 }
072 }
073
074 var index = 0;
075 if (saveFormat == SaveFormat.Triangles) {
076 // Build triangle indices: 3 indices into vertex array for each triangle
077 for (y = 0; y < h-1; y++) {
078 for (x = 0; x < w-1; x++) {
079 // For each grid cell output two triangles
080 tPolys[index++] = (y * w) + x;
081 tPolys[index++] = ((y+1) * w) + x;
082 tPolys[index++] = (y * w) + x + 1;
083
084 tPolys[index++] = ((y+1) * w) + x;
085 tPolys[index++] = ((y+1) * w) + x + 1;
086 tPolys[index++] = (y * w) + x + 1;
087 }
088 }
089 }
090 else {
091 // Build quad indices: 4 indices into vertex array for each quad
092 for (y = 0; y < h-1; y++) {
093 for (x = 0; x < w-1; x++) {
094 // For each grid cell output one quad
095 tPolys[index++] = (y * w) + x;
096 tPolys[index++] = ((y+1) * w) + x;
097 tPolys[index++] = ((y+1) * w) + x + 1;
098 tPolys[index++] = (y * w) + x + 1;
099 }
100 }
101 }
102
103 // Export to .obj
104 try {
105 var sw = new StreamWriter(fileName);
106 sw.WriteLine("# Unity terrain OBJ File");
107
108 // Write vertices
109 System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
110 counter = tCount = 0;
111 totalCount = (tVertices.Length*2 + (saveFormat == SaveFormat.Triangles? tPolys.Length/3 : tPolys.Length/4)) / 1000;
112 for (i = 0; i < tVertices.Length; i++) {
113 UpdateProgress();
114 var sb = StringBuilder("v ", 20);
115 // StringBuilder stuff is done this way because it's faster than using the "{0} {1} {2}"etc. format
116 // Which is important when you're exporting huge terrains.
117 sb.Append(tVertices[i].x.ToString()).Append(" ").
118 Append(tVertices[i].y.ToString()).Append(" ").
119 Append(tVertices[i].z.ToString());
120 sw.WriteLine(sb);
121 }
122 // Write UVs
123 for (i = 0; i < tUV.Length; i++) {
124 UpdateProgress();
125 sb = StringBuilder("vt ", 22);
126 sb.Append(tUV[i].x.ToString()).Append(" ").
127 Append(tUV[i].y.ToString());
128 sw.WriteLine(sb);
129 }
130 if (saveFormat == SaveFormat.Triangles) {
131 // Write triangles
132 for (i = 0; i < tPolys.Length; i += 3) {
133 UpdateProgress();
134 sb = StringBuilder("f ", 43);
135 sb.Append(tPolys[i]+1).Append("/").Append(tPolys[i]+1).Append(" ").
136 Append(tPolys[i+1]+1).Append("/").Append(tPolys[i+1]+1).Append(" ").
137 Append(tPolys[i+2]+1).Append("/").Append(tPolys[i+2]+1);
138 sw.WriteLine(sb);
139 }
140 }
141 else {
142 // Write quads
143 for (i = 0; i < tPolys.Length; i += 4) {
144 UpdateProgress();
145 sb = StringBuilder("f ", 57);
146 sb.Append(tPolys[i]+1).Append("/").Append(tPolys[i]+1).Append(" ").
147 Append(tPolys[i+1]+1).Append("/").Append(tPolys[i+1]+1).Append(" ").
148 Append(tPolys[i+2]+1).Append("/").Append(tPolys[i+2]+1).Append(" ").
149 Append(tPolys[i+3]+1).Append("/").Append(tPolys[i+3]+1);
150 sw.WriteLine(sb);
151 }
152 }
153 }
154 catch (err) {
155 Debug.Log("Error saving file: " + err.Message);
156 }
157 sw.Close();
158
159 terrain = null;
160 EditorUtility.ClearProgressBar();
161 EditorWindow.GetWindow(ExportTerrain).Close();
162 }
163
164 function UpdateProgress () {
165 if (counter++ == 1000) {
166 counter = 0;
167 EditorUtility.DisplayProgressBar("Saving...", "", Mathf.InverseLerp(0, totalCount, ++tCount));
168 }
169 }
170 }
|
|