예제 #1
0
        void _markGroupFaceNeightbours(int vertexIndex, int faceIndex, ref List <int>[] faceLinkedEdges, int groupIndex)
        {
            Stack <int> stack = new Stack <int>();

            stack.Push(faceIndex);
            do
            {
                faceIndex = stack.Pop();
                Face f = faces[faceIndex];
                if (f.mark == -1)
                {
                    f.mark = groupIndex;                     // mark face group. -1 = available
                    // locate neighbours connected by non-creases
                    List <int> faceEdges = faceLinkedEdges[faceIndex];
                    // Search for other faces connected with non-crease edges
                    for (int e = 0; e < faceEdges.Count; ++e)
                    {
                        Edge edge = edges[faceEdges[e]];
                        if (IsEdgeValid(faceEdges[e]) && edge.crease < 1.0f && edge.ContainsVertex(vertexIndex))
                        {
                            IndexList edgeFaces = edge.linkedFaces;
                            for (int k = 0; k < edgeFaces.Count; ++k)
                            {
                                int edgeFaceIndex = edgeFaces[k];
                                if (faces[edgeFaceIndex].mark == -1)
                                {
                                    stack.Push(edgeFaceIndex);
                                }
                            }
                        }
                    }
                }
            } while (stack.Count > 0);
        }
예제 #2
0
        // Dissolve an edge between two triangles.
        // the first is a quad afterwards and the second triangle is destroyed
        // expects valid input, no checks!
        public void DissolveEdgeTriangles(int edgeIndex)
        {
            int i;

            Edge e = edges[edgeIndex];
            // e needs to have two linked faces
            int  f1index = e.linkedFaces[0];
            int  f2index = e.linkedFaces[1];
            Face f1      = faces[f1index];
            Face f2      = faces[f2index];
            // f1 and f2 have two common vertices, need to be triangles
            int v2uniqueCorner = -1;

            for (i = 0; i < 3; ++i)
            {
                if (e.ContainsVertex(f2.v[i]) == false)
                {
                    v2uniqueCorner = i;
                    break;
                }
            }
            for (i = 0; i < 3; ++i)
            {
                if (e.ContainsVertex(f1.v[i]) == false)
                {
                    int insertPos = i + 2;
                    if (insertPos >= 3)
                    {
                        insertPos -= 3;
                    }

                    f1.cornerCount = 4;                     // f1 is now a quad
                    UnlinkFace(f2index);
                    vertices[f2.v[v2uniqueCorner]].linkedFaces.Add(f1index);
                    // Move verts backwards
                    for (int j = 3; j > insertPos; --j)
                    {
                        f1.CopyVertexInfoFromFace(f1, j - 1, j);
                    }
                    f1.CopyVertexInfoFromFace(f2, v2uniqueCorner, insertPos);
                    e.linkedFaces.Clear();
                    break;
                }
            }
        }
예제 #3
0
        // TrisToQuads. Needs mesh with edgelist
        /// <summary>
        /// Joins neighbour triangles to quads in a mesh by dissolving selected edges.
        /// This method needs the mesh to have its edges calculated. The edges are sorted
        /// by their angles and dissolved in order until the maximum edge angle is reached.
        /// Special edges such as uv borders or material seams are not dissolved and concave quads
        /// are avoided. This method is used by the quad-based subdivision algorithm as it works
        /// much better with quads.
        /// </summary>
        /// <param name='mesh'>
        /// The mesh to process.
        /// </param>
        /// <param name='maximumEdgeAngle'>
        /// The maximum angle between two triangles to be joined to a (non-planar) quad.
        /// </param>
        public static void TrisToQuads(MeshEdges mesh, float maximumEdgeAngle)
        {
            if (mesh.topology != MeshTopology.Triangles)
            {
                return;
            }
            int i, j;

            mesh.topology = MeshTopology.Mixed;             // Most likely we'll end up with a mixed topology as some triangles will be left.
            mesh.CalculateFaceNormals();
            mesh.CalculateEdgeLinkedFaces();
            // Calculate the edge angles and compile list of 2-face edges
            int         numEdges   = mesh.edgeCount();
            List <Edge> inneredges = new List <Edge>();

            for (i = 0; i < numEdges; ++i)
            {
                Edge e = mesh.edges[i]
                ;
                if (e.linkedFaces.Count == 2 && mesh.CanEdgeBeDissolved(i))
                {
                    e.mark  = i;                    // Save the index!
                    e.angle = mesh.CalculateEdgeAngle(i);
                    if (e.angle < maximumEdgeAngle)
                    {
                        inneredges.Add(e);
                    }
                }
            }
            // Sort by angle
            inneredges.Sort(delegate(Edge a, Edge b) { return(a.angle.CompareTo(b.angle)); });

            int iecount = inneredges.Count;

            //		Debug.Log("Number of inneredges " + iecount);
            Vector3[] qVec = new Vector3[5];
            for (i = 0; i < iecount; ++i)
            {
                Edge e = inneredges[i];

                Face f1 = mesh.faces[e.linkedFaces[0]];
                Face f2 = mesh.faces[e.linkedFaces[1]];

                // check if edge is between two triangles
                if (f1.valid && f2.valid && (f1.cornerCount == 3) && (f2.cornerCount == 3))
                {
                    // Make sure this doesn't lead to a concave quad
                    Vector3 newNormal = f1.normal + f2.normal;
                    //newNormal.Normalize();
                    // Collect all vertex coordinates
                    qVec[0] = mesh.vertices[e.v[0]].coords;
                    qVec[2] = mesh.vertices[e.v[1]].coords;
                    for (j = 0; j < 3; ++j)
                    {
                        if (e.ContainsVertex(f1.v[j]) == false)
                        {
                            qVec[1] = mesh.vertices[f1.v[j]].coords;
                            break;
                        }
                    }
                    for (j = 0; j < 3; ++j)
                    {
                        if (e.ContainsVertex(f2.v[j]) == false)
                        {
                            qVec[3] = mesh.vertices[f2.v[j]].coords;
                            break;
                        }
                    }
                    // Flip order if it doesn't conform to f1
                    if (f1.VerticesInOrder(e.v[0], e.v[1]) == true)
                    {
                        Vector3 temp = qVec[1]; qVec[1] = qVec[3]; qVec[3] = temp;
                    }
                    // calculate edge vectors
                    qVec[4] = qVec[0];
                    for (j = 0; j < 4; ++j)
                    {
                        qVec[j] -= qVec[j + 1];
                    }
                    qVec[4] = qVec[0];

                    bool convex = true;
                    for (j = 0; j < 4; ++j)
                    {
                        Vector3 localN = Vector3.Cross(qVec[j], qVec[j + 1]);
                        //localN.Normalize();
                        float nAngleCos = Vector3.Dot(newNormal, localN);
                        //Debug.Log("Angle " + nAngleCod);
                        if (nAngleCos <= 0.0f)
                        {
                            convex = false;
                            break;
                        }
                    }

                    if (convex)
                    {
                        //				Debug.Log("Dissolving edge");
                        mesh.DissolveEdgeTriangles(e.mark);
                    }
                    else
                    {
                        //		Debug.Log("not dissolving edge -> concave quad");
                    }
                }
            }

            // There are now invalid faces and edges
            mesh.RebuildMesh();
            mesh.GenerateEdgeTopology();
        }