Ejemplo n.º 1
0
        public static bool DetachFacesToObject(this pb_Object pb, pb_Face[] faces, out pb_Object detachedObject)
        {
            detachedObject = null;

            if (faces.Length < 1 || faces.Length == pb.faces.Length)
            {
                return(false);
            }

            int[] primary = new int[faces.Length];
            for (int i = 0; i < primary.Length; i++)
            {
                primary[i] = System.Array.IndexOf(pb.faces, faces[i]);
            }

            int[] inverse = new int[pb.faces.Length - primary.Length];
            int   n       = 0;

            for (int i = 0; i < pb.faces.Length; i++)
            {
                if (System.Array.IndexOf(primary, i) < 0)
                {
                    inverse[n++] = i;
                }
            }

            detachedObject = pb_Object.InitWithObject(pb);

            detachedObject.transform.position      = pb.transform.position;
            detachedObject.transform.localScale    = pb.transform.localScale;
            detachedObject.transform.localRotation = pb.transform.localRotation;

            pb.DeleteFaces(primary);
            detachedObject.DeleteFaces(inverse);

            pb.Refresh();
            detachedObject.Refresh();

            detachedObject.gameObject.name = pb.gameObject.name + "-detach";

            return(true);
        }
Ejemplo n.º 2
0
        /**
         *	Splits face per vertex.
         *	Todo - Could implement more sanity checks - namely testing for edges before sending to Split_Internal.  However,
         *	the split method is smart enough to fail on those cases, so ignore for now.
         */
        public static bool ConnectVertices(this pb_Object pb, List <pb_VertexConnection> vertexConnectionsUnfiltered, out int[] triangles)
        {
            List <pb_VertexConnection> vertexConnections = new List <pb_VertexConnection>();
            List <int> inds = new List <int>();

            int i = 0;

            for (i = 0; i < vertexConnectionsUnfiltered.Count; i++)
            {
                pb_VertexConnection vc = vertexConnectionsUnfiltered[i];
                vc.indices = vc.indices.Distinct().ToList();

                if (vc.isValid)
                {
                    inds.AddRange(vc.indices);
                    vertexConnections.Add(vc);
                }
            }

            if (vertexConnections.Count < 1)
            {
                triangles = null;
                return(false);
            }

            List <Vector3> selectedVertices = pb.GetVertices(pb_VertexConnection.AllTriangles(vertexConnections));

            int len = vertexConnections.Count;

            // new faces will be built from successfull split ops
            List <pb_Face> successfullySplitFaces = new List <pb_Face>();
            List <pb_Face> all_splitFaces         = new List <pb_Face>();

            List <Vector3[]> all_splitVertices = new List <Vector3[]>();
            List <Color[]>   all_splitColors   = new List <Color[]>();
            List <Vector2[]> all_splitUVs      = new List <Vector2[]>();

            List <int[]> all_splitSharedIndices = new List <int[]>();

            bool[] success = new bool[len];

            pb_IntArray[] sharedIndices = pb.sharedIndices;

            i = 0;
            foreach (pb_VertexConnection vc in vertexConnections)
            {
                pb_Face[]   splitFaces    = null;
                Vector3[][] splitVertices = null;
                Color[][]   splitColors   = null;
                Vector2[][] splitUVs;
                int[][]     splitSharedIndices = null;

                if (vc.indices.Count < 3)
                {
                    int indA = vc.face.indices.IndexOf(vc.indices[0], sharedIndices);
                    int indB = vc.face.indices.IndexOf(vc.indices[1], sharedIndices);

                    if (indA < 0 || indB < 0)
                    {
                        success[i] = false;
                        continue;
                    }

                    indA = vc.face.indices[indA];
                    indB = vc.face.indices[indB];

                    success[i] = SplitFace_Internal(
                        new SplitSelection(pb, vc.face, pb.vertices[indA], pb.vertices[indB], pb.colors[indA], pb.colors[indB], true, true, new int[] { indA }, new int[] { indB }),
                        out splitFaces,
                        out splitVertices,
                        out splitColors,
                        out splitUVs,
                        out splitSharedIndices);

                    if (success[i])
                    {
                        successfullySplitFaces.Add(vc.face);
                    }
                }
                else
                {
                    Vector3 pokedVertex;

                    success[i] = PokeFace_Internal(pb, vc.face, vc.indices.ToArray(),
                                                   out pokedVertex,
                                                   out splitFaces,
                                                   out splitVertices,
                                                   out splitColors,
                                                   out splitUVs,
                                                   out splitSharedIndices);

                    if (success[i])
                    {
                        selectedVertices.Add(pokedVertex);
                        successfullySplitFaces.Add(vc.face);
                    }
                }

                if (success[i])
                {
                    int texGroup = pb.UnusedTextureGroup(i + 1);

                    for (int j = 0; j < splitFaces.Length; j++)
                    {
                        splitFaces[j].textureGroup = texGroup;

                        all_splitFaces.Add(splitFaces[j]);
                        all_splitVertices.Add(splitVertices[j]);
                        all_splitColors.Add(splitColors[j]);
                        all_splitUVs.Add(splitUVs[j]);

                        all_splitSharedIndices.Add(splitSharedIndices[j]);
                    }
                }

                i++;
            }

            if (all_splitFaces.Count < 1)
            {
                triangles = null;
                return(false);
            }

            pb_Face[] appendedFaces = pb.AppendFaces(all_splitVertices.ToArray(),
                                                     all_splitColors.ToArray(),
                                                     all_splitUVs.ToArray(),
                                                     all_splitFaces.ToArray(),
                                                     all_splitSharedIndices.ToArray());

            inds.AddRange(pb_Face.AllTriangles(appendedFaces));

            int[] welds;
            pb.WeldVertices(inds.ToArray(), Mathf.Epsilon, out welds);

            pb.DeleteFaces(successfullySplitFaces.ToArray());

            List <int> seltris = new List <int>();

            for (i = 0; i < selectedVertices.Count; i++)
            {
                int ind = System.Array.IndexOf(pb.vertices, selectedVertices[i]);
                if (ind > -1)
                {
                    seltris.Add(ind);
                }
            }

            triangles = seltris.Distinct().ToArray();
            return(true);
        }
Ejemplo n.º 3
0
        private static bool ConnectEdges(this pb_Object pb, List <pb_EdgeConnection> pb_edgeConnectionsUnfiltered, out pb_Face[] faces)
        {
            List <pb_EdgeConnection> pb_edgeConnections = new List <pb_EdgeConnection>();

            foreach (pb_EdgeConnection ec in pb_edgeConnectionsUnfiltered)
            {
                if (ec.isValid)
                {
                    pb_edgeConnections.Add(ec);
                }
            }

            int len = pb_edgeConnections.Count;

            if (len < 1)
            {
                faces = null;
                return(false);
            }

            Vector3[] vertices = pb.vertices;
            Color[]   colors   = pb.colors;

            List <pb_Face> successfullySplitFaces = new List <pb_Face>();

            List <pb_Face>   all_splitFaces         = new List <pb_Face>();
            List <Vector3[]> all_splitVertices      = new List <Vector3[]>();
            List <Color[]>   all_splitColors        = new List <Color[]>();
            List <Vector2[]> all_splitUVs           = new List <Vector2[]>();
            List <int[]>     all_splitSharedIndices = new List <int[]>();

            bool[] success = new bool[len];

            // use a nullable type because in order for the adjacent face triangulation
            // code to work, it needs to know what dangling vert belongs to which edge,
            // if we out a vector3[] with each index corresponding to the passed edges
            // in pb_EdgeConnection, it's easy to maintain the relationship.
            DanglingVertex?[][] danglingVertices = new DanglingVertex?[len][];

            // profiler.BeginSample("foreach(edge connection)");
            int i = 0;

            foreach (pb_EdgeConnection fc in pb_edgeConnections)
            {
                pb_Face[]   splitFaces         = null;
                Vector3[][] splitVertices      = null;
                Color[][]   splitColors        = null;
                Vector2[][] splitUVs           = null;
                int[][]     splitSharedIndices = null;

                if (fc.edges.Count < 3)
                {
                    Vector3 edgeACen = (vertices[fc.edges[0].x] + vertices[fc.edges[0].y]) / 2f;
                    Vector3 edgeBCen = (vertices[fc.edges[1].x] + vertices[fc.edges[1].y]) / 2f;

                    Color cola = (colors[fc.edges[0].x] + colors[fc.edges[0].y]) / 2f;
                    Color colb = (colors[fc.edges[1].x] + colors[fc.edges[1].y]) / 2f;

                    danglingVertices[i] = new DanglingVertex?[2] {
                        new DanglingVertex(edgeACen, cola), new DanglingVertex(edgeBCen, colb)
                    };

                    success[i] = SplitFace_Internal(
                        new SplitSelection(pb, fc.face, edgeACen, edgeBCen, cola, colb, false, false, new int[] { fc.edges[0].x, fc.edges[0].y }, new int[] { fc.edges[1].x, fc.edges[1].y }),
                        out splitFaces,
                        out splitVertices,
                        out splitColors,
                        out splitUVs,
                        out splitSharedIndices);

                    if (success[i])
                    {
                        successfullySplitFaces.Add(fc.face);
                    }
                }
                else
                {
                    DanglingVertex?[] appendedVertices = null;

                    success[i] = SubdivideFace_Internal(pb, fc,
                                                        out appendedVertices,
                                                        out splitFaces,
                                                        out splitVertices,
                                                        out splitColors,
                                                        out splitUVs,
                                                        out splitSharedIndices);

                    if (success[i])
                    {
                        successfullySplitFaces.Add(fc.face);
                    }

                    danglingVertices[i] = appendedVertices;
                }

                if (success[i])
                {
                    int texGroup = fc.face.textureGroup < 0 ? pb.UnusedTextureGroup(i + 1) : fc.face.textureGroup;

                    for (int j = 0; j < splitFaces.Length; j++)
                    {
                        splitFaces[j].textureGroup = texGroup;
                        all_splitFaces.Add(splitFaces[j]);
                        all_splitVertices.Add(splitVertices[j]);
                        all_splitColors.Add(splitColors[j]);
                        all_splitUVs.Add(splitUVs[j]);
                        all_splitSharedIndices.Add(splitSharedIndices[j]);
                    }
                }

                i++;
            }
            // profiler.EndSample();


            // profiler.BeginSample("Retrianguate");

            /**
             *	Figure out which faces need to be re-triangulated
             */
            pb_Edge[][] tedges = new pb_Edge[pb_edgeConnections.Count][];
            int         n      = 0;

            for (i = 0; i < pb_edgeConnections.Count; i++)
            {
                tedges[n++] = pb_edgeConnections[i].edges.ToArray();
            }

            List <pb_Face>[][] allConnects = pbMeshUtils.GetNeighborFacesJagged(pb, tedges);


            Dictionary <pb_Face, List <DanglingVertex> > addVertex = new Dictionary <pb_Face, List <DanglingVertex> >();
            List <pb_Face> temp = new List <pb_Face>();

            for (int j = 0; j < pb_edgeConnections.Count; j++)
            {
                if (!success[j])
                {
                    continue;
                }

                // check that this edge has a buddy that it welded it's new vertex to, and if not,
                // create one
                for (i = 0; i < pb_edgeConnections[j].edges.Count; i++)
                {
                    if (danglingVertices[j][i] == null)
                    {
                        continue;
                    }

                    List <pb_Face> connected = allConnects[j][i];

                    foreach (pb_Face face in connected)
                    {
                        int ind = successfullySplitFaces.IndexOf(face);

                        if (ind < 0)
                        {
                            if (addVertex.ContainsKey(face))
                            {
                                addVertex[face].Add((DanglingVertex)danglingVertices[j][i]);
                            }
                            else
                            {
                                temp.Add(face);
                                addVertex.Add(face, new List <DanglingVertex>(1)
                                {
                                    (DanglingVertex)danglingVertices[j][i]
                                });
                            }
                        }
                    }
                }
            }
            // profiler.EndSample();

            // profiler.BeginSample("Append vertices to faces");
            pb_Face[] appendedFaces = pb.AppendFaces(all_splitVertices.ToArray(), all_splitColors.ToArray(), all_splitUVs.ToArray(), all_splitFaces.ToArray(), all_splitSharedIndices.ToArray());

            List <pb_Face> triangulatedFaces = new List <pb_Face>();

            foreach (KeyValuePair <pb_Face, List <DanglingVertex> > add in addVertex)
            {
                pb_Face newFace;

                if (pb.AppendVerticesToFace(add.Key, add.Value.Select(x => x.position).ToArray(), add.Value.Select(x => x.color).ToArray(), out newFace))
                {
                    triangulatedFaces.Add(newFace);
                }
                else
                {
                    Debug.LogError("Mesh re-triangulation failed.");            //  Specifically, AppendVerticesToFace(" + add.Key + " : " + add.Value.ToFormattedString(", "));
                }
            }
            // profiler.EndSample();

            // profiler.BeginSample("rebuild mesh");

            // Re-triangulate any faces left with dangling verts at edges
            // Weld verts, including those added in re-triangu
            int[] splitFaceTris        = pb_Face.AllTriangles(appendedFaces);
            int[] triangulatedFaceTris = pb_Face.AllTriangles(triangulatedFaces);
            int[] allModifiedTris      = new int[splitFaceTris.Length + triangulatedFaceTris.Length];

            System.Array.Copy(splitFaceTris, 0, allModifiedTris, 0, splitFaceTris.Length);
            System.Array.Copy(triangulatedFaceTris, 0, allModifiedTris, splitFaceTris.Length, triangulatedFaceTris.Length);

            // safe to assume that we probably didn't delete anything :/
            int[] welds;

            // profiler.BeginSample("weld vertices");
            pb.WeldVertices(allModifiedTris, Mathf.Epsilon, out welds);

            // profiler.EndSample();
            // pb.SetSharedIndices( pb_IntArrayUtility.ExtractSharedIndices(pb.vertices) );

            // Now that we're done screwing with geo, delete all the old faces (that were successfully split)
            // profiler.BeginSample("delete faces");
            pb.DeleteFaces(successfullySplitFaces.ToArray());
            faces = appendedFaces;
            // profiler.EndSample();
            // profiler.EndSample();
            // profiler.EndSample();
            // Debug.Log(profiler.ToString());

            return(true);
        }
