Exemplo n.º 1
0
        public TriangleStripper(ModelBase.FaceListDef faceList)
        {
            if (faceList.m_Type != ModelBase.PolyListType.Triangles)
            {
                bool tris = true;
                for (int i = 0; i < faceList.m_Faces.Count; i++)
                {
                    tris = (faceList.m_Faces[i].m_NumVertices == 3);
                    if (!tris)
                    {
                        throw new ArgumentException("The provided FaceListDef must be triangulated.");
                    }
                }
                faceList.m_Type = ModelBase.PolyListType.Triangles;
            }

            m_Vertices           = new List <VertexLinked>();
            m_Triangles          = new List <TriangleLinked>();
            m_TrianglesToProcess = new List <TriangleLinked>();

            for (int i = 0; i < faceList.m_Faces.Count; i++)
            {
                if (IsDegenerateFace(faceList.m_Faces[i]))
                {
                    faceList.m_Faces.RemoveAt(i);
                }
            }

            for (int i = 0; i < faceList.m_Faces.Count; i++)
            {
                m_Triangles.Add(new TriangleLinked(faceList.m_Faces[i]));
            }

            for (int i = 0; i < m_Triangles.Count; i++)
            {
                ModelBase.FaceDef triangle = m_Triangles[i].m_Triangle;

                for (int j = 0; j < triangle.m_NumVertices; j++)
                {
                    VertexLinked vertex = new VertexLinked(triangle.m_Vertices[j]);

                    int index = m_Vertices.IndexOf(vertex);
                    if (index == -1)
                    {
                        m_Vertices.Add(vertex);
                        index = m_Vertices.Count - 1;
                    }

                    m_Vertices[index].m_LinkedTriangles.Add(i);
                }
            }
        }
