Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by WinterT101 · Sep 30, 2016 at 07:07 AM · terrainexportingobjautomaticallyall

Modifying TerraintoObj for multiple terrain export

I am attempting to modify TerraintoObj (originally made by @Eric5h5) to export more than a single mesh by looping. I just started learning the scripting language and I've been holding out asking for help so I could figure it out myself but I'm stuck. In the code below I'm trying to use a do while loop to cycle through the code if terrains still exist in the scene. My end game was to have this script run without me having to confirm anything after the first format and resolution selection but I need to get past this do while loop issue first. Any help or insight is greatly appreciated!

WARNING THE CODE BELOW LOCKS UP UNITY

 // Converted from UnityScript to C# at http://www.M2H.nl/files/js_to_c.php - by Mike Hergaarden
 // C # manual conversion work by Yun Kyu Choi
  
 using UnityEngine;
 using UnityEditor;
 using System;
 using System.Collections;
 using System.IO;
 using System.Text;
  
 enum SaveFormat { Triangles, Quads }
 enum SaveResolution { Full=0, Half, Quarter, Eighth, Sixteenth }
  
 class ExportTerrain : EditorWindow
 {
    SaveFormat saveFormat = SaveFormat.Triangles;
    SaveResolution saveResolution = SaveResolution.Half;
  
    static TerrainData terrain;
    static Vector3 terrainPos;
  
    int tCount;
    int counter;
    int totalCount;
    int progressUpdateInterval = 10000;
     bool terrainPresent = true;
  
    [MenuItem("Terrain/Export To Obj...")]
    static void Init()
    {
       terrain = null;
       Terrain terrainObject = Selection.activeObject as Terrain;
       if (!terrainObject)
       {
          terrainObject = Terrain.activeTerrain;
       }
       if (terrainObject)
       {
          terrain = terrainObject.terrainData;
          terrainPos = terrainObject.transform.position;
       }
  
       EditorWindow.GetWindow<ExportTerrain>().Show();
    }
  
    void OnGUI()
    {
       if (!terrain)
       {
          GUILayout.Label("No terrain found");
          if (GUILayout.Button("Cancel"))
          {
             EditorWindow.GetWindow<ExportTerrain>().Close();
                 terrainPresent = false;
          }
          return;
       }
       saveFormat = (SaveFormat) EditorGUILayout.EnumPopup("Export Format", saveFormat);
  
       saveResolution = (SaveResolution) EditorGUILayout.EnumPopup("Resolution", saveResolution);
  
       if (GUILayout.Button("Export"))
       {
          Export();
       }
    }
  
     void Export()
    {
 
         string fileName = EditorUtility.SaveFilePanel("Export .obj file", "", Terrain.activeTerrain.name, "obj");
       int w = terrain.heightmapWidth;
       int h = terrain.heightmapHeight;
       Vector3 meshScale = terrain.size;
       int tRes = (int)Mathf.Pow(2, (int)saveResolution );
       meshScale = new Vector3(meshScale.x / (w - 1) * tRes, meshScale.y, meshScale.z / (h - 1) * tRes);
       Vector2 uvScale = new Vector2(1.0f / (w - 1), 1.0f / (h - 1));
       float[,] tData = terrain.GetHeights(0, 0, w, h);
  
       w = (w - 1) / tRes + 1;
       h = (h - 1) / tRes + 1;
       Vector3[] tVertices = new Vector3[w * h];
       Vector2[] tUV = new Vector2[w * h];
  
       int[] tPolys;
  
       if (saveFormat == SaveFormat.Triangles)
       {
          tPolys = new int[(w - 1) * (h - 1) * 6];
       }
       else
       {
          tPolys = new int[(w - 1) * (h - 1) * 4];
       }
  
       // Build vertices and UVs
       for (int y = 0; y < h; y++)
       {
          for (int x = 0; x < w; x++)
          {
             tVertices[y * w + x] = Vector3.Scale(meshScale, new Vector3(-y, tData[x * tRes, y * tRes], x)) + terrainPos;
             tUV[y * w + x] = Vector2.Scale( new Vector2(x * tRes, y * tRes), uvScale);
          }
       }
  
       int  index = 0;
       if (saveFormat == SaveFormat.Triangles)
       {
          // Build triangle indices: 3 indices into vertex array for each triangle
          for (int y = 0; y < h - 1; y++)
          {
             for (int x = 0; x < w - 1; x++)
             {
                // For each grid cell output two triangles
                tPolys[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 quad
          for (int y = 0; y < h - 1; y++)
          {
             for (int x = 0; x < w - 1; x++)
             {
                // For each grid cell output one quad
                tPolys[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 .obj
       StreamWriter sw = new StreamWriter(fileName);
       try
       {
  
          sw.WriteLine("# Unity terrain OBJ File");
  
          // Write vertices
          System.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)) / progressUpdateInterval;
          for (int i = 0; i < tVertices.Length; i++)
          {
             UpdateProgress();
             StringBuilder sb = new 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 UVs
          for (int i = 0; i < tUV.Length; i++)
          {
             UpdateProgress();
             StringBuilder sb = new StringBuilder("vt ", 22);
             sb.Append(tUV[i].x.ToString()).Append(" ").
                Append(tUV[i].y.ToString());
             sw.WriteLine(sb);
          }
          if (saveFormat == SaveFormat.Triangles)
          {
             // Write triangles
             for (int i = 0; i < tPolys.Length; i += 3)
             {
                UpdateProgress();
                StringBuilder sb = new 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 quads
             for (int i = 0; i < tPolys.Length; i += 4)
             {
                UpdateProgress();
                StringBuilder sb = new 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(Exception err)
       {
          Debug.Log("Error saving file: " + err.Message);
       }
       sw.Close();
  
       terrain = null;
       EditorUtility.DisplayProgressBar("Saving file to disc.", "This might take a while...", 1f);
       EditorWindow.GetWindow<ExportTerrain>().Close();      
       EditorUtility.ClearProgressBar();
 
         DestroyImmediate (Terrain.activeTerrain);
         if (!terrain)
             {
                 terrainPresent = false;
             } 
 
             while (terrainPresent = true) {
                 Export ();
 
             }
         
    }
  
    void UpdateProgress()
    {
       if (counter++ == progressUpdateInterval)
       {
          counter = 0;
          EditorUtility.DisplayProgressBar("Saving...", "", Mathf.InverseLerp(0, totalCount, ++tCount));
       }
    }
 }
Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image WinterT101 · Oct 01, 2016 at 07:01 PM 0
Share

Note: The code creates a NullReference on line 71 if only a single terrain exists. If there are two or more terrains in the scene the NullReference is on line 72. I think it is due to the fact that terrain is static and needs to e "refreshed" after the active terrain is destroyed. No idea how to do this however.

0 Replies

· Add your reply
  • Sort: 

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

3 People are following this question.

avatar image avatar image avatar image

Related Questions

Do I have to manually assign every texture to material? 0 Answers

Exporting OBJ WITH transform information 0 Answers

How to export the materials of a model to a 2D UV map .png? -1 Answers

Problem importing 3D obj as Terrain 1 Answer

Make a simple tree 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges