Конвертер Terrain-а в меш

Лучший способ помочь другим, поделиться своими находками.

Конвертер Terrain-а в меш

Сообщение Syberex 09 дек 2012, 18:28

Написал для своего проекта скритпик конвертации террейна в меш, думается для мобильников так будет лучше. Террейн можно дорабатывать и быстро (одним нажатием в меню Tettain - Create Mesh from Terrain) создать меш террейна заного. Для меш-террейна планируется использовать шейдер отсюда. Также можно загнать его в 3D программу через ObjExporter для редактирования/оптимизации/текстурирования или сборки сцены :)

Синтаксис:
Используется csharp
using UnityEngine;
using UnityEditor;


public class TerrainMeshCreator : EditorWindow
{
        /// <summary>
        /// 0 - all, 1 - warning, 2 - error/critical
        /// </summary>
        private int  _logLevel = 0;
       
        private Vector3[] newVertices;
        private Vector2[] newUV;
        private int[] newTriangles;
       
        private int resolution = 128;


        [MenuItem("Terrain/Create Mesh from Terrain")]
        static void Init()
        {
                TerrainMeshCreator window = (TerrainMeshCreator) EditorWindow.GetWindow(typeof(TerrainMeshCreator));
                window.Show();
        }
       
       
        void CreateMesh()
        {
                if (Selection.activeGameObject)
                {
                        Terrain terrain = Selection.activeGameObject.GetComponent<Terrain>();
                       
                        if (terrain)
                        {
                                int l = (int) resolution;               // длина в точках
                                int w = (int) resolution;               // ширина в точках
                                // Длинна, ширина террейна
                                float width  = terrain.terrainData.heightmapWidth * terrain.terrainData.heightmapScale.x;
                                float length = terrain.terrainData.heightmapWidth * terrain.terrainData.heightmapScale.z;
                                float height = 0f;
                                LogMessage("Terrain width = "+width+", length = "+length, 0);
                                Vector3 terrainPos = terrain.transform.position;
                               
                                newVertices = new Vector3[l*w];
                                newTriangles = new int[l*w*2*3];        // 2 - два треугольника в каждой ячейке, 3 - три точки для каждого треугольника
                                int tri = 0;    // счетчик для массива треугольников
                               
                                newUV = new Vector2[l*w];
                                float uvStepL = 1f / (l-1);
                                float uvStepW = 1f / (w-1);
                               
                                for (int i = 0; i < l; i++)     // цикл в длину
                                {
                                        for (int j = 0; j < w; j++)     // цикл в ширину
                                        {
                                                // Получаем высоту в точке
                                                height = terrain.SampleHeight(new Vector3(terrainPos.x + width/(w-1)*j, 0f, terrainPos.z + length/(l-1)*i));
                                                // Создаем вершины меша
                                                newVertices[i*w+j] = new Vector3(width/(w-1)*j, height, length/(l-1)*i);
                                                // Задаем текстурные координаты точек
                                               
                                                newUV[i*w+j] = new Vector2(uvStepL*i, uvStepW*j);
                                               
                                                // С каждой следующей точкой задаем 2 треугольника
                                                // 1   2
                                                // +---+
                                                // |  /|
                                                // | / |
                                                // |/  |
                                                // +---+(i,j)
                                                // 3   4
                                                if (i > 0 && j > 0)     // кроме крайних начальных точек
                                                {
                                                        newTriangles[tri+0] = i*w     + j-1;    // 3
                                                        newTriangles[tri+1] = (i-1)*w + j;              // 2
                                                        newTriangles[tri+2] = (i-1)*w + j-1;    // 1
                                                       
                                                        tri += 3;
                                                        newTriangles[tri+0] = i*w     + j;              // 4
                                                        newTriangles[tri+1] = (i-1)*w + j;              // 2
                                                        newTriangles[tri+2] = i*w     + j-1;    // 3
                                                        tri += 3;
                                                }
                                        }
                                }
                               
                                // Создаем меш
                                Mesh mesh = new Mesh();
                                mesh.vertices = newVertices;
                                mesh.triangles = newTriangles;
                                mesh.uv = newUV;
                                mesh.RecalculateNormals();
                               
//                              // Инвертируем нормали
//                              //Vector3[] newNormals = new Vector3[mesh.normals.Length];
//                              int n = 0;
//                              for (n = 0; n < mesh.normals.Length; n++)
//                                      //newNormals[n]
//                                      mesh.normals [n] = new Vector3(mesh.normals[n].x, mesh.normals[n].y * -1, mesh.normals[n].z);
//                              //mesh.normals = newNormals;
//                              LogMessage("calc normals: "+n, 0);
//                             
//                              //mesh.RecalculateNormals();
                               
                                mesh.RecalculateBounds();
                                mesh.Optimize();
                               
                                // Создаем го и присоединяем меш
                                GameObject goMesh = new GameObject ();
                                goMesh.name = "New Terrain Mesh";
                                MeshFilter meshFilter = goMesh.AddComponent<MeshFilter>();
                                meshFilter.mesh = mesh;
                                goMesh.AddComponent<MeshRenderer>();
                               
                                LogMessage("New Terrain Mesh is created!", 0);
                        }
                        else
                                LogMessage ("This GameObject is not Terrain", 1);
                }
                else
                        LogMessage("Terrain is not selected", 1);              
        }
       

