将Unity3D中的地形导出为*.Obj模型文件

转自XiaoKe\'s Blog 原文地址 http://www.1vr.cn/article.asp?id=518

将下面的脚本放在你项目目录下资源文件夹的Editor里.
要导出地形,首先在你的场景中选中地形对象.如果没选,他将用于当前场景中可用的地 形.从Terrain菜单下选择Export To Obj... ,在分辨率窗口,选择你要四边形还是三角形网格结构.同样也可以选择要导出地形的分辨率,有高中低等等.点击Export,选择要保存的位置和文件 名.Obj文件将被导出.要注意如果选择大面积的Full地形导出,最终的Obj文件将非常大,而且也要导出很久.

下面为 ExportTerrain.js脚本.

001 import System.IO;
002 import System.Text;
003
004 enum SaveFormat {Triangles, Quads}
005 enum SaveResolution {Full, Half, Quarter, Eighth, Sixteenth}
006
007 class ExportTerrain extends EditorWindow {
008 var saveFormat = SaveFormat.Triangles;
009 var saveResolution = SaveResolution.Half;
010 static var terrain : TerrainData;
011 static var terrainPos : Vector3;
012
013 var tCount : int;
014 var counter : int;
015 var totalCount : int;
016
017 @MenuItem ("Terrain/Export To Obj...")
018 static function Init () {
019 terrain = null;
020 var terrainObject : Terrain = Selection.activeObject as Terrain;
021 if (!terrainObject) {
022 terrainObject = Terrain.activeTerrain;
023 }
024 if (terrainObject) {
025 terrain = terrainObject.terrainData;
026 terrainPos = terrainObject.transform.position;
027 }
028 EditorWindow.GetWindow(ExportTerrain).Show();
029 }
030
031 function OnGUI () {
032 if (!terrain) {
033 GUILayout.Label("No terrain found");
034 if (GUILayout.Button("Cancel")) {
035 EditorWindow.GetWindow(ExportTerrain).Close();
036 }
037 return;
038 }
039 saveFormat = EditorGUILayout.EnumPopup("Export Format", saveFormat);
040 saveResolution = EditorGUILayout.EnumPopup("Resolution", saveResolution);
041
042 if (GUILayout.Button("Export")) {

043 Export();
044 }
045 }
046
047 function Export () {
048 var fileName = EditorUtility.SaveFilePanel("Export .obj file", "", "Terrain", "obj");
049 var w = terrain.heightmapWidth;
050 var h = terrain.heightmapHeight;
051 var meshScale = terrain.size;
052 var tRes = Mathf.Pow(2, parseInt(saveResolution));
053 meshScale = Vector3(meshScale.x/(w-1)*tRes, meshScale.y, meshScale.z/(h-1)*tRes);
054 var uvScale = Vector2(1.0/(w-1), 1.0/(h-1));
055 var tData = terrain.GetHeights(0, 0, w, h);
056
057 w = (w-1) / tRes + 1;
058 h = (h-1) / tRes + 1;
059 var tVertices = new Vector3[w * h];
060 var tUV = new Vector2[w * h];
061 if (saveFormat == SaveFormat.Triangles) {
062 var tPolys = new int[(w-1) * (h-1) * 6];
063 }
064 else {
065 tPolys = new int[(w-1) * (h-1) * 4];
066 }
067
068 // Build vertices and UVs
069 for (y = 0; y < h; y++) {
070 for (x = 0; x < w; x++) {
071 tVertices[y*w + x] = Vector3.Scale(meshScale, Vector3(x, tData[x*tRes,y*tRes], y)) + terrainPos;
072 tUV[y*w + x] = Vector2.Scale(Vector2(x*tRes, y*tRes), uvScale);
073 }
074 }
075
076 var index = 0;
077 if (saveFormat == SaveFormat.Triangles) {
078 // Build triangle indices: 3 indices into vertex array for each triangle
079 for (y = 0; y < h-1; y++) {
080 for (x = 0; x < w-1; x++) {
081 // For each grid cell output two triangles
082 tPolys[index++] = (y * w) + x;
083 tPolys[index++] = ((y+1) * w) + x;

084 tPolys[index++] = (y * w) + x + 1;
085
086 tPolys[index++] = ((y+1) * w) + x;
087 tPolys[index++] = ((y+1) * w) + x + 1;
088 tPolys[index++] = (y * w) + x + 1;
089 }
090 }
091 }
092 else {
093 // Build quad indices: 4 indices into vertex array for each quad
094 for (y = 0; y < h-1; y++) {
095 for (x = 0; x < w-1; x++) {
096 // For each grid cell output one quad
097 tPolys[index++] = (y * w) + x;
098 tPolys[index++] = ((y+1) * w) + x;
099 tPolys[index++] = ((y+1) * w) + x + 1;
100 tPolys[index++] = (y * w) + x + 1;
101 }
102 }
103 }
104
105 // Export to .obj
106 try {
107 var sw = new StreamWriter(fileName);
108 sw.WriteLine("# Unity terrain OBJ File");
109
110 // Write vertices
111 System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
112 counter = tCount = 0;
113 totalCount = (tVertices.Length*2 + (saveFormat == SaveFormat.Triangles? tPolys.Length/3 : tPolys.Length/4)) / 1000;
114 for (i = 0; i < tVertices.Length; i++) {
115 UpdateProgress();
116 var sb = StringBuilder("v ", 20);
117 // StringBuilder stuff is done this way because it\'s faster than using the "{0} {1} {2}"etc. format
118 // Which is important when you\'re exporting huge terrains.
119 sb.Append(tVertices[i].x.ToString()).Append(" ").
120 Append(tVertices[i].y.ToString()).Append(" ").
121 Append(tVertices[i].z.ToString());

122 sw.WriteLine(sb);
123 }
124 // Write UVs
125 for (i = 0; i < tUV.Length; i++) {
126 UpdateProgress();
127 sb = StringBuilder("vt ", 22);
128 sb.Append(tUV[i].x.ToString()).Append(" ").
129 Append(tUV[i].y.ToString());
130 sw.WriteLine(sb);
131 }
132 if (saveFormat == SaveFormat.Triangles) {
133 // Write triangles
134 for (i = 0; i < tPolys.Length; i += 3) {
135 UpdateProgress();
136 sb = StringBuilder("f ", 43);
137 sb.Append(tPolys[i]+1).Append("/").Append(tPolys[i]+1).Append(" ").
138 Append(tPolys[i+1]+1).Append("/").Append(tPolys[i+1]+1).Append(" ").
139 Append(tPolys[i+2]+1).Append("/").Append(tPolys[i+2]+1);
140 sw.WriteLine(sb);
141 }
142 }
143 else {
144 // Write quads
145 for (i = 0; i < tPolys.Length; i += 4) {
146 UpdateProgress();
147 sb = StringBuilder("f ", 57);
148 sb.Append(tPolys[i]+1).Append("/").Append(tPolys[i]+1).Append(" ").
149 Append(tPolys[i+1]+1).Append("/").Append(tPolys[i+1]+1).Append(" ").
150 Append(tPolys[i+2]+1).Append("/").Append(tPolys[i+2]+1).Append(" ").
151 Append(tPolys[i+3]+1).Append("/").Append(tPolys[i+3]+1);
152 sw.WriteLine(sb);
153 }
154 }
155 }
156 catch (err) {
157 Debug.Log("Error saving file: " + err.Message);

158 }
159 sw.Close();
160
161 terrain = null;
162 EditorUtility.ClearProgressBar();
163 EditorWindow.GetWindow(ExportTerrain).Close();
164 }
165
166 function UpdateProgress () {
167 if (counter++ == 1000) {
168 counter = 0;
169 EditorUtility.DisplayProgressBar("Saving...", "", Mathf.InverseLerp(0, totalCount, ++tCount));
170 }
171 }
172 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值