Skip to main content
AR论坛
 首页 » 资源教程 » Unity3D教程

Unity地形导出为.obj模型

2016年09月04日 17:13:227140

我在Uniyt 3D中创建的真实地形想保存为模型以备以后使用,经过在网上艰辛的搜索(呵呵。。。),终于找到一个方法,经过实验验证,绝对真实可靠!有图有真相!

先上代码(O(_)O哈哈~)。

下面为ExportTerrain.js脚本:

[javascript] view plain copy
  1. import System.IO;  

  2. import System.Text;  

  3.   

  4. enum SaveFormat {Triangles, Quads}  

  5. enum SaveResolution {Full, Half, Quarter, Eighth, Sixteenth}  

  6.   

  7. class ExportTerrain extends EditorWindow   

  8. {  

  9.     var saveFormat = SaveFormat.Triangles;  

  10.     var saveResolution = SaveResolution.Half;  

  11.     static var terrain : TerrainData;  

  12.     static var terrainPos : Vector3;  

  13.        

  14.     var tCount : int;  

  15.     var counter : int;  

  16.     var totalCount : int;  

  17.       

  18.     @MenuItem ("Terrain/Export To Obj...")  

  19.     static function Init ()   

  20.     {  

  21.         terrain = null;  

  22.        var terrainObject : Terrain = Selection.activeObject as Terrain;  

  23.         if (!terrainObject)   

  24.         {  

  25.            terrainObject = Terrain.activeTerrain;  

  26.         }  

  27.         if (terrainObject)   

  28.         {  

  29.             terrain = terrainObject.terrainData;  

  30.             terrainPos = terrainObject.transform.position;  

  31.         }  

  32.         EditorWindow.GetWindow(ExportTerrain).Show();  

  33.     }  

  34.        

  35.     function OnGUI ()   

  36.     {  

  37.        if (!terrain)   

  38.        {  

  39.             GUILayout.Label("No terrain found");  

  40.             if (GUILayout.Button("Cancel"))   

  41.             {  

  42.                 EditorWindow.GetWindow(ExportTerrain).Close();  

  43.             }  

  44.            return;  

  45.      }  

  46.         saveFormat = EditorGUILayout.EnumPopup("Export Format", saveFormat);  

  47.        saveResolution = EditorGUILayout.EnumPopup("Resolution", saveResolution);  

  48.            

  49.         if (GUILayout.Button("Export"))   

  50.         {  

  51.             Export();  

  52.         }  

  53.     }  

  54.        

  55.     function Export ()   

  56.     {  

  57.         var fileName = EditorUtility.SaveFilePanel("Export .obj file""""Terrain""obj");  

  58.        var w = terrain.heightmapWidth;  

  59.         var h = terrain.heightmapHeight;  

  60.         var meshScale = terrain.size;  

  61.         var tRes = Mathf.Pow(2, parseInt(saveResolution));  

  62.         meshScale = Vector3(meshScale.x/(w-1)*tRes, meshScale.y, meshScale.z/(h-1)*tRes);  

  63.         var uvScale = Vector2(1.0/(w-1), 1.0/(h-1));  

  64.         var tData = terrain.GetHeights(0, 0, w, h);  

  65.            

  66.         w = (w-1) / tRes + 1;  

  67.         h = (h-1) / tRes + 1;  

  68.        var tVertices = new Vector3[w * h];  

  69.         var tUV = new Vector2[w * h];  

  70.         if (saveFormat == SaveFormat.Triangles)   

  71.         {  

  72.             var tPolys = new int[(w-1) * (h-1) * 6];  

  73.         }  

  74.         else   

  75.         {  

  76.            tPolys = new int[(w-1) * (h-1) * 4];  

  77.         }  

  78.            

  79.         // Build vertices and UVs  

  80.         for (y = 0; y < h; y++)   

  81.         {  

  82.             for (x = 0; x < w; x++)   

  83.             {  

  84.                 tVertices[y*w + x] = Vector3.Scale(meshScale, Vector3(x, tData[x*tRes,y*tRes], y)) + terrainPos;  

  85.                 tUV[y*w + x] = Vector2.Scale(Vector2(x*tRes, y*tRes), uvScale);  

  86.             }  

  87.         }  

  88.        

  89.        var index = 0;  

  90.         if (saveFormat == SaveFormat.Triangles)   

  91.         {  

  92.             // Build triangle indices: 3 indices into vertex array for each triangle  

  93.             for (y = 0; y < h-1; y++)   

  94.             {  

  95.                 for (x = 0; x < w-1; x++)   

  96.                 {  

  97.                     // For each grid cell output two triangles  

  98.                     tPolys[index++] = (y     * w) + x;  

  99.                     tPolys[index++] = ((y+1) * w) + x;  

  100.                     tPolys[index++] = (y     * w) + x + 1;  

  101.            

  102.                    tPolys[index++] = ((y+1) * w) + x;  

  103.                     tPolys[index++] = ((y+1) * w) + x + 1;  

  104.                    tPolys[index++] = (y     * w) + x + 1;  

  105.                 }  

  106.             }  

  107.         }  

  108.         else   

  109.         {  

  110.             // Build quad indices: 4 indices into vertex array for each quad  

  111.             for (y = 0; y < h-1; y++)   

  112.             {  

  113.                 for (x = 0; x < w-1; x++)   

  114.                 {  

  115.                     // For each grid cell output one quad  

  116.                     tPolys[index++] = (y     * w) + x;  

  117.                     tPolys[index++] = ((y+1) * w) + x;  

  118.                     tPolys[index++] = ((y+1) * w) + x + 1;  

  119.                     tPolys[index++] = (y     * w) + x + 1;  

  120.                 }  

  121.             }    

  122.         }  

  123.        

  124.        // Export to .obj  

  125.         try   

  126.         {  

  127.             var sw = new StreamWriter(fileName);  

  128.             sw.WriteLine("# Unity terrain OBJ File");  

  129.                

  130.             // Write vertices  

  131.             System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");  

  132.             counter = tCount = 0;  

  133.            totalCount = (tVertices.Length*2 + (saveFormat == SaveFormat.Triangles? tPolys.Length/3 : tPolys.Length/4)) / 1000;  

  134.             for (i = 0; i < tVertices.Length; i++)   

  135.             {  

  136.                 UpdateProgress();  

  137.                 var sb = StringBuilder("v ", 20);  

  138.                // StringBuilder stuff is done this way because it's faster than using the "{0} {1} {2}"etc. format  

  139.                 // Which is important when you're exporting huge terrains.  

  140.                 sb.Append(tVertices[i].x.ToString()).Append(" ").  

  141.                    Append(tVertices[i].y.ToString()).Append(" ").  

  142.                    Append(tVertices[i].z.ToString());  

  143.                 sw.WriteLine(sb);  

  144.             }  

  145.             // Write UVs  

  146.            for (i = 0; i < tUV.Length; i++)   

  147.            {  

  148.                 UpdateProgress();  

  149.                sb = StringBuilder("vt ", 22);  

  150.                 sb.Append(tUV[i].x.ToString()).Append(" ").  

  151.                    Append(tUV[i].y.ToString());  

  152.                 sw.WriteLine(sb);  

  153.             }  

  154.             if (saveFormat == SaveFormat.Triangles)   

  155.             {  

  156.                // Write triangles  

  157.                 for (i = 0; i < tPolys.Length; i += 3)   

  158.                 {  

  159.                     UpdateProgress();  

  160.                    sb = StringBuilder("f ", 43);  

  161.                     sb.Append(tPolys[i]+1).Append("/").Append(tPolys[i]+1).Append(" ").  

  162.                        Append(tPolys[i+1]+1).Append("/").Append(tPolys[i+1]+1).Append(" ").  

  163.                        Append(tPolys[i+2]+1).Append("/").Append(tPolys[i+2]+1);  

  164.                     sw.WriteLine(sb);  

  165.                 }  

  166.             }  

  167.             else   

  168.             {  

  169.                 // Write quads  

  170.                 for (i = 0; i < tPolys.Length; i += 4)   

  171.                 {  

  172.                     UpdateProgress();  

  173.                     sb = StringBuilder("f ", 57);  

  174.                     sb.Append(tPolys[i]+1).Append("/").Append(tPolys[i]+1).Append(" ").  

  175.                        Append(tPolys[i+1]+1).Append("/").Append(tPolys[i+1]+1).Append(" ").  

  176.                        Append(tPolys[i+2]+1).Append("/").Append(tPolys[i+2]+1).Append(" ").  

  177.                        Append(tPolys[i+3]+1).Append("/").Append(tPolys[i+3]+1);  

  178.                     sw.WriteLine(sb);  

  179.                 }        

  180.             }  

  181.         }  

  182.         catch (err)   

  183.         {  

  184.             Debug.Log("Error saving file: " + err.Message);  

  185.         }  

  186.        sw.Close();  

  187.            

  188.         terrain = null;  

  189.         EditorUtility.ClearProgressBar();  

  190.         EditorWindow.GetWindow(ExportTerrain).Close();  

  191.     }  

  192.        

  193.     function UpdateProgress ()   

  194.     {  

  195.         if (counter++ == 1000)   

  196.         {  

  197.             counter = 0;  

  198.             EditorUtility.DisplayProgressBar("Saving...""", Mathf.InverseLerp(0, totalCount, ++tCount));  

  199.         }  

  200.         }     

  201.  }    


