Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System.Collections.Generic;
- using UnityEngine;
- using System.Collections;
- using UnityEditor;
- public class MeshCombiner : EditorWindow
- {
- struct CellKey
- {
- public CellKey(int x, int y, Material material)
- {
- X = x;
- Y = y;
- Material = material;
- }
- public int X;
- public int Y;
- public Material Material;
- }
- private static Dictionary<CellKey, List<GameObject>> grid;
- static HashSet<GameObject> destroyList = new HashSet<GameObject>();
- private static void GenerateCombinedMeshObjects(Transform transform)
- {
- foreach (var cell in grid)
- {
- GameObject combinedMeshObject = new GameObject();
- combinedMeshObject.name = "Combined mesh";
- var combinedFilter = combinedMeshObject.AddComponent<MeshFilter>();
- var combinedRenderer = combinedMeshObject.AddComponent<MeshRenderer>();
- combinedRenderer.sharedMaterial = cell.Key.Material;
- combinedFilter.mesh = CombineObjects(cell.Value);
- combinedMeshObject.transform.parent = transform;
- combinedMeshObject.isStatic = true;
- }
- }
- /// <summary>
- /// Combines the meshes in the objects in a single mesh. TODO: Hogs up a bit more memory than it should.
- /// </summary>
- /// <param name="list">The list of objects to combine</param>
- /// <returns>The combined mehs</returns>
- private static Mesh CombineObjects(List<GameObject> list)
- {
- Mesh combinedMesh = new Mesh();
- List<Vector3> vertex = new List<Vector3>();
- List<Vector2> uv = new List<Vector2>();
- List<Vector3> normals = new List<Vector3>();
- List<int> indices = new List<int>();
- for (int i = 0; i < list.Count; i++)
- {
- var theObject = list[i];
- var mf = theObject.GetComponent<MeshFilter>();
- var m = mf.sharedMesh;
- if (m == null)
- {
- m = mf.mesh;
- }
- int offset = vertex.Count;
- for (int index = 0; index < m.vertices.Length; index++)
- {
- var vert = m.vertices[index];
- vert = Vector3.Scale(vert, theObject.transform.lossyScale);
- vert = theObject.transform.rotation * vert;
- vertex.Add(vert + theObject.transform.position);
- }
- uv.AddRange(m.uv);
- normals.AddRange(m.normals);
- for (int index = 0; index < m.triangles.Length; index++)
- {
- indices.Add(m.triangles[index] + offset);
- }
- destroyList.Add(theObject);
- }
- combinedMesh.vertices = vertex.ToArray();
- combinedMesh.uv = uv.ToArray();
- combinedMesh.normals = normals.ToArray();
- combinedMesh.triangles = indices.ToArray();
- combinedMesh.RecalculateNormals();
- return combinedMesh;
- }
- private static void SortChildrenInToGrid(Transform parent, int GridCellSize, bool YIsUp)
- {
- foreach (Transform child in parent)
- {
- if (child.childCount > 0)
- {
- SortChildrenInToGrid(child, GridCellSize, YIsUp);
- destroyList.Add(child.gameObject);
- }
- if (!child.gameObject.isStatic)
- continue;
- var rend = child.GetComponent<MeshRenderer>();
- if (rend == null)
- continue;
- rend.enabled = false;
- int x = Mathf.CeilToInt(child.position.x / GridCellSize);
- int y = Mathf.CeilToInt(child.position.z / GridCellSize);
- if (!YIsUp)
- y = Mathf.CeilToInt(child.position.y / GridCellSize);
- foreach (var material in rend.sharedMaterials)
- {
- List<GameObject> cell;
- var key = new CellKey(x, y, material);
- // Try to get cell, or create one if not found
- if (!grid.TryGetValue(key, out cell))
- {
- cell = new List<GameObject>();
- grid.Add(key, cell);
- }
- cell.Add(child.gameObject);
- }
- }
- }
- [MenuItem("Static Mesh Tools/Static mesh combiner", false, 0)]
- static void GenerateStaticMeshesWindow()
- {
- EditorWindow.GetWindow(typeof(MeshCombiner));
- }
- static void DoCombine(int GridCellSize, bool YIsUp)
- {
- foreach (var current in Selection.gameObjects)
- {
- if (!current.isStatic)
- continue;
- var newObject = Instantiate(current);
- current.SetActive(false);
- grid = new Dictionary<CellKey, List<GameObject>>();
- SortChildrenInToGrid(newObject.transform, GridCellSize, YIsUp);
- GenerateCombinedMeshObjects(newObject.transform);
- }
- foreach (var item in destroyList)
- {
- if(item != null)
- DestroyImmediate(item);
- }
- }
- bool yIsUp = true;
- int gridSize = 10;
- void OnGUI()
- {
- GUILayout.Label("Mesh Generator Settings", EditorStyles.boldLabel);
- gridSize = Mathf.FloorToInt(EditorGUILayout.Slider("Grid Cell Size", gridSize, 1, 20));
- yIsUp = EditorGUILayout.Toggle("Y is up", yIsUp);
- if (GUILayout.Button("Build Objects"))
- {
- DoCombine(gridSize, yIsUp);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement