/// <summary> /// Add a new CombinedMesh /// </summary> /// <param name="combinedMesh"></param> /// <param name="combineInstanceID"></param> /// <param name="combinedIndex"></param> public void AddCombinedMesh(Mesh combinedMesh, CombineInstanceID combineInstanceID, int combinedIndex) { MeshCombined meshResult = new MeshCombined(); int vertexIndex = 0; int triangleIndex = 0; for (int i = 0; i < combineInstanceID._combineInstances.Count; i++) { if (!meshResult.instanceIds.Contains(combineInstanceID._instancesID[i])) { vertexIndex += combineInstanceID._combineInstances[i].mesh.vertexCount; triangleIndex += combineInstanceID._combineInstances[i].mesh.triangles.Length; meshResult.names.Add(combineInstanceID._names[i]); meshResult.instanceIds.Add(combineInstanceID._instancesID[i]); meshResult.indexes.Add(new CombineInstanceIndexes(combineInstanceID._combineInstances[i].mesh, vertexIndex, triangleIndex)); } } _meshResults.Add(meshResult); }
/// <summary> /// Create a new GameObject based on the CombineInstance list /// </summary> /// <param name="instances"></param> /// <param name="parent"></param> /// <param name="number"></param> /// <returns></returns> private GameObject CreateCombinedSkinnedMeshGameObject(CombineInstanceID instances, Transform parent, int number, int combinedIndex) { GameObject combined = new GameObject(_sessionName + number.ToString()); SkinnedMeshRenderer skinnedMeshRenderer = combined.AddComponent <SkinnedMeshRenderer>(); skinnedMeshRenderer.sharedMaterial = _combinedResult._combinedMaterials[combinedIndex].material; skinnedMeshRenderer.sharedMesh = new Mesh(); skinnedMeshRenderer.sharedMesh.name = _sessionName + "_" + _combinedResult._combinedMaterials[combinedIndex].displayedIndex + "_mesh" + number; skinnedMeshRenderer.sharedMesh.CombineMeshes(instances._combineInstances.ToArray(), true, true); #if UNITY_5_3_OR_NEWER // Add blendShapes to new skinnedMesh renderer if needed foreach (BlendShapeFrame blendShape in blendShapes.Values) { Vector3[] detlaVertices = new Vector3[skinnedMeshRenderer.sharedMesh.vertexCount]; Vector3[] detlaNormals = new Vector3[skinnedMeshRenderer.sharedMesh.vertexCount]; Vector3[] detlaTangents = new Vector3[skinnedMeshRenderer.sharedMesh.vertexCount]; for (int p = 0; p < blendShape._deltaVertices.Length; p++) { detlaVertices.SetValue(blendShape._deltaVertices[p], p + blendShape._vertexOffset); detlaNormals.SetValue(blendShape._deltaNormals[p], p + blendShape._vertexOffset); detlaTangents.SetValue(blendShape._deltaTangents[p], p + blendShape._vertexOffset); } skinnedMeshRenderer.sharedMesh.AddBlendShapeFrame(blendShape._shapeName, blendShape._frameWeight, detlaVertices, detlaNormals, detlaTangents); } #endif #if UNITY_EDITOR MeshUtility.Optimize(skinnedMeshRenderer.sharedMesh); #endif combined.transform.SetParent(parent); combined.transform.localPosition = Vector3.zero; _combinedResult._totalVertexCount += skinnedMeshRenderer.sharedMesh.vertexCount; _combinedResult.AddCombinedMesh(skinnedMeshRenderer.sharedMesh, instances, combinedIndex); return(combined); }
/// <summary> /// Create a new GameObject based on the CombineInstance list. /// Set its MeshFilter and MeshRenderer to the new combined Meshe/Material /// </summary> /// <param name="instances"></param> /// <param name="parent"></param> /// <param name="number"></param> /// <returns></returns> public GameObject CreateCombinedMeshGameObject(CombineInstanceID instances, Transform parent, int number, int combinedIndex) { GameObject combined; MeshFilter meshFilter; MeshRenderer meshRenderer; // If parent has components MeshFilters and MeshRenderers, replace meshes and materials if (number == 0 && parent.GetComponent <MeshFilter>() != null && parent.GetComponent <MeshRenderer>() != null) { combined = parent.gameObject; meshFilter = parent.GetComponent <MeshFilter>(); meshRenderer = parent.GetComponent <MeshRenderer>(); } else { combined = new GameObject(_sessionName + "_" + _combinedResult._combinedMaterials[combinedIndex].displayedIndex + "_" + number.ToString()); meshFilter = combined.AddComponent <MeshFilter>(); meshRenderer = combined.AddComponent <MeshRenderer>(); combined.transform.SetParent(parent); combined.transform.localPosition = Vector3.zero; } meshRenderer.sharedMaterial = _combinedResult._combinedMaterials[combinedIndex].material; meshFilter.mesh = new Mesh(); meshFilter.sharedMesh.name = _sessionName + "_" + _combinedResult._combinedMaterials[combinedIndex].displayedIndex + "_mesh" + number; meshFilter.sharedMesh.CombineMeshes(instances._combineInstances.ToArray()); #if UNITY_EDITOR MeshUtility.Optimize(meshFilter.sharedMesh); if (_generateUv2) { Unwrapping.GenerateSecondaryUVSet(meshFilter.sharedMesh); } #endif _combinedResult._totalVertexCount += meshFilter.sharedMesh.vertexCount; _combinedResult.AddCombinedMesh(meshFilter.sharedMesh, instances, combinedIndex); return(combined); }
/// <summary> /// Create a new combineInstance based on a new mesh /// </summary> /// <param name="mesh"></param> /// <param name="sharedMaterials"></param> /// <param name="instanceID"></param> /// <param name="name"></param> /// <param name="matrix"></param> /// <param name="combinedIndex"></param> /// <returns></returns> private CombineInstanceID CreateCombinedInstances(Mesh mesh, Material[] sharedMaterials, int instanceID, string name, Matrix4x4 matrix, int combinedIndex) { CombineInstanceID instances = new CombineInstanceID(); int[] textureIndexes = new int[mesh.subMeshCount]; for (int k = 0; k < mesh.subMeshCount; k++) { // Find corresponding _material for each submesh if (k < sharedMaterials.Length) { Material mat = sharedMaterials[k]; textureIndexes[k] = _combinedResult.FindCorrespondingMaterialIndex(mat, combinedIndex); } else { Logger.Instance.AddLog("SuperCombiner", " Mesh '" + mesh.name + "' has " + mesh.subMeshCount + " submeshes but only " + sharedMaterials.Length + " _material(s) assigned", Logger.LogLevel.LOG_WARNING); break; } } // Update submesh count _combinedResult._subMeshCount += (mesh.subMeshCount - 1); // Generate new UVs only if there are more than 1 _material combined if (_combinedResult._originalMaterialList[combinedIndex].Count > 1) { GenerateUV(mesh, textureIndexes, _combinedResult._combinedMaterials[combinedIndex].scaleFactors.ToArray(), name, combinedIndex); } for (int k = 0; k < mesh.subMeshCount; k++) { instances.AddCombineInstance(k, mesh, matrix, instanceID, name); } return(instances); }
public void AddRange(CombineInstanceID instances) { _combineInstances.AddRange(instances._combineInstances); _instancesID.AddRange(instances._instancesID); _names.AddRange(instances._names); }
public List <GameObject> CombineToMeshes(List <MeshRenderer> meshRenderers, List <SkinnedMeshRenderer> skinnedMeshRenderers, Transform parent, int combinedIndex) { // The list of Meshes created List <GameObject> combinedMeshes = new List <GameObject>(); // The list of _combineInstances CombineInstanceID combineInstances = new CombineInstanceID(); int verticesCount = 0; int combinedGameObjectCount = 0; // Process meshes for combine process for (int i = 0; i < meshRenderers.Count; i++) { for (int j = 0; j < meshRenderers[i].GetComponent <MeshFilter>().sharedMesh.subMeshCount; j++) { // Get a copy of the submesh at index j Mesh newMesh = SubmeshSplitter.ExtractSubmesh(meshRenderers[i].GetComponent <MeshFilter>().sharedMesh, j); verticesCount += newMesh.vertexCount; if (verticesCount > _maxVerticesCount) { combinedMeshes.Add(CreateCombinedMeshGameObject(combineInstances, parent, combinedGameObjectCount, combinedIndex)); combineInstances.Clear(); combinedGameObjectCount++; verticesCount = newMesh.vertexCount; } // Create the list of CombineInstance for this mesh Matrix4x4 matrix = parent.transform.worldToLocalMatrix * meshRenderers[i].transform.localToWorldMatrix; combineInstances.AddRange(CreateCombinedInstances(newMesh, new Material[] { meshRenderers[i].sharedMaterials[j] }, meshRenderers[i].gameObject.GetInstanceID(), meshRenderers[i].gameObject.name, matrix, combinedIndex)); } } for (int i = 0; i < skinnedMeshRenderers.Count; i++) { for (int j = 0; j < meshRenderers[i].GetComponent <MeshFilter>().sharedMesh.subMeshCount; j++) { // Get a snapshot of the sub skinnedMesh renderer at index j Mesh newMesh = SubmeshSplitter.ExtractSubmesh(skinnedMeshRenderers[i].sharedMesh, j); _vertexOffset += newMesh.vertexCount; verticesCount += newMesh.vertexCount; if (verticesCount > _maxVerticesCount && combineInstances.Count() > 0) { combinedMeshes.Add(CreateCombinedMeshGameObject(combineInstances, parent, combinedGameObjectCount, combinedIndex)); combineInstances.Clear(); combinedGameObjectCount++; verticesCount = newMesh.vertexCount; } // Create the list of CombineInstance for this skinnedMesh Matrix4x4 matrix = parent.transform.worldToLocalMatrix * skinnedMeshRenderers[i].transform.localToWorldMatrix; combineInstances.AddRange(CreateCombinedInstances(newMesh, new Material[] { skinnedMeshRenderers[i].sharedMaterials[j] }, skinnedMeshRenderers[i].GetInstanceID(), skinnedMeshRenderers[i].gameObject.name, matrix, combinedIndex)); } } if (combineInstances.Count() > 0) { // Create the combined GameObject which contains the combined meshes combinedMeshes.Add(CreateCombinedMeshGameObject(combineInstances, parent, combinedGameObjectCount, combinedIndex)); } return(combinedMeshes); }
public List <GameObject> CombineToSkinnedMeshes(List <MeshRenderer> meshRenderers, List <SkinnedMeshRenderer> skinnedMeshRenderers, Transform parent, int combinedIndex) { // The list of Meshes created List <GameObject> combinedMeshes = new List <GameObject>(); // The list of _combineInstances CombineInstanceID combineInstances = new CombineInstanceID(); int verticesCount = 0; int combinedGameObjectCount = 0; /* * / Skinned mesh parameters */ // List of bone weight List <BoneWeight> boneWeights = new List <BoneWeight>(); // List of bones List <Transform> bones = new List <Transform>(); // List of bindposes List <Matrix4x4> bindposes = new List <Matrix4x4>(); // List of original bones mapped to their instanceId Dictionary <int, Transform> originalBones = new Dictionary <int, Transform>(); // Link original bone instanceId to the new created bones Dictionary <int, Transform> originToNewBoneMap = new Dictionary <int, Transform>(); // The vertices count int boneOffset = 0; // Get bones hierarchies from all skinned mesh for (int i = 0; i < skinnedMeshRenderers.Count; i++) { foreach (Transform t in skinnedMeshRenderers[i].bones) { if (!originalBones.ContainsKey(t.GetInstanceID())) { originalBones.Add(t.GetInstanceID(), t); } } } // Find the root bones Transform[] rootBones = FindRootBone(originalBones); for (int i = 0; i < rootBones.Length; i++) { // Instantiate the GameObject parent for this rootBone GameObject rootBoneParent = new GameObject("rootBone" + i); rootBoneParent.transform.position = rootBones[i].position; rootBoneParent.transform.parent = parent; rootBoneParent.transform.localPosition -= rootBones[i].localPosition; rootBoneParent.transform.localRotation = Quaternion.identity; // Instanciate a copy of the root bone GameObject newRootBone = InstantiateCopy(rootBones[i].gameObject); newRootBone.transform.position = rootBones[i].position; newRootBone.transform.rotation = rootBones[i].rotation; newRootBone.transform.parent = rootBoneParent.transform; newRootBone.AddComponent <MeshRenderer>(); // Get the correspondancy map between original bones and new bones GetOrignialToNewBonesCorrespondancy(rootBones[i], newRootBone.transform, originToNewBoneMap); } // Copy Animator Controllers to new Combined GameObject foreach (Animator anim in parent.parent.GetComponentsInChildren <Animator>()) { Transform[] children = anim.GetComponentsInChildren <Transform>(); // Find the transform into which a copy of the Animator component will be added Transform t = FindTransformForAnimator(children, rootBones, anim); if (t != null) { CopyAnimator(anim, originToNewBoneMap[t.GetInstanceID()].parent.gameObject); } } for (int i = 0; i < skinnedMeshRenderers.Count; i++) { // Get a snapshot of the skinnedMesh renderer Mesh mesh = copyMesh(skinnedMeshRenderers[i].sharedMesh, skinnedMeshRenderers[i].GetInstanceID().ToString()); _vertexOffset += mesh.vertexCount; verticesCount += skinnedMeshRenderers[i].sharedMesh.vertexCount; if (verticesCount > _maxVerticesCount && combineInstances.Count() > 0) { // Create the new GameObject GameObject combinedGameObject = CreateCombinedSkinnedMeshGameObject(combineInstances, parent, combinedGameObjectCount, combinedIndex); // Assign skinnedMesh parameters values SkinnedMeshRenderer sk = combinedGameObject.GetComponent <SkinnedMeshRenderer>(); AssignParametersToSkinnedMesh(sk, bones, boneWeights, bindposes); combinedMeshes.Add(combinedGameObject); boneOffset = 0; combineInstances.Clear(); combinedGameObjectCount++; verticesCount = skinnedMeshRenderers[i].sharedMesh.vertexCount; } // Copy bone weights BoneWeight[] meshBoneweight = skinnedMeshRenderers[i].sharedMesh.boneWeights; foreach (BoneWeight bw in meshBoneweight) { BoneWeight bWeight = bw; bWeight.boneIndex0 += boneOffset; bWeight.boneIndex1 += boneOffset; bWeight.boneIndex2 += boneOffset; bWeight.boneIndex3 += boneOffset; boneWeights.Add(bWeight); } boneOffset += skinnedMeshRenderers[i].bones.Length; // Copy bones and bindposes Transform[] meshBones = skinnedMeshRenderers[i].bones; foreach (Transform bone in meshBones) { bones.Add(originToNewBoneMap[bone.GetInstanceID()]); bindposes.Add(bone.worldToLocalMatrix * parent.transform.localToWorldMatrix); } // Create the list of CombineInstance for this skinnedMesh Matrix4x4 matrix = parent.transform.worldToLocalMatrix * skinnedMeshRenderers[i].transform.localToWorldMatrix; combineInstances.AddRange(CreateCombinedInstances(mesh, skinnedMeshRenderers[i].sharedMaterials, skinnedMeshRenderers[i].GetInstanceID(), skinnedMeshRenderers[i].gameObject.name, matrix, combinedIndex)); } if (combineInstances.Count() > 0) { // Create the combined GameObject which contains the combined meshes // Create the new GameObject GameObject combinedGameObject = CreateCombinedSkinnedMeshGameObject(combineInstances, parent, combinedGameObjectCount, combinedIndex); // Assign skinnedMesh parameters values SkinnedMeshRenderer sk = combinedGameObject.GetComponent <SkinnedMeshRenderer>(); AssignParametersToSkinnedMesh(sk, bones, boneWeights, bindposes); combinedMeshes.Add(combinedGameObject); } return(combinedMeshes); }