Ejemplo n.º 4
0
	/**
	 * Deletes @faces from the passed pb_Object, and creates a new pb_Object using @faces.  On success,
	 * detachedObject will be set to the new pb_Object.
	 * 
	 * NOTE - As of 2.3, `DetachFacesToObject` was not publicly available in the pbMeshOps.  This method
	 * was made available in 2.3.1 as an extension method to pb_Object:
	 * `pbMeshOps::DetachFacesToObject(this pb_Object pb, pb_Face[] faces, out pb_Object detachedObject)`
	 */
	static bool DetachFacesToObject(pb_Object pb, pb_Face[] faces, out pb_Object detachedObject)
	{
		detachedObject = null;

		if(faces.Length < 1 || faces.Length == pb.faces.Length)
			return false;

		int[] primary = new int[faces.Length];
		for(int i = 0; i < primary.Length; i++)
			primary[i] = System.Array.IndexOf(pb.faces, faces[i]);
		
		int[] inverse = new int[pb.faces.Length - primary.Length];
		int n = 0;

		for(int i = 0; i < pb.faces.Length; i++)
			if(System.Array.IndexOf(primary, i) < 0)
				inverse[n++] = i;
				
		detachedObject = pb_Object.InitWithObject(pb);

		detachedObject.transform.position = pb.transform.position;
		detachedObject.transform.localScale = pb.transform.localScale;
		detachedObject.transform.localRotation = pb.transform.localRotation;

		pb.DeleteFaces(primary);
		detachedObject.DeleteFaces(inverse);

		pb.ToMesh();
		detachedObject.ToMesh();

		pb.Refresh();
		detachedObject.Refresh();
	
		detachedObject.gameObject.name = pb.gameObject.name + "-detach";
		
		return true;
	}
Ejemplo n.º 5
0
        /**
         *
         */
        public static bool ConnectEdges(this pb_Object pb, List <EdgeConnection> edgeConnectionsUnfiltered, out pb_Face[] faces)
        {
            // first, remove any junk connections.  faces with less than two edges confuse this method.
            List <EdgeConnection> edgeConnections = new List <EdgeConnection>();

            foreach (EdgeConnection ec in edgeConnectionsUnfiltered)
            {
                if (ec.isValid)
                {
                    edgeConnections.Add(ec);
                }
            }

            int len = edgeConnections.Count;

            if (len < 1)
            {
                Debug.LogWarning("No valid split paths found.  This is most likely because you are attempting to split edges that do belong to the same face, or do not have more than one edge selected.  This is not currently supported, sorry!");
                faces = null;
                return(false);
            }


            Vector3[] vertices = pb.vertices;

            List <pb_Face> successfullySplitFaces = new List <pb_Face>();

            List <pb_Face>   all_splitFaces         = new List <pb_Face>();
            List <Vector3[]> all_splitVertices      = new List <Vector3[]>();
            List <int[]>     all_splitSharedIndices = new List <int[]>();

            bool[] success = new bool[len];

            // use a nullable type because in order for the adjacent face triangulation
            // code to work, it needs to know what dangling vert belongs to which edge,
            // if we out a vector3[] with each index corresponding to the passed edges
            // in EdgeConnection, it's easy to maintain the relationship.
            Vector3?[][] danglingVertices = new Vector3?[len][];

            int i = 0;

            foreach (EdgeConnection fc in edgeConnections)
            {
                pb_Face[]   splitFaces         = null;
                Vector3[][] splitVertices      = null;
                int[][]     splitSharedIndices = null;

                if (fc.edges.Count < 3)
                {
                    Vector3 edgeACen = (vertices[fc.edges[0].x] + vertices[fc.edges[0].y]) / 2f;
                    Vector3 edgeBCen = (vertices[fc.edges[1].x] + vertices[fc.edges[1].y]) / 2f;
                    danglingVertices[i] = new Vector3?[2] {
                        edgeACen, edgeBCen
                    };
                    success[i] = SplitFace_Internal(new SplitSelection(pb, fc.face, edgeACen, edgeBCen, false, false, -1, -1),
                                                    out splitFaces,
                                                    out splitVertices,
                                                    out splitSharedIndices);

                    if (success[i])
                    {
                        successfullySplitFaces.Add(fc.face);
                    }
                }
                else
                {
                    Vector3?[] appendedVertices = null;
                    success[i] = SubdivideFace_Internal(pb, fc,
                                                        out appendedVertices,
                                                        out splitFaces,
                                                        out splitVertices,
                                                        out splitSharedIndices);

                    if (success[i])
                    {
                        successfullySplitFaces.Add(fc.face);
                    }

                    danglingVertices[i] = appendedVertices;
                }

                if (success[i])
                {
                    int texGroup = fc.face.textureGroup < 0 ? pb.UnusedTextureGroup(i + 1) : fc.face.textureGroup;

                    for (int j = 0; j < splitFaces.Length; j++)
                    {
                        splitFaces[j].textureGroup = texGroup;
                        all_splitFaces.Add(splitFaces[j]);
                        all_splitVertices.Add(splitVertices[j]);
                        all_splitSharedIndices.Add(splitSharedIndices[j]);
                    }
                }

                i++;
            }

            /**
             *	Figure out which faces need to be re-triangulated
             */
            pb_Edge[][] tedges = new pb_Edge[edgeConnections.Count][];
            int         n      = 0;

            for (i = 0; i < edgeConnections.Count; i++)
            {
                tedges[n++] = edgeConnections[i].edges.ToArray();
            }

            List <pb_Face>[][] allConnects = pbMeshUtils.GetConnectedFacesJagged(pb, tedges);

            Dictionary <pb_Face, List <Vector3> > addVertex = new Dictionary <pb_Face, List <Vector3> >();
            List <pb_Face> temp = new List <pb_Face>();

            for (int j = 0; j < edgeConnections.Count; j++)
            {
                if (!success[j])
                {
                    continue;
                }

                // check that this edge has a buddy that it welded it's new vertex to, and if not,
                // create one
                for (i = 0; i < edgeConnections[j].edges.Count; i++)
                {
                    if (danglingVertices[j][i] == null)
                    {
                        continue;
                    }

                    List <pb_Face> connected = allConnects[j][i];

                    foreach (pb_Face face in connected)
                    {
                        int ind = successfullySplitFaces.IndexOf(face);

                        if (ind < 0)
                        {
                            if (addVertex.ContainsKey(face))
                            {
                                addVertex[face].Add((Vector3)danglingVertices[j][i]);
                            }
                            else
                            {
                                temp.Add(face);
                                addVertex.Add(face, new List <Vector3>(1)
                                {
                                    (Vector3)danglingVertices[j][i]
                                });
                            }
                        }
                    }
                }
            }

            pb_Face[] appendedFaces = pb.AppendFaces(all_splitVertices.ToArray(), all_splitFaces.ToArray(), all_splitSharedIndices.ToArray());

            List <pb_Face> triangulatedFaces = new List <pb_Face>();

            foreach (KeyValuePair <pb_Face, List <Vector3> > add in addVertex)
            {
                pb_Face newFace;
                if (pb.AppendVerticesToFace(add.Key, add.Value, out newFace))
                {
                    triangulatedFaces.Add(newFace);
                }
                else
                {
                    Debug.LogError("Mesh re-triangulation failed.  Specifically, AppendVerticesToFace(" + add.Key + " : " + add.Value.ToFormattedString(", "));
                }
            }

            // Re-triangulate any faces left with dangling verts at edges
            // Weld verts, including those added in re-triangu
            int[] splitFaceTris        = pb_Face.AllTriangles(appendedFaces);
            int[] triangulatedFaceTris = pb_Face.AllTriangles(triangulatedFaces);
            int[] allModifiedTris      = new int[splitFaceTris.Length + triangulatedFaceTris.Length];
            System.Array.Copy(splitFaceTris, 0, allModifiedTris, 0, splitFaceTris.Length);
            System.Array.Copy(triangulatedFaceTris, 0, allModifiedTris, splitFaceTris.Length, triangulatedFaceTris.Length);

            pb.WeldVertices(allModifiedTris, Mathf.Epsilon);

            // Now that we're done screwing with geo, delete all the old faces (that were successfully split)
            pb.DeleteFaces(successfullySplitFaces.ToArray());
            faces = appendedFaces;
            return(true);
        }
