Exemplo n.º 1
0
        static List <ProBuilderMesh> CombineToNewMeshes(IEnumerable <ProBuilderMesh> meshes)
        {
            if (meshes == null)
            {
                throw new ArgumentNullException("meshes");
            }

            if (!meshes.Any() || meshes.Count() < 2)
            {
                return(null);
            }

            var vertices       = new List <Vertex>();
            var faces          = new List <Face>();
            var autoUvFaces    = new List <Face>();
            var sharedVertices = new List <SharedVertex>();
            var sharedTextures = new List <SharedVertex>();
            int offset         = 0;
            var materialMap    = new List <Material>();

            AccumulateMeshesInfo(
                meshes,
                offset,
                ref vertices,
                ref faces,
                ref autoUvFaces,
                ref sharedVertices,
                ref sharedTextures,
                ref materialMap
                );

            var res   = SplitByMaxVertexCount(vertices, faces, sharedVertices, sharedTextures);
            var pivot = meshes.LastOrDefault().transform.position;

            foreach (var m in res)
            {
                m.renderer.sharedMaterials = materialMap.ToArray();
                InternalMeshUtility.FilterUnusedSubmeshIndexes(m);
                m.SetPivot(pivot);
                UVEditing.SetAutoAndAlignUnwrapParamsToUVs(m, autoUvFaces);
            }

            return(res);
        }
        /// <summary>
        /// Merge a collection of <see cref="ProBuilderMesh"/> objects to as few meshes as possible. This may result in
        /// more than one mesh due to a max vertex count limit of 65535.
        /// </summary>
        /// <param name="meshes">A collection of meshes to be merged.</param>
        /// <returns>
        /// A list of merged meshes. In most cases this will be a single mesh. However it can be multiple in cases
        /// where the resulting vertex count exceeds the maximum allowable value.
        /// </returns>
        public static List <ProBuilderMesh> Combine(IEnumerable <ProBuilderMesh> meshes)
        {
            if (meshes == null)
            {
                throw new ArgumentNullException("meshes");
            }

            if (!meshes.Any() || meshes.Count() < 2)
            {
                return(null);
            }

            var vertices       = new List <Vertex>();
            var faces          = new List <Face>();
            var autoUvFaces    = new List <Face>();
            var sharedVertices = new List <SharedVertex>();
            var sharedTextures = new List <SharedVertex>();
            int offset         = 0;
            var materialMap    = new List <Material>();

            foreach (var mesh in meshes)
            {
                var meshVertexCount    = mesh.vertexCount;
                var transform          = mesh.transform;
                var meshVertices       = mesh.GetVertices();
                var meshFaces          = mesh.facesInternal;
                var meshSharedVertices = mesh.sharedVertices;
                var meshSharedTextures = mesh.sharedTextures;
                var materials          = mesh.renderer.sharedMaterials;
                var materialCount      = materials.Length;

                for (int i = 0; i < meshVertexCount; i++)
                {
                    vertices.Add(transform.TransformVertex(meshVertices[i]));
                }

                foreach (var face in meshFaces)
                {
                    var newFace = new Face(face);
                    newFace.ShiftIndexes(offset);

                    // prevents uvs from shifting when being converted from local coords to world space
                    if (!newFace.manualUV && !newFace.uv.useWorldSpace)
                    {
                        newFace.manualUV = true;
                        autoUvFaces.Add(newFace);
                    }
                    var material     = materials[Math.Clamp(face.submeshIndex, 0, materialCount - 1)];
                    var submeshIndex = materialMap.IndexOf(material);

                    if (submeshIndex > -1)
                    {
                        newFace.submeshIndex = submeshIndex;
                    }
                    else
                    {
                        if (material == null)
                        {
                            newFace.submeshIndex = 0;
                        }
                        else
                        {
                            newFace.submeshIndex = materialMap.Count;
                            materialMap.Add(material);
                        }
                    }

                    faces.Add(newFace);
                }

                foreach (var sv in meshSharedVertices)
                {
                    var nsv = new SharedVertex(sv);
                    nsv.ShiftIndexes(offset);
                    sharedVertices.Add(nsv);
                }

                foreach (var st in meshSharedTextures)
                {
                    var nst = new SharedVertex(st);
                    nst.ShiftIndexes(offset);
                    sharedTextures.Add(nst);
                }

                offset += meshVertexCount;
            }

            var res   = SplitByMaxVertexCount(vertices, faces, sharedVertices, sharedTextures);
            var pivot = meshes.LastOrDefault().transform.position;

            foreach (var m in res)
            {
                m.renderer.sharedMaterials = materialMap.ToArray();
                InternalMeshUtility.FilterUnusedSubmeshIndexes(m);
                m.SetPivot(pivot);
                UVEditing.SetAutoAndAlignUnwrapParamsToUVs(m, autoUvFaces);
            }

            return(res);
        }