        void OnGUI()
        {
                GUILayout.Label("Resolution (2-254):");
                resolution = int.Parse(GUILayout.TextField(resolution.ToString()));
                if (GUILayout.Button("Create Mesh"))
                        CreateMesh();
        }
       
       
        /// <summary>
        /// Write to log file (0 - all, 1 - warning, 2 - error/critical)
        /// </summary>
        void LogMessage(string msg, int important)
        {
                if (_logLevel == 0)                                             // all messages
                        Debug.Log (msg);
                else if (_logLevel == 1 && important >= 1)      // warning messages
                        Debug.LogWarning (msg);
                else if (_logLevel >= 2 && important >= 2)      // error/critical messages
                        Debug.LogError (msg);
        }
}
 


ЗЫ: Всем еще раз спасибо за помощь в теме Инвертировать нормали!
У вас нет доступа для просмотра вложений в этом сообщении.
Аватара пользователя
Syberex
Адепт
 
Сообщения: 2292
Зарегистрирован: 14 янв 2011, 20:35
Откуда: Кострома
  • Сайт

Re: Конвертер Terrain-а в меш

Сообщение seaman 09 дек 2012, 19:29

Велосипед?
TerrainObjExporter
seaman
Адепт
 
Сообщения: 8352
Зарегистрирован: 24 янв 2011, 12:32
Откуда: Самара

Re: Конвертер Terrain-а в меш

Сообщение Syberex 09 дек 2012, 20:07

Ну я бы так не сказал, ведь у меня сразу делается go, его сразу видно и можно работать, а там в файл пишется - там более актуально для экспорта в 3D программы. У меня для продолжения работы в Юнити - для этого и задумывалось :)

Щас выяснил, что альфа карта не одинаково закрашивает меш-террейн с шейдером по ссылке выше. Придется всеже и альфа карту конвертировать :-?
Аватара пользователя
Syberex
Адепт
 
Сообщения: 2292
Зарегистрирован: 14 янв 2011, 20:35
Откуда: Кострома
  • Сайт

Re: Конвертер Terrain-а в меш

Сообщение Syberex 23 дек 2012, 18:58

Еще выяснилось, что на полученном меш-террейне не работает меш коллайдер в силу того, что нет объекта меша, который бы можно было подключить к коллайдеру ... как бы его так сохранить :-? ?
Аватара пользователя
Syberex
Адепт
 
Сообщения: 2292
Зарегистрирован: 14 янв 2011, 20:35
Откуда: Кострома
  • Сайт

Re: Конвертер Terrain-а в меш

Сообщение BornFoRdeatH 23 дек 2012, 19:29

Не знаю на сколько это актуально, как мне кажется в четвертой юнити провели оптимизацию, сейчас вот у меня на сцене терейн 500*500 с четырьмя текстурами на андроиде выдает 60 фпс, с 20 юнитами активно движущимися, стреляющими фпс проседает до 50, все это тестится на бюджетном sony ericsson st25i.

Но желаю успехов в развитии.
Не бойся, если ты один, бойся, если ты ноль.
BornFoRdeatH
Адепт
 
Сообщения: 2377
Зарегистрирован: 22 окт 2011, 23:41
Откуда: Украина
Skype: bornfordeath

Re: Конвертер Terrain-а в меш

Сообщение Syberex 23 дек 2012, 23:01

BornFoRdeatH писал(а):Не знаю на сколько это актуально, как мне кажется в четвертой юнити провели оптимизацию, сейчас вот у меня на сцене терейн 500*500 с четырьмя текстурами на андроиде выдает 60 фпс, с 20 юнитами активно движущимися, стреляющими фпс проседает до 50, все это тестится на бюджетном sony ericsson st25i.

Но желаю успехов в развитии.

Странно, я тоже тестил на андроиде террайн - он жрет от 10 до 100 дравколов, что не есть гуд :(
Аватара пользователя
Syberex
Адепт
 
Сообщения: 2292
Зарегистрирован: 14 янв 2011, 20:35
Откуда: Кострома
  • Сайт

Re: Конвертер Terrain-а в меш

Сообщение maxik 27 сен 2013, 15:51

спасибо за скрипт
и меш устанавливается :D
maxik
UNец
 
Сообщения: 25
Зарегистрирован: 26 сен 2013, 18:52


Вернуться в Исходники (Копилка)

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 5