Unity地形导出为.obj模型

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


源代码来自于这儿:http://blog.sina.com.cn/s/blog_7812d64701010f7h.html,感谢他的分享!

下面为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里。

 

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

 

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

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

 

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

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

 

下边是我实践过的例子:

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

 

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

 

Maya 2013中打开如下:

 

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

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

 

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

 

Delete删除,大功告成!

 

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

 

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

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值