Advertisement
Guest User

Unity Static Mesh Combiner

a guest
Nov 21st, 2014
15
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.59 KB | None | 0 0
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. using System.Collections;
  4. using UnityEditor;
  5.  
  6. public class MeshCombiner : EditorWindow
  7. {
  8.     struct CellKey
  9.     {
  10.         public CellKey(int x, int y, Material material)
  11.         {
  12.             X = x;
  13.             Y = y;
  14.             Material = material;
  15.         }
  16.         public int X;
  17.         public int Y;
  18.         public Material Material;
  19.     }
  20.  
  21.     private static Dictionary<CellKey, List<GameObject>> grid;
  22.     static HashSet<GameObject> destroyList = new HashSet<GameObject>();
  23.  
  24.     private static void GenerateCombinedMeshObjects(Transform transform)
  25.     {
  26.         foreach (var cell in grid)
  27.         {
  28.             GameObject combinedMeshObject = new GameObject();
  29.             combinedMeshObject.name = "Combined mesh";
  30.            
  31.             var combinedFilter = combinedMeshObject.AddComponent<MeshFilter>();
  32.             var combinedRenderer = combinedMeshObject.AddComponent<MeshRenderer>();
  33.  
  34.             combinedRenderer.sharedMaterial = cell.Key.Material;
  35.  
  36.             combinedFilter.mesh = CombineObjects(cell.Value);
  37.  
  38.             combinedMeshObject.transform.parent = transform;
  39.  
  40.             combinedMeshObject.isStatic = true;
  41.         }
  42.     }
  43.  
  44.     /// <summary>
  45.     /// Combines the meshes in the objects in a single mesh. TODO: Hogs up a bit more memory than it should.
  46.     /// </summary>
  47.     /// <param name="list">The list of objects to combine</param>
  48.     /// <returns>The combined mehs</returns>
  49.     private static Mesh CombineObjects(List<GameObject> list)
  50.     {
  51.         Mesh combinedMesh = new Mesh();
  52.  
  53.         List<Vector3> vertex = new List<Vector3>();
  54.         List<Vector2> uv = new List<Vector2>();
  55.         List<Vector3> normals = new List<Vector3>();
  56.         List<int> indices = new List<int>();
  57.  
  58.         for (int i = 0; i < list.Count; i++)
  59.         {
  60.             var theObject = list[i];
  61.  
  62.             var mf = theObject.GetComponent<MeshFilter>();
  63.             var m = mf.sharedMesh;
  64.  
  65.             if (m == null)
  66.             {
  67.                 m = mf.mesh;
  68.             }
  69.  
  70.             int offset = vertex.Count;
  71.  
  72.             for (int index = 0; index < m.vertices.Length; index++)
  73.             {
  74.                 var vert = m.vertices[index];
  75.  
  76.                 vert = Vector3.Scale(vert, theObject.transform.lossyScale);
  77.                 vert = theObject.transform.rotation * vert;
  78.  
  79.                 vertex.Add(vert + theObject.transform.position);
  80.             }
  81.            
  82.             uv.AddRange(m.uv);
  83.             normals.AddRange(m.normals);
  84.  
  85.             for (int index = 0; index < m.triangles.Length; index++)
  86.             {
  87.                 indices.Add(m.triangles[index] + offset);
  88.             }
  89.  
  90.             destroyList.Add(theObject);
  91.         }
  92.  
  93.         combinedMesh.vertices = vertex.ToArray();
  94.         combinedMesh.uv = uv.ToArray();
  95.         combinedMesh.normals = normals.ToArray();
  96.         combinedMesh.triangles = indices.ToArray();
  97.  
  98.         combinedMesh.RecalculateNormals();
  99.  
  100.         return combinedMesh;
  101.     }
  102.  
  103.     private static void SortChildrenInToGrid(Transform parent, int GridCellSize, bool YIsUp)
  104.     {
  105.         foreach (Transform child in parent)
  106.         {
  107.             if (child.childCount > 0)
  108.             {
  109.                 SortChildrenInToGrid(child, GridCellSize, YIsUp);
  110.                 destroyList.Add(child.gameObject);
  111.             }
  112.  
  113.             if (!child.gameObject.isStatic)
  114.                 continue;
  115.  
  116.             var rend = child.GetComponent<MeshRenderer>();
  117.  
  118.             if (rend == null)
  119.                 continue;
  120.            
  121.             rend.enabled = false;
  122.  
  123.             int x = Mathf.CeilToInt(child.position.x / GridCellSize);
  124.             int y = Mathf.CeilToInt(child.position.z / GridCellSize);
  125.  
  126.             if (!YIsUp)
  127.                 y = Mathf.CeilToInt(child.position.y / GridCellSize);
  128.  
  129.             foreach (var material in rend.sharedMaterials)
  130.             {
  131.                 List<GameObject> cell;
  132.                 var key = new CellKey(x, y, material);
  133.  
  134.                 // Try to get cell, or create one if not found
  135.                 if (!grid.TryGetValue(key, out cell))
  136.                 {
  137.                     cell = new List<GameObject>();
  138.                     grid.Add(key, cell);
  139.                 }
  140.  
  141.                 cell.Add(child.gameObject);
  142.             }
  143.         }
  144.  
  145.     }
  146.  
  147.     [MenuItem("Static Mesh Tools/Static mesh combiner", false, 0)]
  148.     static void GenerateStaticMeshesWindow()
  149.     {
  150.         EditorWindow.GetWindow(typeof(MeshCombiner));
  151.     }
  152.  
  153.     static void DoCombine(int GridCellSize, bool YIsUp)
  154.     {
  155.         foreach (var current in Selection.gameObjects)
  156.         {
  157.             if (!current.isStatic)
  158.                 continue;
  159.  
  160.             var newObject = Instantiate(current);
  161.             current.SetActive(false);
  162.  
  163.             grid = new Dictionary<CellKey, List<GameObject>>();
  164.  
  165.             SortChildrenInToGrid(newObject.transform, GridCellSize, YIsUp);
  166.             GenerateCombinedMeshObjects(newObject.transform);
  167.         }
  168.  
  169.         foreach (var item in destroyList)
  170.         {
  171.             if(item != null)
  172.                 DestroyImmediate(item);
  173.         }
  174.     }
  175.  
  176.     bool yIsUp = true;
  177.     int gridSize = 10;
  178.  
  179.     void OnGUI()
  180.     {
  181.         GUILayout.Label("Mesh Generator Settings", EditorStyles.boldLabel);
  182.         gridSize = Mathf.FloorToInt(EditorGUILayout.Slider("Grid Cell Size", gridSize, 1, 20));
  183.         yIsUp = EditorGUILayout.Toggle("Y is up", yIsUp);
  184.        
  185.         if (GUILayout.Button("Build Objects"))
  186.         {
  187.             DoCombine(gridSize, yIsUp);
  188.         }
  189.  
  190.     }
  191. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement