Unity地形导出为.obj模型
我在Uniyt?3D中創建的真實地形想保存為模型以備以后使用,經過在網上艱辛的搜索(呵呵。。。),終于找到一個方法,經過實驗驗證,絕對真實可靠!有圖有真相!
先上代碼(O(∩_∩)O哈哈~)。
源代碼來自于這兒:http://blog.sina.com.cn/s/blog_7812d64701010f7h.html,感謝他的分享!
下面為ExportTerrain.js腳本:
import System.IO;import System.Text;enum SaveFormat {Triangles, Quads}enum SaveResolution {Full, Half, Quarter, Eighth, Sixteenth}class ExportTerrain extends EditorWindow {var saveFormat = SaveFormat.Triangles;var saveResolution = SaveResolution.Half;static var terrain : TerrainData;static var terrainPos : Vector3;var tCount : int;var counter : int;var totalCount : int;@MenuItem ("Terrain/Export To Obj...")static function Init () {terrain = null;var terrainObject : Terrain = Selection.activeObject as Terrain;if (!terrainObject) {terrainObject = Terrain.activeTerrain;}if (terrainObject) {terrain = terrainObject.terrainData;terrainPos = terrainObject.transform.position;}EditorWindow.GetWindow(ExportTerrain).Show();}function OnGUI () {if (!terrain) {GUILayout.Label("No terrain found");if (GUILayout.Button("Cancel")) {EditorWindow.GetWindow(ExportTerrain).Close();}return;}saveFormat = EditorGUILayout.EnumPopup("Export Format", saveFormat);saveResolution = EditorGUILayout.EnumPopup("Resolution", saveResolution);if (GUILayout.Button("Export")) {Export();}}function Export () {var fileName = EditorUtility.SaveFilePanel("Export .obj file", "", "Terrain", "obj");var w = terrain.heightmapWidth;var h = terrain.heightmapHeight;var meshScale = terrain.size;var tRes = Mathf.Pow(2, parseInt(saveResolution));meshScale = Vector3(meshScale.x/(w-1)*tRes, meshScale.y, meshScale.z/(h-1)*tRes);var uvScale = Vector2(1.0/(w-1), 1.0/(h-1));var tData = terrain.GetHeights(0, 0, w, h);w = (w-1) / tRes + 1;h = (h-1) / tRes + 1;var tVertices = new Vector3[w * h];var tUV = new Vector2[w * h];if (saveFormat == SaveFormat.Triangles) {var tPolys = new int[(w-1) * (h-1) * 6];}else {tPolys = new int[(w-1) * (h-1) * 4];}// Build vertices and UVsfor (y = 0; y < h; y++) {for (x = 0; x < w; x++) {tVertices[y*w + x] = Vector3.Scale(meshScale, Vector3(x, tData[x*tRes,y*tRes], y)) + terrainPos;tUV[y*w + x] = Vector2.Scale(Vector2(x*tRes, y*tRes), uvScale);}}var index = 0;if (saveFormat == SaveFormat.Triangles) {// Build triangle indices: 3 indices into vertex array for each trianglefor (y = 0; y < h-1; y++) {for (x = 0; x < w-1; x++) {// For each grid cell output two trianglestPolys[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 quadfor (y = 0; y < h-1; y++) {for (x = 0; x < w-1; x++) {// For each grid cell output one quadtPolys[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 .objtry {var sw = new StreamWriter(fileName);sw.WriteLine("# Unity terrain OBJ File");// Write verticesSystem.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)) / 1000;for (i = 0; i < tVertices.Length; i++) {UpdateProgress();var sb = 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 UVsfor (i = 0; i < tUV.Length; i++) {UpdateProgress();sb = StringBuilder("vt ", 22);sb.Append(tUV[i].x.ToString()).Append(" ").Append(tUV[i].y.ToString());sw.WriteLine(sb);}if (saveFormat == SaveFormat.Triangles) {// Write trianglesfor (i = 0; i < tPolys.Length; i += 3) {UpdateProgress();sb = 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 quadsfor (i = 0; i < tPolys.Length; i += 4) {UpdateProgress();sb = 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 (err) {Debug.Log("Error saving file: " + err.Message);}sw.Close();terrain = null;EditorUtility.ClearProgressBar();EditorWindow.GetWindow(ExportTerrain).Close();}function UpdateProgress () {if (counter++ == 1000) {counter = 0;EditorUtility.DisplayProgressBar("Saving...", "", Mathf.InverseLerp(0, totalCount, ++tCount));}} }
將上面的腳本放在Unity項的目錄資源文件夾的Editor里。
?
刷新一下菜單欄,會發現多了一個Terrain的菜單。
?
先在場景中選中地形對象,如果沒選,他將用于當前場景中可用的地形。
然后從Terrain菜單下選擇Export?To?Obj...
?
接下來會彈出一個框,在這里你可以選擇要導出四邊形網絡結構還是三角形網絡結構,還可以選擇要導出的地形的分辨率,有高中低...。最后點擊Export,選擇要保存的位置和文件名,.obj文件將被導出。
注意:如果選擇大面積的Full地形導出,最終.obj文件將非常大,而且也要導出很久。
?
下邊是我實踐過的例子:
Uniyt?4.6.2中創建的真實地形(釣魚島哈):
?
導出.obj格式的模型(模型和貼圖):
?
在Maya?2013中打開如下:
?
哎呀,怎么是這個樣子?我只想要釣魚島,該怎么辦?只要在Maya里簡單處理一下就好了。
選中模型,右鍵選擇“面”:
?
框選中模型整體,然后切換到側視圖,按著Shift鍵,用鼠標框選突出的部分。(注意:要稍微比水平面高一點。)
?
Delete刪除,大功告成!
?
好啦,給他加上貼圖,導出為FBX文件,再放回Unity看看(釣魚島和達山島)。
?
PS:.obj模型在maya中打開是沒有貼圖的,需要重新為其附貼圖。
?
總結
以上是生活随笔為你收集整理的Unity地形导出为.obj模型的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 文件修复软件winhex
- 下一篇: 基于java+ssm教学质量评价系统(学