private static void MakeBatch(List <MeshSubsetCombineUtility.MeshInstance> meshes, List <MeshSubsetCombineUtility.SubMeshInstance> subsets, List <GameObject> subsetGOs, Transform staticBatchRootTransform, int batchIndex) { if (meshes.Count < 2) { return; } MeshSubsetCombineUtility.MeshInstance[] meshes2 = meshes.ToArray(); MeshSubsetCombineUtility.SubMeshInstance[] array = subsets.ToArray(); string text = "Combined Mesh"; text = text + " (root: " + ((!(staticBatchRootTransform != null)) ? "scene" : staticBatchRootTransform.name) + ")"; if (batchIndex > 0) { text = text + " " + (batchIndex + 1); } Mesh mesh = StaticBatchingUtility.InternalCombineVertices(meshes2, text); StaticBatchingUtility.InternalCombineIndices(array, mesh); int num = 0; for (int i = 0; i < array.Length; i++) { MeshSubsetCombineUtility.SubMeshInstance subMeshInstance = array[i]; GameObject gameObject = subsetGOs[i]; Mesh sharedMesh = mesh; MeshFilter meshFilter = (MeshFilter)gameObject.GetComponent(typeof(MeshFilter)); meshFilter.sharedMesh = sharedMesh; Renderer component = gameObject.GetComponent <Renderer>(); component.SetSubsetIndex(subMeshInstance.subMeshIndex, num); component.staticBatchRootTransform = staticBatchRootTransform; component.enabled = false; component.enabled = true; MeshRenderer meshRenderer = component as MeshRenderer; if (meshRenderer != null) { meshRenderer.additionalVertexStreams = null; } num++; } }
private static void MakeBatch(List <MeshSubsetCombineUtility.MeshInstance> meshes, List <MeshSubsetCombineUtility.SubMeshInstance> subsets, List <GameObject> subsetGOs, Transform staticBatchRootTransform, int batchIndex) { if (meshes.Count < 2) { return; } MeshSubsetCombineUtility.MeshInstance[] array1 = meshes.ToArray(); MeshSubsetCombineUtility.SubMeshInstance[] array2 = subsets.ToArray(); string meshName = "Combined Mesh" + " (root: " + (!((Object)staticBatchRootTransform != (Object)null) ? "scene" : staticBatchRootTransform.name) + ")"; if (batchIndex > 0) { meshName = meshName + " " + (object)(batchIndex + 1); } Mesh combinedMesh = StaticBatchingUtility.InternalCombineVertices(array1, meshName); StaticBatchingUtility.InternalCombineIndices(array2, combinedMesh); int subSetIndexForMaterial = 0; for (int index = 0; index < array2.Length; ++index) { MeshSubsetCombineUtility.SubMeshInstance subMeshInstance = array2[index]; GameObject subsetGo = subsetGOs[index]; Mesh mesh = combinedMesh; ((MeshFilter)subsetGo.GetComponent(typeof(MeshFilter))).sharedMesh = mesh; Renderer component = subsetGo.GetComponent <Renderer>(); component.SetSubsetIndex(subMeshInstance.subMeshIndex, subSetIndexForMaterial); component.staticBatchRootTransform = staticBatchRootTransform; component.enabled = false; component.enabled = true; MeshRenderer meshRenderer = component as MeshRenderer; if ((Object)meshRenderer != (Object)null) { meshRenderer.additionalVertexStreams = (Mesh)null; } ++subSetIndexForMaterial; } }
public static void CombineGameObjects(GameObject[] gos, GameObject staticBatchRoot, bool isEditorPostprocessScene) { Matrix4x4 lhs = Matrix4x4.identity; Transform staticBatchRootTransform = null; if (staticBatchRoot) { lhs = staticBatchRoot.transform.worldToLocalMatrix; staticBatchRootTransform = staticBatchRoot.transform; } int batchIndex = 0; int num = 0; List <MeshSubsetCombineUtility.MeshContainer> list = new List <MeshSubsetCombineUtility.MeshContainer>(); Array.Sort(gos, new InternalStaticBatchingUtility.SortGO()); foreach (GameObject gameObject in gos) { MeshFilter meshFilter = gameObject.GetComponent(typeof(MeshFilter)) as MeshFilter; if (!(meshFilter == null)) { Mesh sharedMesh = meshFilter.sharedMesh; if (!(sharedMesh == null) && (isEditorPostprocessScene || sharedMesh.canAccess)) { Renderer component = meshFilter.GetComponent <Renderer>(); if (!(component == null) && component.enabled) { if (component.staticBatchIndex == 0) { Material[] array = component.sharedMaterials; if (!array.Any((Material m) => m != null && m.shader != null && m.shader.disableBatching != DisableBatchingType.False)) { int vertexCount = sharedMesh.vertexCount; if (vertexCount != 0) { MeshRenderer meshRenderer = component as MeshRenderer; if (meshRenderer != null && meshRenderer.additionalVertexStreams != null) { if (vertexCount != meshRenderer.additionalVertexStreams.vertexCount) { goto IL_387; } } if (num + vertexCount > 64000) { InternalStaticBatchingUtility.MakeBatch(list, staticBatchRootTransform, batchIndex++); list.Clear(); num = 0; } MeshSubsetCombineUtility.MeshInstance instance = default(MeshSubsetCombineUtility.MeshInstance); instance.meshInstanceID = sharedMesh.GetInstanceID(); instance.rendererInstanceID = component.GetInstanceID(); if (meshRenderer != null && meshRenderer.additionalVertexStreams != null) { instance.additionalVertexStreamsMeshInstanceID = meshRenderer.additionalVertexStreams.GetInstanceID(); } instance.transform = lhs * meshFilter.transform.localToWorldMatrix; instance.lightmapScaleOffset = component.lightmapScaleOffset; instance.realtimeLightmapScaleOffset = component.realtimeLightmapScaleOffset; MeshSubsetCombineUtility.MeshContainer item = new MeshSubsetCombineUtility.MeshContainer { gameObject = gameObject, instance = instance, subMeshInstances = new List <MeshSubsetCombineUtility.SubMeshInstance>() }; list.Add(item); if (array.Length > sharedMesh.subMeshCount) { Debug.LogWarning(string.Concat(new object[] { "Mesh '", sharedMesh.name, "' has more materials (", array.Length, ") than subsets (", sharedMesh.subMeshCount, ")" }), component); Material[] array2 = new Material[sharedMesh.subMeshCount]; for (int j = 0; j < sharedMesh.subMeshCount; j++) { array2[j] = component.sharedMaterials[j]; } component.sharedMaterials = array2; array = array2; } for (int k = 0; k < Math.Min(array.Length, sharedMesh.subMeshCount); k++) { MeshSubsetCombineUtility.SubMeshInstance item2 = default(MeshSubsetCombineUtility.SubMeshInstance); item2.meshInstanceID = meshFilter.sharedMesh.GetInstanceID(); item2.vertexOffset = num; item2.subMeshIndex = k; item2.gameObjectInstanceID = gameObject.GetInstanceID(); item2.transform = instance.transform; item.subMeshInstances.Add(item2); } num += sharedMesh.vertexCount; } } } } } } IL_387 :; } InternalStaticBatchingUtility.MakeBatch(list, staticBatchRootTransform, batchIndex); }
static public void CombineGameObjects(GameObject[] gos, UnityEngine.GameObject staticBatchRoot, bool isEditorPostprocessScene) { Matrix4x4 staticBatchInverseMatrix = Matrix4x4.identity; Transform staticBatchRootTransform = null; if (staticBatchRoot) { staticBatchInverseMatrix = staticBatchRoot.transform.worldToLocalMatrix; staticBatchRootTransform = staticBatchRoot.transform; } int batchIndex = 0; int verticesInBatch = 0; List <MeshSubsetCombineUtility.MeshContainer> meshes = new List <MeshSubsetCombineUtility.MeshContainer>(); Array.Sort(gos, new SortGO()); foreach (GameObject go in gos) { MeshFilter filter = go.GetComponent(typeof(MeshFilter)) as MeshFilter; if (filter == null) { continue; } Mesh instanceMesh = filter.sharedMesh; // reject if has no mesh or (mesh not readable and not called from Editor PostprocessScene.cs) // Editor is allowed to modify meshes even if they are marked as read-only e.g. Applicatiopn.LoadLevel() called from a script inside the editor player if (instanceMesh == null || (!isEditorPostprocessScene && !instanceMesh.canAccess)) { continue; } Renderer renderer = filter.GetComponent <Renderer>(); // reject if has not renderer or renderer is disabled if (renderer == null || !renderer.enabled) { continue; } // reject if already combined for static batching if (renderer.staticBatchIndex != 0) { continue; } Material[] materials = renderer.sharedMaterials; // reject if any of the material's shader is using DisableBatching tag if (materials.Any(m => m != null && m.shader != null && m.shader.disableBatching != DisableBatchingType.False)) { continue; } int vertexCount = instanceMesh.vertexCount; // Use same tests as MeshCombiner::IsMeshBatchable to stay consistent with C++ code if (vertexCount == 0) { continue; } MeshRenderer meshRenderer = renderer as MeshRenderer; if ((meshRenderer != null) && (meshRenderer.additionalVertexStreams != null)) { if (vertexCount != meshRenderer.additionalVertexStreams.vertexCount) { continue; } } // check if we have enough space inside the current batch if (verticesInBatch + vertexCount > MaxVerticesInBatch) { MakeBatch(meshes, staticBatchRootTransform, batchIndex++); meshes.Clear(); verticesInBatch = 0; } MeshSubsetCombineUtility.MeshInstance instance = new MeshSubsetCombineUtility.MeshInstance(); instance.meshInstanceID = instanceMesh.GetInstanceID(); instance.rendererInstanceID = renderer.GetInstanceID(); if (meshRenderer != null && meshRenderer.additionalVertexStreams != null) { instance.additionalVertexStreamsMeshInstanceID = meshRenderer.additionalVertexStreams.GetInstanceID(); } instance.transform = staticBatchInverseMatrix * filter.transform.localToWorldMatrix; instance.lightmapScaleOffset = renderer.lightmapScaleOffset; instance.realtimeLightmapScaleOffset = renderer.realtimeLightmapScaleOffset; MeshSubsetCombineUtility.MeshContainer mesh = new MeshSubsetCombineUtility.MeshContainer(); mesh.gameObject = go; mesh.instance = instance; mesh.subMeshInstances = new List <MeshSubsetCombineUtility.SubMeshInstance>(); //;;Debug.Log("New static mesh (" + go.name + ")verts: " + instanceMesh.vertexCount + // ", tris: " + instanceMesh.triangles.Length + // ", materials: " + renderer.sharedMaterials.Length + // ", subs: " + instanceMesh.subMeshCount // ); meshes.Add(mesh); if (materials.Length > instanceMesh.subMeshCount) { Debug.LogWarning("Mesh '" + instanceMesh.name + "' has more materials (" + materials.Length + ") than subsets (" + instanceMesh.subMeshCount + ")", renderer); // extra materials don't have a meaning and it screws the rendering as Unity // tries to render with those extra materials. Material[] newMats = new Material[instanceMesh.subMeshCount]; for (int i = 0; i < instanceMesh.subMeshCount; ++i) { newMats[i] = renderer.sharedMaterials[i]; } renderer.sharedMaterials = newMats; materials = newMats; } for (int m = 0; m < System.Math.Min(materials.Length, instanceMesh.subMeshCount); ++m) { //;;Debug.Log(" new subset : " + m + ", tris " + instanceMesh.GetTriangles(m).Length); MeshSubsetCombineUtility.SubMeshInstance subMeshInstance = new MeshSubsetCombineUtility.SubMeshInstance(); subMeshInstance.meshInstanceID = filter.sharedMesh.GetInstanceID(); subMeshInstance.vertexOffset = verticesInBatch; subMeshInstance.subMeshIndex = m; subMeshInstance.gameObjectInstanceID = go.GetInstanceID(); subMeshInstance.transform = instance.transform; mesh.subMeshInstances.Add(subMeshInstance); } verticesInBatch += instanceMesh.vertexCount; } MakeBatch(meshes, staticBatchRootTransform, batchIndex); }
public static void CombineGameObjects(GameObject[] gos, GameObject staticBatchRoot, bool isEditorPostprocessScene) { Matrix4x4 lhs = Matrix4x4.identity; Transform staticBatchRootTransform = null; if ((bool)staticBatchRoot) { lhs = staticBatchRoot.transform.worldToLocalMatrix; staticBatchRootTransform = staticBatchRoot.transform; } int num = 0; int num2 = 0; List <MeshSubsetCombineUtility.MeshInstance> list = new List <MeshSubsetCombineUtility.MeshInstance>(); List <MeshSubsetCombineUtility.SubMeshInstance> list2 = new List <MeshSubsetCombineUtility.SubMeshInstance>(); List <GameObject> list3 = new List <GameObject>(); Array.Sort(gos, new SortGO()); foreach (GameObject gameObject in gos) { MeshFilter meshFilter = gameObject.GetComponent(typeof(MeshFilter)) as MeshFilter; if (meshFilter == null) { continue; } Mesh sharedMesh = meshFilter.sharedMesh; if (sharedMesh == null || (!isEditorPostprocessScene && !sharedMesh.canAccess)) { continue; } Renderer component = meshFilter.GetComponent <Renderer>(); if (component == null || !component.enabled || component.staticBatchIndex != 0) { continue; } Material[] array = meshFilter.GetComponent <Renderer>().sharedMaterials; if (array.Any((Material m) => m != null && m.shader != null && m.shader.disableBatching != DisableBatchingType.False)) { continue; } if (num2 + meshFilter.sharedMesh.vertexCount > 64000) { MakeBatch(list, list2, list3, staticBatchRootTransform, num++); list.Clear(); list2.Clear(); list3.Clear(); num2 = 0; } MeshSubsetCombineUtility.MeshInstance item = default(MeshSubsetCombineUtility.MeshInstance); item.meshInstanceID = sharedMesh.GetInstanceID(); item.rendererInstanceID = component.GetInstanceID(); MeshRenderer meshRenderer = component as MeshRenderer; if (meshRenderer != null && meshRenderer.additionalVertexStreams != null) { item.additionalVertexStreamsMeshInstanceID = meshRenderer.additionalVertexStreams.GetInstanceID(); } item.transform = lhs * meshFilter.transform.localToWorldMatrix; item.lightmapScaleOffset = component.lightmapScaleOffset; item.realtimeLightmapScaleOffset = component.realtimeLightmapScaleOffset; list.Add(item); if (array.Length > sharedMesh.subMeshCount) { Debug.LogWarning("Mesh has more materials (" + array.Length + ") than subsets (" + sharedMesh.subMeshCount + ")", meshFilter.GetComponent <Renderer>()); Material[] array2 = new Material[sharedMesh.subMeshCount]; for (int j = 0; j < sharedMesh.subMeshCount; j++) { array2[j] = meshFilter.GetComponent <Renderer>().sharedMaterials[j]; } meshFilter.GetComponent <Renderer>().sharedMaterials = array2; array = array2; } for (int k = 0; k < Math.Min(array.Length, sharedMesh.subMeshCount); k++) { MeshSubsetCombineUtility.SubMeshInstance item2 = default(MeshSubsetCombineUtility.SubMeshInstance); item2.meshInstanceID = meshFilter.sharedMesh.GetInstanceID(); item2.vertexOffset = num2; item2.subMeshIndex = k; item2.gameObjectInstanceID = gameObject.GetInstanceID(); item2.transform = item.transform; list2.Add(item2); list3.Add(gameObject); } num2 += sharedMesh.vertexCount; } MakeBatch(list, list2, list3, staticBatchRootTransform, num); }