将上面的脚本放在Unity项的目录资源文件夹的Editor里。

Unity地形导出为.obj模型 Unity3D教程 第1张

刷新一下菜单栏,会发现多了一个Terrain的菜单。

Unity地形导出为.obj模型 Unity3D教程 第2张

先在场景中选中地形对象,如果没选,他将用于当前场景中可用的地形。

然后从Terrain菜单下选择Export To Obj...

Unity地形导出为.obj模型 Unity3D教程 第3张

接下来会弹出一个框,在这里你可以选择要导出四边形网络结构还是三角形网络结构,还可以选择要导出的地形的分辨率,有高中低...。最后点击Export,选择要保存的位置和文件名,.obj文件将被导出。

注意:如果选择大面积的Full地形导出,最终.obj文件将非常大,而且也要导出很久。

Unity地形导出为.obj模型 Unity3D教程 第4张

下边是我实践过的例子:

Uniyt 4.6.2中创建的真实地形(钓鱼岛哈):

Unity地形导出为.obj模型 Unity3D教程 第5张

导出.obj格式的模型(模型和贴图):

Unity地形导出为.obj模型 Unity3D教程 第6张

在Maya 2013中打开如下:

Unity地形导出为.obj模型 Unity3D教程 第7张

哎呀,怎么是这个样子?我只想要钓鱼岛,该怎么办?只要在Maya里简单处理一下就好了。

选中模型,右键选择“面”:

Unity地形导出为.obj模型 Unity3D教程 第8张

框选中模型整体,然后切换到侧视图,按着Shift键,用鼠标框选突出的部分。(注意:要稍微比水平面高一点。)

Unity地形导出为.obj模型 Unity3D教程 第9张

Delete删除,大功告成!

Unity地形导出为.obj模型 Unity3D教程 第10张

好啦,给他加上贴图,导出为FBX文件,再放回Unity看看(钓鱼岛和达山岛)。

Unity地形导出为.obj模型 Unity3D教程 第11张

PS:.obj模型在maya中打开是没有贴图的,需要重新为其附贴图。


评论列表暂无评论
发表评论