Mesh Manipulation - Mesh合并

做项目的时候,有的时候我们需要把多个Mesh合并起来,只是为了让我们做起来的时候更方便些。下面是Mesh合并的代码,支持动态合并和保存到文件。

using UnityEngine;
using System.Collections.Generic;

namespace LDFW.Model
{
    
    public class MeshCombiner : MonoBehaviour
    {
        public List                  subMeshTransformList0;
        public List                  subMeshTransformList1;
        public List                  subMeshTransformList2;
        public List                  subMeshTransformList3;
        public List                  multiSubMeshTransformList;
        public string                           meshSavePath = "Assets/";



        public Mesh CombineMeshesWithSameUV(List transformList)
        {
            if (transformList == null || transformList.Count <= 0)
            {
                Debug.LogError("Input transform list is null!");
                return null;
            }

            Mesh newMesh = new Mesh();
            
            List vertexList = new List();
            List uvList = new List();
            List triangleList = new List();
            int currentVertexListLength = 0;

            foreach (var trans in transformList)
            {
                if (trans == null)
                    continue;

                MeshFilter meshFilter = trans.GetComponent();
                if (meshFilter == null)
                    continue;

                Mesh mesh = meshFilter.mesh;
                if (mesh == null)
                    continue;

                currentVertexListLength = vertexList.Count;

                foreach (var vertex in mesh.vertices)
                    vertexList.Add(transform.InverseTransformPoint(trans.TransformPoint(vertex)));

                foreach (var uv in mesh.uv)
                    uvList.Add(uv);

                foreach (var triangleVertexIndex in mesh.triangles)
                    triangleList.Add(currentVertexListLength + triangleVertexIndex);

            }

            newMesh.vertices = vertexList.ToArray();
            newMesh.uv = uvList.ToArray();
            newMesh.triangles = triangleList.ToArray();

            return newMesh;
        }
        
        public Mesh CombineSubMeshes(List subMesh0, List subMesh1, List subMesh2, List subMesh3)
        {
            Mesh[] subMeshArray = new Mesh[4]
            {
                CombineMeshesWithSameUV(subMesh0),
                CombineMeshesWithSameUV(subMesh1),
                CombineMeshesWithSameUV(subMesh2),
                CombineMeshesWithSameUV(subMesh3),
            };
            

            Mesh newMesh = new Mesh();
            List vertexList = new List();
            List uvList = new List();
            List triangleIndexList = new List();
            int currentVertexCount = 0;

            Mesh currentMesh;
            Vector3[] currentMeshVertices;
            Vector2[] currentMeshUV;
            int[] currentMeshTriangleIndices;
            List[] subMeshTriangleListArray = new List[4];

            int subMeshCount = 0;


            for (int i = 0; i < 4; i++)
            {
                currentMesh = subMeshArray[i];
                subMeshTriangleListArray[i] = new List();

                if (currentMesh == null)
                    continue;


                subMeshCount++;
                currentVertexCount = vertexList.Count;
                currentMeshVertices = currentMesh.vertices;
                currentMeshUV = currentMesh.uv;
                currentMeshTriangleIndices = currentMesh.triangles;

                foreach (var vertex in currentMeshVertices)
                    vertexList.Add(vertex);

                foreach (var uv in currentMeshUV)
                    uvList.Add(uv);

                foreach (var triangleIndex in currentMeshTriangleIndices)
                {
                    subMeshTriangleListArray[i].Add(currentVertexCount + triangleIndex);
                    triangleIndexList.Add(currentVertexCount + triangleIndex);
                }

            }

            newMesh.vertices = vertexList.ToArray();

            newMesh.subMeshCount = subMeshCount;
            if (subMeshCount >= 1)
            {
                newMesh.uv = uvList.ToArray();
                newMesh.SetIndices(subMeshTriangleListArray[0].ToArray(), MeshTopology.Triangles, 0);
            }
            if (subMeshCount >= 2)
            {
                newMesh.uv2 = uvList.ToArray();
                newMesh.SetIndices(subMeshTriangleListArray[1].ToArray(), MeshTopology.Triangles, 1);
            }
            if (subMeshCount >= 3)
            {
                newMesh.uv3 = uvList.ToArray();
                newMesh.SetIndices(subMeshTriangleListArray[2].ToArray(), MeshTopology.Triangles, 2);
            }
            if (subMeshCount >= 4)
            {
                newMesh.uv4 = uvList.ToArray();
                newMesh.SetIndices(subMeshTriangleListArray[3].ToArray(), MeshTopology.Triangles, 3);
            }
            
            newMesh.RecalculateBounds();
            newMesh.RecalculateNormals();

            System.GC.Collect();

            return newMesh;
        }