Ejemplo n.º 6
0
        /**
         *	Splits face per vertex.
         *	Todo - Could implement more sanity checks - namely testing for edges before sending to Split_Internal.  However,
         *	the split method is smart enough to fail on those cases, so ignore for now.
         */
        public static bool ConnectVertices(this pb_Object pb, List <VertexConnection> vertexConnectionsUnfiltered, out pb_Face[] faces)
        {
            List <VertexConnection> vertexConnections = new List <VertexConnection>();
            List <int> inds = new List <int>();

            int i = 0;

            for (i = 0; i < vertexConnectionsUnfiltered.Count; i++)
            {
                VertexConnection vc = vertexConnectionsUnfiltered[i];
                vc.indices = vc.indices.Distinct().ToList();

                if (vc.isValid)
                {
                    inds.AddRange(vc.indices);
                    vertexConnections.Add(vc);
                }
            }

            if (vertexConnections.Count < 1)
            {
                faces = null;
                return(false);
            }

            int              len = vertexConnections.Count;
            List <pb_Face>   successfullySplitFaces = new List <pb_Face>();
            List <pb_Face>   all_splitFaces         = new List <pb_Face>();
            List <Vector3[]> all_splitVertices      = new List <Vector3[]>();
            List <int[]>     all_splitSharedIndices = new List <int[]>();

            bool[] success = new bool[len];

            pb_IntArray[] sharedIndices = pb.sharedIndices;

            i = 0;
            foreach (VertexConnection vc in vertexConnections)
            {
                pb_Face[]   splitFaces         = null;
                Vector3[][] splitVertices      = null;
                int[][]     splitSharedIndices = null;

                if (vc.indices.Count < 3)
                {
                    int indA = vc.face.indices.IndexOf(vc.indices[0], sharedIndices);
                    int indB = vc.face.indices.IndexOf(vc.indices[1], sharedIndices);

                    if (indA < 0 || indB < 0)
                    {
                        success[i] = false;
                        continue;
                    }

                    indA = vc.face.indices[indA];
                    indB = vc.face.indices[indB];

                    success[i] = SplitFace_Internal(new SplitSelection(pb, vc.face, pb.vertices[indA], pb.vertices[indB], true, true, indA, indB),
                                                    out splitFaces,
                                                    out splitVertices,
                                                    out splitSharedIndices);

                    if (success[i])
                    {
                        successfullySplitFaces.Add(vc.face);
                    }
                }
                else
                {
                    success[i] = PokeFace_Internal(pb, vc.face, vc.indices.ToArray(),
                                                   out splitFaces,
                                                   out splitVertices,
                                                   out splitSharedIndices);

                    if (success[i])
                    {
                        successfullySplitFaces.Add(vc.face);
                    }
                }

                if (success[i])
                {
                    int texGroup = pb.UnusedTextureGroup(i + 1);

                    for (int j = 0; j < splitFaces.Length; j++)
                    {
                        splitFaces[j].textureGroup = texGroup;
                        all_splitFaces.Add(splitFaces[j]);
                        all_splitVertices.Add(splitVertices[j]);
                        all_splitSharedIndices.Add(splitSharedIndices[j]);
                    }
                }

                i++;
            }

            if (all_splitFaces.Count < 1)
            {
                faces = null;
                return(false);
            }

            pb_Face[] appendedFaces = pb.AppendFaces(all_splitVertices.ToArray(), all_splitFaces.ToArray(), all_splitSharedIndices.ToArray());
            inds.AddRange(pb_Face.AllTriangles(appendedFaces));

            pb.WeldVertices(inds.ToArray(), Mathf.Epsilon);

            pb.DeleteFaces(successfullySplitFaces.ToArray());

            faces = appendedFaces;
            return(true);
        }