Exemplo n.º 2
0
        Tuple <ModelBase.FaceListDef, List <int> > GetStripAndIndicesForStartingEvenEdge(
            TriangleLinked start, TriangleEdge startForwardEdge)
        {
            List <int> stripIndices = new List <int>();
            List <TriangleRotation> stripRotations = new List <TriangleRotation>();

            List <TriangleLinked> linked        = GetLinked(start)[(int)startForwardEdge];
            TriangleLinked        bestNeighbour = DetermineBestNextNeighbour(start, linked, startForwardEdge);

            if (bestNeighbour == null)
            {
                return(new Tuple <ModelBase.FaceListDef, List <int> >(new ModelBase.FaceListDef(), new List <int>()));
            }

            TriangleRotation startRotation = (TriangleRotation)((int)(startForwardEdge - TriangleEdge.Edge_BC + 3) % 3);

            TriangleLinked   t               = start;
            TriangleEdge     currentEdge     = startForwardEdge;
            TriangleRotation currentRotation = startRotation;
            bool             even            = true;
            int index_t = -1;

            while (t != null && !stripIndices.Contains((index_t = m_Triangles.IndexOf(t))))
            {
                stripIndices.Add(index_t);
                stripRotations.Add(currentRotation);

                linked        = GetLinked(t)[(int)currentEdge];
                bestNeighbour = DetermineBestNextNeighbour(t, linked, currentEdge);

                t = bestNeighbour;

                even = !even;

                if (t != null)
                {
                    // Determine rotation and the edge to be used to get the next face

                    ModelBase.FaceDef triangleC_CW = new ModelBase.FaceDef(3);
                    if (even)
                    {
                        triangleC_CW.m_Vertices[0] = t.m_Triangle.m_Vertices[0];
                        triangleC_CW.m_Vertices[1] = t.m_Triangle.m_Vertices[1];
                        triangleC_CW.m_Vertices[2] = t.m_Triangle.m_Vertices[2];
                    }
                    else
                    {
                        triangleC_CW.m_Vertices[0] = t.m_Triangle.m_Vertices[2];
                        triangleC_CW.m_Vertices[1] = t.m_Triangle.m_Vertices[1];
                        triangleC_CW.m_Vertices[2] = t.m_Triangle.m_Vertices[0];
                    }

                    // The edge of the vertices which match the preceding triangle's
                    TriangleEdge linkBackEdge = TriangleEdge.Edge_AB;
                    // The vertices which match the preceding triangle's
                    ModelBase.VertexDef[] currentMatchedEdge = new ModelBase.VertexDef[2];
                    TriangleLinked        previous           = m_Triangles[stripIndices[stripIndices.Count - 1]];
                    currentMatchedEdge[0] = previous.m_Triangle.m_Vertices[(int)(currentEdge + 0) % 3];
                    currentMatchedEdge[1] = previous.m_Triangle.m_Vertices[(int)(currentEdge + 1) % 3];
                    // Find the edge in the current triangle which if odd has been made CW which matches
                    // that from the preceding triangle. This will be set as the current triangle's first,
                    // or 'AB' edge and the next edge (next two vertices) will be used to match the next
                    // triangle.
                    for (int i = 0; i < 3; i++)
                    {
                        ModelBase.VertexDef[] edge = new ModelBase.VertexDef[2];
                        edge[0] = triangleC_CW.m_Vertices[(i + 0) % 3];
                        edge[1] = triangleC_CW.m_Vertices[(i + 1) % 3];
                        if (edge.Except(currentMatchedEdge).Count() == 0)
                        {
                            linkBackEdge = (TriangleEdge)i;
                            break;
                        }
                    }

                    TriangleEdge nextEdgeNoC_CW = (TriangleEdge)((int)(linkBackEdge + 1) % 3);

                    TriangleEdge nextEdge = nextEdgeNoC_CW;
                    if (!even)
                    {
                        // If odd, nextEdgeNoC_CW points to the edge to be used if written CW, however
                        // all triangles have been read in as CCW so need to get the corresponding edge
                        // in CCW version.
                        ModelBase.VertexDef[] nextEdgeNoC_CW_Vertices = new ModelBase.VertexDef[2];
                        nextEdgeNoC_CW_Vertices[0] = triangleC_CW.m_Vertices[(int)(nextEdgeNoC_CW + 0) % 3];
                        nextEdgeNoC_CW_Vertices[1] = triangleC_CW.m_Vertices[(int)(nextEdgeNoC_CW + 1) % 3];
                        for (int i = 0; i < 3; i++)
                        {
                            ModelBase.VertexDef[] ccwEdge = new ModelBase.VertexDef[2];
                            ccwEdge[0] = t.m_Triangle.m_Vertices[(i + 0) % 3];
                            ccwEdge[1] = t.m_Triangle.m_Vertices[(i + 1) % 3];
                            if (nextEdgeNoC_CW_Vertices.Except(ccwEdge).Count() == 0)
                            {
                                nextEdge = (TriangleEdge)i;
                                break;
                            }
                        }
                    }

                    // Now we need to determine the required rotation of the current triangle so that for
                    // even triangles the new vertex in at index 0 and for odd triangles it occurs at
                    // index 2.
                    ModelBase.VertexDef uniqueVertex  = t.m_Triangle.m_Vertices.Except(previous.m_Triangle.m_Vertices).ElementAt(0);
                    int uniqueVertexIndex             = Array.IndexOf(t.m_Triangle.m_Vertices, uniqueVertex);
                    TriangleRotation requiredRotation =
                        (even) ? (TriangleRotation)((uniqueVertexIndex - 2 + 3) % 3) :
                        (TriangleRotation)(uniqueVertexIndex);

                    currentRotation = requiredRotation;
                    currentEdge     = nextEdge;

                    // To best understand how this works, debug and step-through how the following model is handled:
                    //
                    // An example:
                    // Faces as defined in model (all Counter-Clockwise (CCW)):
                    // f 1 2 3
                    // f 4 1 3
                    // f 4 5 1
                    // Build strip from edge CA.
                    // # 2 3 1 (LS)      <- Need to Left Shift vertices so that CA is the second edge (in a tri. strip it's
                    //                      always the second edge that's shared - see diagram at top).
                    // #   3 1 4 (4 1 3) <- For odd faces the new vertex must be at index [0]
                    //                      No Rot required, link-back CW: AB, CW forward: AB + 1 = BC,
                    //                      CCW forward: edge in CCW that contains vertices in (CW forward) = AB
                    //                      The next triangle is the one that shares the CCW edge AB (vertices 1 and 4)
                    // #     1 4 5 (RS)  <- Even face the new vertex needs to be in index [2] so need to Right Shift vertices
                    //                      Repeat steps as for above face but don't need to worry about converting between CCW and CW order
                }
            }

            ModelBase.FaceListDef tStrip = new ModelBase.FaceListDef(ModelBase.PolyListType.TriangleStrip);

            for (int i = 0; i < stripIndices.Count; i++)
            {
                TriangleRotation requiredRotation = (TriangleRotation)stripRotations[i];

                ModelBase.FaceDef rotated = new ModelBase.FaceDef(3);
                rotated.m_Vertices[0] = m_Triangles[stripIndices[i]].m_Triangle.m_Vertices[((int)(0 + requiredRotation) % 3)];
                rotated.m_Vertices[1] = m_Triangles[stripIndices[i]].m_Triangle.m_Vertices[((int)(1 + requiredRotation) % 3)];
                rotated.m_Vertices[2] = m_Triangles[stripIndices[i]].m_Triangle.m_Vertices[((int)(2 + requiredRotation) % 3)];

                tStrip.m_Faces.Add(rotated);
            }

            return(new Tuple <ModelBase.FaceListDef, List <int> >(tStrip, stripIndices));
        }
Exemplo n.º 3
0
 // Return true if two of a triangle's vertices are the same
 private bool IsDegenerateFace(ModelBase.FaceDef triangle)
 {
     return(triangle.m_Vertices.ToList().Except(triangle.m_Vertices.ToList()).Count() != 0);
 }