Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //This script is free to use, but the hexagon combine type doesn't work yet
- //This script will not work without the editor script
- using System.Collections.Generic;
- using UnityEngine;
- public class MeshMerge : MonoBehaviour
- {
- [SerializeField]
- private Material material;
- [SerializeField]
- private CombineType combineType = CombineType.Simple;
- [SerializeField]
- private SubMeshesType subMeshesType = SubMeshesType.MergeSubmeshesTogether;
- [SerializeField]
- [Tooltip("This bool allows you to combine meshes up to 4 billions of vertices instead of the default 65 536 vertices, but it isn't supported on all the platforms")]
- private bool use32BitsBuffer;
- [SerializeField]
- private Mesh mesh;
- [SerializeField]
- private Gradient colors;
- [SerializeField]
- private int range;
- [SerializeField]
- private Vector3 gridOffset;
- [SerializeField]
- private Vector2 gridMaxSize;
- [SerializeField]
- private List<CellData> groupedItems = new List<CellData>();
- [SerializeField]
- private Texture2D atlasTexture;
- [SerializeField]
- private string path;
- [SerializeField]
- private Material newMat;
- public List<GameObject> items = new List<GameObject>();
- public void CombineMeshes()
- {
- Quaternion oldRot = transform.rotation;
- Vector3 oldPos = transform.position;
- Vector3 oldScale = transform.localScale;
- List<MeshFilter> filters = new List<MeshFilter>();
- List<CombineInstance> combiners = new List<CombineInstance>();
- SetGroupedList();
- GroupItems();
- foreach (CellData data in groupedItems)
- {
- uint totalVertexCount = 0;
- Mesh finalMesh;
- if (use32BitsBuffer) finalMesh = new Mesh{ indexFormat = UnityEngine.Rendering.IndexFormat.UInt32 };
- else finalMesh = new Mesh();
- filters.Clear();
- combiners.Clear();
- foreach (GameObject mf in data.cellItems)
- filters.Add(mf.GetComponent<MeshFilter>());
- print(name + " is combining " + filters.Count + " meshes ! ID : " + data.ID);
- for (int a = 0; a < filters.Count; a++)
- {
- totalVertexCount += (uint)filters[a].sharedMesh.vertexCount;
- if (!use32BitsBuffer && totalVertexCount >= 65536)
- {
- Debug.LogError("Can't combine meshes with more than 65 536 vertices ! (" + totalVertexCount + ")", gameObject);
- return;
- }
- if (use32BitsBuffer && totalVertexCount >= 4000000000)
- {
- Debug.LogError("Can't combine meshes with more than 4 000 000 000 vertices ! (" + totalVertexCount + ")", gameObject);
- return;
- }
- if (filters[a].transform == transform)
- continue;
- if (subMeshesType == SubMeshesType.UseOnlyTheFirst)
- {
- CombineInstance subComb = new CombineInstance();
- subComb.subMeshIndex = 0;
- subComb.mesh = filters[a].sharedMesh;
- subComb.transform = filters[a].transform.localToWorldMatrix;
- combiners.Add(subComb);
- }
- else
- {
- for (int b = 0; b < filters[a].sharedMesh.subMeshCount; b++)
- {
- CombineInstance subComb = new CombineInstance();
- subComb.subMeshIndex = b;
- subComb.mesh = filters[a].sharedMesh;
- subComb.transform = filters[a].transform.localToWorldMatrix;
- combiners.Add(subComb);
- }
- }
- }
- finalMesh.CombineMeshes(combiners.ToArray(), subMeshesType == SubMeshesType.MergeSubmeshesTogether || subMeshesType == SubMeshesType.UseOnlyTheFirst ? true : false);
- GameObject truc = new GameObject("Cell_" + data.ID);
- truc.AddComponent<MeshFilter>().sharedMesh = finalMesh;
- truc.AddComponent<MeshRenderer>().material = material;
- truc.transform.position = oldPos;
- truc.transform.rotation = oldRot;
- truc.transform.localScale = oldScale;
- foreach (GameObject item in data.cellItems)
- item.SetActive(false);
- }
- }
- public void Undo()
- {
- for (int a = 0; a < items.Count; a++)
- items[a].SetActive(true);
- }
- void OnDrawGizmosSelected()
- {
- if (combineType != CombineType.Simple && range > 5)
- {
- bool color = false;
- for (int i = 0; i < gridMaxSize.x; i += range)
- {
- for (int o = 0; o < gridMaxSize.y; o += range)
- {
- Gizmos.color = colors.Evaluate((color = !color) ? 0 : 1);
- if (combineType == CombineType.Cube)
- Gizmos.DrawWireCube(Vector3.zero + gridOffset + new Vector3(i, 0, o), new Vector3(range, range / 5, range));
- if (combineType == CombineType.Hex)
- {
- //Even
- if ((o / range) % 2 == 0)
- Gizmos.DrawMesh(mesh, gridOffset + new Vector3(i + gridOffset.z, 0, o * 0.866f + 0.77f), Quaternion.Euler(-90, 0, 0), Vector3.one * range * 0.962f);
- //Odd
- else
- Gizmos.DrawMesh(mesh, gridOffset + new Vector3(i, 0, o * 0.866f + 0.77f), Quaternion.Euler(-90, 0, 0), Vector3.one * range * 0.962f);
- }
- }
- }
- }
- }
- public void CalculatePerfectCellSize()
- {
- SetGroupedList();
- GroupItems();
- uint totalVertexCount = 0;
- foreach (GameObject go in groupedItems[0].cellItems)
- totalVertexCount += (uint)go.GetComponent<MeshFilter>().sharedMesh.vertexCount;
- if (!use32BitsBuffer)
- {
- float bestSize = Mathf.RoundToInt(64000f / totalVertexCount * range) - 1;
- if (totalVertexCount >= 65536)
- Debug.Log("The first cell has more than 65 536 vertices (" + totalVertexCount + "), please lower the size to something like : " + bestSize, gameObject);
- if (totalVertexCount < 65536)
- Debug.Log("The first cell has less than 65 536 vertices (" + totalVertexCount + "), the best size will probably be : " + bestSize, gameObject);
- }
- else
- {
- float bestSize = Mathf.RoundToInt(4000000000f / totalVertexCount * range) - 1;
- if (totalVertexCount >= 4000000000)
- Debug.Log("The first cell has more than 4 000 000 000 vertices (" + totalVertexCount + "), please lower the size to something like : " + bestSize, gameObject);
- if (totalVertexCount < 4000000000)
- Debug.Log("The first cell has less than 4 000 000 000 vertices (" + totalVertexCount + "), the best size will probably be : " + bestSize, gameObject);
- }
- }
- public void SetGroupedList()
- {
- if (combineType != CombineType.Simple)
- {
- groupedItems.Clear();
- int cellsNbr = 0;
- for (int i = 0; i < gridMaxSize.x; i += range)
- {
- for (int o = 0; o < gridMaxSize.y; o += range)
- {
- groupedItems.Add(new CellData(
- cellsNbr,
- new Vector2(i, o)
- ));
- cellsNbr++;
- }
- }
- }
- else
- {
- groupedItems.Clear();
- groupedItems.Add(new CellData(
- 0,
- new Vector2(0, 0)
- ));
- }
- }
- public void GroupItems()
- {
- for (int i = 0; i < groupedItems.Count; i++)
- {
- foreach (GameObject item in items)
- {
- if (combineType == CombineType.Cube && item.transform.position.x <= groupedItems[i].cellOrigin.x + range && item.transform.position.x >= groupedItems[i].cellOrigin.x && item.transform.position.z <= groupedItems[i].cellOrigin.y + range && item.transform.position.z >= groupedItems[i].cellOrigin.y)
- groupedItems[i].cellItems.Add(item);
- else if (combineType == CombineType.Simple)
- groupedItems[i].cellItems.Add(item);
- }
- }
- }
- public void AtlasUVS()
- {
- //if (subMeshesType == SubMeshesType.)
- List<MeshFilter> meshFilters = new List<MeshFilter>();
- for (int a = 0; a < items.Count; a++)
- {
- if (items[a].GetComponent<MeshFilter>())
- meshFilters.Add(items[a].GetComponent<MeshFilter>());
- else
- Debug.LogError("Item " + a + " in the list doesn't have any MeshFilter on it. Remove it or add to it a MeshFilter");
- }
- List<Texture2D> textures = new List<Texture2D>();
- for (int a = 0; a < items.Count; a++)
- {
- if (items[a].GetComponent<MeshRenderer>() && items[a].GetComponent<MeshRenderer>().sharedMaterial)
- textures.Add(DuplicateTextureWithMat(items[a].GetComponent<MeshRenderer>().sharedMaterial));
- else
- Debug.LogError("Item " + a + " in the list doesn't have any MeshRenderer on it. Remove it or add to it a MeshRenderer");
- }
- Rect[] uvRectChangesFromTextureAtlas = atlasTexture.PackTextures(textures.ToArray(), 0, 8192);
- for (var i = 0; i < uvRectChangesFromTextureAtlas.Length; i++)
- {
- Quaternion oldRot = items[i].transform.rotation;
- Vector3 oldPos = items[i].transform.position;
- Vector3 oldScale = items[i].transform.localScale;
- Rect rect = uvRectChangesFromTextureAtlas[i];
- Mesh atlasedMesh = CopyMesh(meshFilters[i].sharedMesh);
- Vector2[] remappedUVs = atlasedMesh.uv;
- for (var j = 0; j < remappedUVs.Length; j++)
- {
- var uv = remappedUVs[j];
- uv.x = rect.x + (uv.x * rect.width);
- uv.y = rect.y + (uv.y * rect.height);
- remappedUVs[j] = uv;
- }
- atlasedMesh.uv = remappedUVs;
- GameObject truc = new GameObject(items[i].name + "_Atlased");
- truc.transform.rotation = oldRot;
- truc.transform.position = oldPos;
- truc.transform.localScale = oldScale;
- items[i].SetActive(false);
- truc.AddComponent<MeshFilter>().sharedMesh = atlasedMesh;
- newMat.mainTexture = atlasTexture;
- truc.AddComponent<MeshRenderer>().material = newMat;
- }
- if (!string.IsNullOrEmpty(path))
- System.IO.File.WriteAllBytes(path + "/" + atlasTexture.name + ".png", atlasTexture.EncodeToPNG());
- }
- private Mesh CopyMesh (Mesh mesh)
- {
- return Instantiate(mesh);
- }
- public Texture2D DuplicateTextureWithMat(Material mat)
- {
- Texture2D source = new Texture2D(1, 1);
- if (mat.mainTexture)
- source = (Texture2D)mat.mainTexture;
- else
- source.SetPixel(0, 0, mat.color);
- RenderTexture renderTex = RenderTexture.GetTemporary(
- source.width,
- source.height,
- 0,
- RenderTextureFormat.Default,
- RenderTextureReadWrite.Linear);
- Graphics.Blit(source, renderTex);
- RenderTexture previous = RenderTexture.active;
- RenderTexture.active = renderTex;
- Texture2D readableText = new Texture2D(source.width, source.height);
- readableText.ReadPixels(new Rect(0, 0, renderTex.width, renderTex.height), 0, 0);
- readableText.Apply();
- RenderTexture.active = previous;
- RenderTexture.ReleaseTemporary(renderTex);
- return readableText;
- }
- public void AtlasAndCombine()
- {
- Quaternion oldRot = transform.rotation;
- Vector3 oldPos = transform.position;
- Vector3 oldScale = transform.localScale;
- List<MeshFilter> filters = new List<MeshFilter>();
- List<CombineInstance> combiners = new List<CombineInstance>();
- int totalVertexCount = 0;
- Mesh finalMesh = new Mesh();
- List<Texture2D> textures = new List<Texture2D>();
- foreach (GameObject mf in items)
- {
- filters.Add(mf.GetComponent<MeshFilter>());
- for (int b = 0; b < mf.GetComponent<MeshFilter>().sharedMesh.subMeshCount; b++)
- textures.Add(DuplicateTextureWithMat(mf.GetComponent<MeshRenderer>().sharedMaterials[b]));
- }
- Rect[] uvRectChangesFromTextureAtlas = atlasTexture.PackTextures(textures.ToArray(), 0, 8192);
- print(name + " is combining " + filters.Count + " meshes !");
- for (int a = 0; a < filters.Count; a++)
- {
- totalVertexCount += filters[a].sharedMesh.vertexCount;
- if (totalVertexCount >= 65536)
- {
- Debug.LogError("Can't combine meshes with more than 65 536 vertices ! (" + totalVertexCount + ")", gameObject);
- return;
- }
- if (filters[a].transform == transform)
- continue;
- for (int b = 0; b < filters[a].sharedMesh.subMeshCount; b++)
- {
- Rect rect = uvRectChangesFromTextureAtlas[a + b];
- Vector2[] remappedUVs = CopyMesh(filters[a].sharedMesh).uv;
- HashSet<int> tris = new HashSet<int>(filters[a].sharedMesh.GetTriangles(b));
- for (var j = 0; j < remappedUVs.Length; j++)
- {
- var uv = remappedUVs[j];
- uv.x = rect.x + (uv.x * rect.width);
- uv.y = rect.y + (uv.y * rect.height);
- remappedUVs[j] = uv;
- }
- CombineInstance subComb = new CombineInstance();
- subComb.subMeshIndex = b;
- subComb.mesh = CopyMesh(filters[a].sharedMesh);
- subComb.mesh.uv = remappedUVs;
- subComb.transform = filters[a].transform.localToWorldMatrix;
- combiners.Add(subComb);
- }
- }
- finalMesh.CombineMeshes(combiners.ToArray());
- GameObject truc = new GameObject("Cell_Atlased");
- truc.AddComponent<MeshFilter>().sharedMesh = finalMesh;
- newMat.mainTexture = atlasTexture;
- truc.AddComponent<MeshRenderer>().material = newMat;
- truc.transform.position = oldPos;
- truc.transform.rotation = oldRot;
- truc.transform.localScale = oldScale;
- if (!string.IsNullOrEmpty(path))
- System.IO.File.WriteAllBytes(path + "/" + atlasTexture.name + ".png", atlasTexture.EncodeToPNG());
- foreach (GameObject item in items)
- item.SetActive(false);
- }
- }
- public enum CombineType
- {
- Cube = 0,
- Hex = 1,
- Simple = 2
- }
- public enum SubMeshesType
- {
- MergeSubmeshesTogether = 0,
- DontMergeThemTogether = 1,
- UseOnlyTheFirst = 2
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement