private void Combine(List <MeshCombineMaterial> meshCombineMaterials, GameObject combinedMeshesParent) { List <GameObject> allCombinedMeshObjects = new List <GameObject>(100); if (combinedMeshesParent == null) { combinedMeshesParent = new GameObject(GetNameForCombinedMeshesParent()); UndoEx.RegisterCreatedGameObject(combinedMeshesParent); } for (int combMaterialIndex = 0; combMaterialIndex < meshCombineMaterials.Count; ++combMaterialIndex) { MeshCombineMaterial meshCombMaterial = meshCombineMaterials[combMaterialIndex]; List <GameObject> combineMeshdObjects = Combine(meshCombMaterial, combinedMeshesParent); if (_combineSettings.WeldVertexPositions) { if (_combineSettings.WeldVertexPositionsOnlyForCommonMaterial) { WeldVertexPositionsForMeshObjects(combineMeshdObjects); } else { allCombinedMeshObjects.AddRange(combineMeshdObjects); } } } if (_combineSettings.WeldVertexPositions && !_combineSettings.WeldVertexPositionsOnlyForCommonMaterial) { WeldVertexPositionsForMeshObjects(allCombinedMeshObjects); } if (_combineSettings.CollHandling == MeshCombineSettings.ColliderHandling.Preserve) { PreserveColliders(meshCombineMaterials, combinedMeshesParent); } }
private void PreserveColliders(List <MeshCombineMaterial> meshCombineMaterials, GameObject combinedMeshesParent) { if (meshCombineMaterials.Count == 0 || _combineSettings.CollHandling != MeshCombineSettings.ColliderHandling.Preserve) { return; } GameObject colliderParent = combinedMeshesParent; Transform colliderParentTransform = colliderParent.transform; if (_combineSettings.CollPreserveParent == MeshCombineSettings.ColliderPreserveParent.OneForAll) { colliderParent = new GameObject(_combineSettings.OneForAllColliderParentName); UndoEx.RegisterCreatedGameObject(colliderParent); colliderParentTransform = colliderParent.transform; colliderParentTransform.parent = combinedMeshesParent.transform; } HashSet <GameObject> processedObjects = new HashSet <GameObject>(); Vector3 positionSum = Vector3.zero; for (int cmbMaterialIndex = 0; cmbMaterialIndex < meshCombineMaterials.Count; ++cmbMaterialIndex) { MeshCombineMaterial meshCmbMaterial = meshCombineMaterials[cmbMaterialIndex]; EditorUtility.DisplayProgressBar("Collider Handling", "Preserving colliders...", (float)cmbMaterialIndex / meshCombineMaterials.Count); List <MeshInstance> meshInstances = meshCmbMaterial.MeshInstances; foreach (var meshInstance in meshInstances) { GameObject meshObject = meshInstance.MeshTransform.gameObject; if (processedObjects.Contains(meshObject)) { continue; } processedObjects.Add(meshObject); positionSum += meshObject.transform.position; BoxCollider[] boxColliders = meshObject.GetComponents <BoxCollider>(); foreach (var boxCollider in boxColliders) { string colliderName = _combineSettings.CollPreserveName == MeshCombineSettings.ColliderPreserveName.SameAsSource ? meshObject.name : GetDefaultBoxColliderObjectName(); GameObject colliderObject = boxCollider.CloneAsNewObject(colliderName).gameObject; UndoEx.RegisterCreatedGameObject(colliderObject); colliderObject.transform.parent = colliderParentTransform; } SphereCollider[] sphereColliders = meshObject.GetComponents <SphereCollider>(); foreach (var sphereCollider in sphereColliders) { string colliderName = _combineSettings.CollPreserveName == MeshCombineSettings.ColliderPreserveName.SameAsSource ? meshObject.name : GetDefaultSphereColliderObjectName(); GameObject colliderObject = sphereCollider.CloneAsNewObject(colliderName).gameObject; UndoEx.RegisterCreatedGameObject(colliderObject); colliderObject.transform.parent = colliderParentTransform; } CapsuleCollider[] capsuleColliders = meshObject.GetComponents <CapsuleCollider>(); foreach (var capsuleCollider in capsuleColliders) { string colliderName = _combineSettings.CollPreserveName == MeshCombineSettings.ColliderPreserveName.SameAsSource ? meshObject.name : GetDefaultCapsuleColliderObjectName(); GameObject colliderObject = capsuleCollider.CloneAsNewObject(colliderName).gameObject; UndoEx.RegisterCreatedGameObject(colliderObject); colliderObject.transform.parent = colliderParentTransform; } MeshCollider[] meshColliders = meshObject.GetComponents <MeshCollider>(); foreach (var meshCollider in meshColliders) { string colliderName = _combineSettings.CollPreserveName == MeshCombineSettings.ColliderPreserveName.SameAsSource ? meshObject.name : GetDefaultMeshColliderObjectName(); GameObject colliderObject = meshCollider.CloneAsNewObject(colliderName).gameObject; UndoEx.RegisterCreatedGameObject(colliderObject); colliderObject.transform.parent = colliderParentTransform; } } } if (_combineSettings.CollPreserveParent == MeshCombineSettings.ColliderPreserveParent.OneForAll) { colliderParent.SetWorldPosDontAffectChildren(positionSum *= (1.0f / processedObjects.Count)); } if (colliderParent.transform.childCount == 0) { GameObject.DestroyImmediate(colliderParent); } EditorUtility.ClearProgressBar(); }
private List <GameObject> Combine(MeshCombineMaterial meshCombineMaterial, GameObject combinedMeshesParent) { List <MeshInstance> meshInstances = meshCombineMaterial.MeshInstances; if (meshInstances.Count == 0) { return(new List <GameObject>()); } int maxNumMeshVerts = GetMaxNumberOfMeshVerts(); const int numVertsPerMeshGuess = 500; int totalNumVertsGuess = meshCombineMaterial.MeshInstances.Count * numVertsPerMeshGuess; var combinedMeshData = new CombinedMeshData(totalNumVertsGuess); List <GameObject> combinedMeshObjects = new List <GameObject>(100); for (int meshInstanceIndex = 0; meshInstanceIndex < meshInstances.Count; ++meshInstanceIndex) { MeshInstance meshInstance = meshInstances[meshInstanceIndex]; Mesh mesh = meshInstance.SourceMesh; if (mesh.vertexCount == 0) { continue; } EditorUtility.DisplayProgressBar("Combining Meshes", "Processing material: " + meshCombineMaterial.Material.name, (float)meshInstanceIndex / meshInstances.Count); Matrix4x4 worldMatrix = meshInstance.MeshTransform.localToWorldMatrix; Matrix4x4 worldInverseTranspose = worldMatrix.inverse.transpose; int numNegativeScaleComps = 0; Vector3 worldScale = meshInstance.MeshTransform.lossyScale; if (worldScale[0] < 0.0f) { ++numNegativeScaleComps; } if (worldScale[1] < 0.0f) { ++numNegativeScaleComps; } if (worldScale[2] < 0.0f) { ++numNegativeScaleComps; } bool reverseVertexWindingOrder = (numNegativeScaleComps % 2 != 0); int[] submeshVertIndices = mesh.GetTriangles(meshInstance.SubmeshIndex); if (submeshVertIndices.Length == 0) { continue; } Vector4[] vertTangents = mesh.tangents; Vector3[] vertPositions = mesh.vertices; Vector3[] vertNormals = mesh.normals; Vector2[] vertUV1 = mesh.uv; Vector2[] vertUV2 = mesh.uv2; Vector2[] vertUV3 = mesh.uv3; Vector2[] vertUV4 = mesh.uv4; Color[] vertColors = mesh.colors; foreach (var vertIndex in submeshVertIndices) { if (vertTangents.Length != 0) { Vector3 transformedTangent = new Vector3(vertTangents[vertIndex].x, vertTangents[vertIndex].y, vertTangents[vertIndex].z); transformedTangent = worldInverseTranspose.MultiplyVector(transformedTangent); transformedTangent.Normalize(); combinedMeshData.VertTangents.Add(new Vector4(transformedTangent.x, transformedTangent.y, transformedTangent.z, vertTangents[vertIndex].w)); } if (vertNormals.Length != 0) { Vector3 transformedNormal = worldInverseTranspose.MultiplyVector(vertNormals[vertIndex]); transformedNormal.Normalize(); combinedMeshData.VertNormals.Add(transformedNormal); } if (vertPositions.Length != 0) { combinedMeshData.VertPositions.Add(worldMatrix.MultiplyPoint(vertPositions[vertIndex])); } if (vertColors.Length != 0) { combinedMeshData.VertColors.Add(vertColors[vertIndex]); } if (vertUV1.Length != 0) { combinedMeshData.VertUV1.Add(vertUV1[vertIndex]); } if (vertUV3.Length != 0) { combinedMeshData.VertUV2.Add(vertUV3[vertIndex]); } if (vertUV4.Length != 0) { combinedMeshData.VertUV3.Add(vertUV4[vertIndex]); } if (vertUV2.Length != 0 && !_combineSettings.GenerateLightmapUVs) { combinedMeshData.VertUV2.Add(vertUV2[vertIndex]); } combinedMeshData.AddCurrentVertIndex(); int numIndices = combinedMeshData.VertIndices.Count; if (reverseVertexWindingOrder && numIndices % 3 == 0) { combinedMeshData.ReverseWindingOrderForLastTriangle(); } int numMeshVerts = combinedMeshData.VertPositions.Count; if (combinedMeshData.VertIndices.Count % 3 == 0 && (maxNumMeshVerts - numMeshVerts) < 3) { combinedMeshObjects.Add(CreateCombinedMeshObject(combinedMeshData, meshCombineMaterial.Material, combinedMeshesParent)); combinedMeshData.Reset(); } } } combinedMeshObjects.Add(CreateCombinedMeshObject(combinedMeshData, meshCombineMaterial.Material, combinedMeshesParent)); EditorUtility.ClearProgressBar(); return(combinedMeshObjects); }
private List <MeshCombineMaterial> GetMeshCombineMaterials(List <GameObject> meshObjects, GameObject sourceParent) { var meshCombineMaterialsMap = new Dictionary <Material, MeshCombineMaterial>(); var meshCombineMaterials = new List <MeshCombineMaterial>(); Transform sourceParentTransform = sourceParent != null ? sourceParent.transform : null; foreach (var meshObject in meshObjects) { Transform meshTransform = meshObject.transform; if (_combineSettings.IgnoreObjectsInHierarchies) { if (sourceParentTransform != null) { if (meshTransform.parent != sourceParentTransform || meshTransform.childCount != 0) { continue; } } else { if (meshTransform.parent != null || meshTransform.childCount != 0) { continue; } } } if (!_combineSettings.CombineStaticMeshes && meshTransform.gameObject.isStatic) { continue; } if (!_combineSettings.CombineDynamicMeshes && !meshTransform.gameObject.isStatic) { continue; } MeshFilter meshFilter = meshObject.GetComponent <MeshFilter>(); if (meshFilter == null || meshFilter.sharedMesh == null) { continue; } MeshRenderer meshRenderer = meshObject.GetComponent <MeshRenderer>(); if (meshRenderer == null) { continue; } Mesh sharedMesh = meshFilter.sharedMesh; for (int submeshIndex = 0; submeshIndex < sharedMesh.subMeshCount; ++submeshIndex) { Material subMeshMaterial = meshRenderer.sharedMaterials[submeshIndex]; MeshCombineMaterial meshCombineMaterial = null; if (!meshCombineMaterialsMap.ContainsKey(subMeshMaterial)) { meshCombineMaterial = new MeshCombineMaterial(); meshCombineMaterial.Material = subMeshMaterial; meshCombineMaterialsMap.Add(subMeshMaterial, meshCombineMaterial); meshCombineMaterials.Add(meshCombineMaterial); } else { meshCombineMaterial = meshCombineMaterialsMap[subMeshMaterial]; } var meshInstance = new MeshInstance(); meshInstance.SourceMesh = sharedMesh; meshInstance.SubmeshIndex = submeshIndex; meshInstance.MeshTransform = meshTransform; meshCombineMaterial.MeshInstances.Add(meshInstance); } } return(meshCombineMaterials); }