        public Mesh CombineMultiSubMeshes(List multiSubMeshList)
        {

            Mesh newMesh = new Mesh();
            Mesh currentMesh = null;
            int totalSubMeshCount = 0;

            List vertices = new List();
            List uvs = new List();

            List[] uvList= new List[4];
            for (int i = 0; i < 4; i++)
                uvList[i] = new List();

            List[] triangleList = new List[4];
            for (int i = 0; i < 4; i++)
                triangleList[i] = new List();


            // i:                   multiSubMeshList index
            // totalSubMeshCount:   total submesh count
            // 
            for (int i = 0; totalSubMeshCount < 4 && i < multiSubMeshList.Count; i++)
            {
                if (multiSubMeshList[i] == null)
                    continue;

                currentMesh = multiSubMeshList[i].GetComponent().mesh;
                if (currentMesh == null)
                    continue;

                Debug.Log(MeshInfoExtractor.GetMeshVerticesData(currentMesh));
                Debug.Log(MeshInfoExtractor.GetMeshUVData(currentMesh));
                Debug.Log(MeshInfoExtractor.GetTriangleData(currentMesh));
                Debug.Log(MeshInfoExtractor.GetSubmeshData(currentMesh));


                int currentSubMeshCount = currentMesh.subMeshCount;
                if (totalSubMeshCount + currentSubMeshCount > 4)
                    break;

                
                int currentVertexCount = vertices.Count;

                // concatenate vertices and uvs
                AddVertices(vertices, currentMesh.vertices, transform, multiSubMeshList[i]);
                AddUVs(uvs, currentMesh.uv);

                // Extract submesh triangles
                int[][] currentMeshTriangleArray = new int[currentSubMeshCount][];
                for (int j = 0; j < currentSubMeshCount; j++)
                    currentMeshTriangleArray[j] = currentMesh.GetTriangles(j);

                // Concatenate submesh triangles
                int currentMeshTriangleArrayIndex = 0;
                for (int j = totalSubMeshCount; j < totalSubMeshCount + currentSubMeshCount; j++)
                {
                    if (currentMeshTriangleArray[currentMeshTriangleArrayIndex] != null)
                        AddMeshTriangle(triangleList[j], currentMeshTriangleArray[currentMeshTriangleArrayIndex], currentVertexCount);

                    currentMeshTriangleArrayIndex++;
                }

                totalSubMeshCount += currentSubMeshCount;
            }

            Debug.Log("Vertices length = " + vertices.Count);
            Debug.Log("UVs length = " + uvList[0].Count + ", " + uvList[1].Count + ", " + uvList[2].Count + ", " + uvList[3].Count);
            Debug.Log("Triangles length = " + triangleList[0].Count + ", " + triangleList[1].Count + ", " + triangleList[2].Count + ", " + triangleList[3].Count);

            newMesh.SetVertices(vertices);
            newMesh.uv = uvs.ToArray();

            newMesh.subMeshCount = totalSubMeshCount;
            for (int i = 0; i < totalSubMeshCount; i++)
                newMesh.SetIndices(triangleList[i].ToArray(), MeshTopology.Triangles, i);
            
            newMesh.RecalculateBounds();
            newMesh.RecalculateNormals();

            System.GC.Collect();

            return newMesh;
        }

        private void AddVertices(List targetVertices, Vector3[] newVertices, Transform newParent, Transform oldParent)
        {
            if (newVertices != null)
            {
                foreach (var vec3 in newVertices)
                    targetVertices.Add(newParent.InverseTransformPoint(oldParent.TransformPoint(vec3)));
            }
        }

        private void AddUVs(List targetUVs, Vector2[] newUVs)
        {
            if (newUVs != null)
            {
                foreach (var vec2 in newUVs)
                    targetUVs.Add(vec2);
            }
        }

        private void AddMeshUV(List targetUV, Vector2[] uvArray)
        {
            if (uvArray != null)
            {
                foreach (var vec2 in uvArray)
                    targetUV.Add(vec2);
            }
        }

        private void AddMeshTriangle(List targetTriangles, int[] triangleArray, int triangleIndexOffset)
        {
            if (triangleArray != null)
            {
                for (int i = 0; i < triangleArray.Length; i++)
                {
                    targetTriangles.Add(triangleArray[i] + triangleIndexOffset);
                }

            }
        }




    }

}

你可能感兴趣的:(Mesh Manipulation - Mesh合并)