⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wmlmtmesh.cpp

📁 3D Game Engine Design Source Code非常棒
💻 CPP
📖 第 1 页 / 共 2 页
字号:
            {
                MTTriangle& rkA = m_akTriangle[iA];
                rkA.ReplaceAdjacent(iTOld,iTNew);
            }
        }

        pkT = m_kTMap.find(MTITriangle(rkV0.GetLabel(),rkV1.GetLabel(),
            rkV2.GetLabel()));
        assert( pkT != m_kTMap.end() );
        pkT->second = iTNew;
    }
}
//----------------------------------------------------------------------------
void MTMesh::AttachTriangleToEdge (int iT, MTTriangle& rkT, int i, int iE,
    MTEdge& rkE)
{
    if ( rkE.Triangle(0) == -1 )
    {
        rkE.Triangle(0) = iT;
    }
    else
    {
        int iTAdj = rkE.Triangle(0);
        MTTriangle& rkTAdj = m_akTriangle[iTAdj];
        rkT.Adjacent(i) = iTAdj;
        for (int j = 0; j < 3; j++)
        {
            if ( rkTAdj.Edge(j) == iE )
            {
                rkTAdj.Adjacent(j) = iT;
                break;
            }
        }

        if ( rkE.Triangle(1) == -1 )
        {
            rkE.Triangle(1) = iT;
        }
        else
        {
            // mesh is not manifold
            assert( false );
        }
    }

    rkT.Edge(i) = iE;
}
//----------------------------------------------------------------------------
void MTMesh::DetachTriangleFromEdge (int iT, MTTriangle& rkT, int i, int iE,
    MTEdge& rkE)
{
    // This function leaves T only partially complete.  The edge E is no
    // longer referenced by T, even though the vertices of T reference the
    // end points of E.  If T has an adjacent triangle A that shares E, then
    // A is a complete triangle.

    if ( rkE.Triangle(0) == iT )
    {
        int iTAdj = rkE.Triangle(1);
        if ( iTAdj != -1 )
        {
            // T and TAdj share E, update adjacency information for both
            MTTriangle& rkTAdj = m_akTriangle[iTAdj];
            for (int j = 0; j < 3; j++)
            {
                if ( rkTAdj.Edge(j) == iE )
                {
                    rkTAdj.Adjacent(j) = -1;
                    break;
                }
            }
        }
        rkE.Triangle(0) = iTAdj;
    }
    else if ( rkE.Triangle(1) == iT )
    {
        // T and TAdj share E, update adjacency information for both
        MTTriangle& rkTAdj = m_akTriangle[rkE.Triangle(0)];
        for (int j = 0; j < 3; j++)
        {
            if ( rkTAdj.Edge(j) == iE )
            {
                rkTAdj.Adjacent(j) = -1;
                break;
            }
        }
    }
    else
    {
        // Should not get here.  The specified edge must share the input
        // triangle.
        assert( false );
    }

    rkE.Triangle(1) = -1;
    rkT.Edge(i) = -1;
    rkT.Adjacent(i) = -1;
}
//----------------------------------------------------------------------------
bool MTMesh::SubdivideCentroid (int iLabel0, int iLabel1, int iLabel2,
    int& riNextLabel)
{
    int iT = T(iLabel0,iLabel1,iLabel2);
    if ( iT == -1 )
        return false;

    if ( m_kVMap.find(MTIVertex(riNextLabel)) != m_kVMap.end() )
    {
        // vertex already exists with this label
        return false;
    }

    // subdivide the triangle
    Remove(iLabel0,iLabel1,iLabel2);
    Insert(iLabel0,iLabel1,riNextLabel);
    Insert(iLabel1,iLabel2,riNextLabel);
    Insert(iLabel2,iLabel0,riNextLabel);

    riNextLabel++;
    return true;
}
//----------------------------------------------------------------------------
bool MTMesh::SubdivideCentroidAll (int& riNextLabel)
{
    // verify that the next-label range is valid
    int iT, iTMax = m_akTriangle.GetQuantity();
    int iTempLabel = riNextLabel;
    for (iT = 0; iT < iTMax; iT++, iTempLabel++)
    {
        if ( m_kVMap.find(MTIVertex(iTempLabel)) != m_kVMap.end() )
        {
            // vertex already exists with this label
            return false;
        }
    }

    // Care must be taken when processing the triangles iteratively.  The
    // side of effect of removing the first triangle is that the last triangle
    // in the array is moved into the vacated position.  The first problem is
    // that the moved triangle will be skipped in the iteration.  The second
    // problem is that the insertions cause the triangle array to grow.  To
    // avoid skipping the moved triangle, a different algorithm than the one
    // in SubdivideCentroid(int,int,int,int&) is used.  The triangle to be
    // removed is detached from two edges.  Two of the subtriangles are added
    // to the mesh.  The third subtriangle is calculated in the already
    // existing memory that stored the original triangle.  To avoid the
    // infinite recursion induced by a growing array, the original size of
    // the triangle array is stored int iTMax.  This guarantees that only the
    // original triangles are subdivided and that newly added triangles are
    // not.
    for (iT = 0; iT < iTMax; iT++, riNextLabel++)
    {
        // the triangle to subdivide
        MTTriangle& rkT = m_akTriangle[iT];
        int iLabel0 = GetVLabel(rkT.Vertex(0));
        int iLabel1 = GetVLabel(rkT.Vertex(1));
        int iLabel2 = GetVLabel(rkT.Vertex(2));

        // detach the triangle from two edges
        int iE1 = rkT.Edge(1), iE2 = rkT.Edge(2);
        MTEdge& rkE1 = m_akEdge[iE1];
        MTEdge& rkE2 = m_akEdge[iE2];
        DetachTriangleFromEdge(iT,rkT,1,iE1,rkE1);
        DetachTriangleFromEdge(iT,rkT,2,iE2,rkE2);

        // Insert the two subtriangles that share edges E1 and E2.  A
        // potential side effect is that the triangle array is reallocated
        // to make room for the new triangles.  This will invalidate the
        // reference rkT from the code above, but the index iT into the array
        // is still correct.  A reallocation of the vertex array might also
        // occur.
        Insert(iLabel1,iLabel2,riNextLabel);
        Insert(iLabel2,iLabel0,riNextLabel);

        // stitch the third subtriangle to the other subtriangles.
        MTTriangle& rkTN = m_akTriangle[iT];
        int iSubE1 = E(iLabel1,riNextLabel);
        int iSubE2 = E(iLabel0,riNextLabel);
        MTEdge& rkSubE1 = m_akEdge[iSubE1];
        MTEdge& rkSubE2 = m_akEdge[iSubE2];
        AttachTriangleToEdge(iT,rkTN,1,iSubE1,rkSubE1);
        AttachTriangleToEdge(iT,rkTN,2,iSubE2,rkSubE2);
    }

    return true;
}
//----------------------------------------------------------------------------
bool MTMesh::SubdivideEdge (int iLabel0, int iLabel1, int& riNextLabel)
{
    int iE = E(iLabel0,iLabel1);
    if ( iE == -1 )
        return false;

    if ( m_kVMap.find(MTIVertex(riNextLabel)) != m_kVMap.end() )
    {
        // vertex already exists with this label
        return false;
    }

    // split the triangles sharing the edge
    MTEdge& rkE = m_akEdge[iE];
    int iT0 = rkE.Triangle(0), iT1 = rkE.Triangle(1);
    int iT0L0, iT0L1, iT0L2, iT1L0, iT1L1, iT1L2;
    int iT0E0, iT0E1, iT1E0, iT1E1;
    if ( iT0 >= 0 && iT1 == -1 )
    {
        // edge shared by only T0
        MTTriangle& rkT0 = m_akTriangle[iT0];
        iT0L0 = GetVLabel(rkT0.Vertex(0));
        iT0L1 = GetVLabel(rkT0.Vertex(1));
        iT0L2 = GetVLabel(rkT0.Vertex(2));
        iT0E0 = rkT0.Edge(0);
        iT0E1 = rkT0.Edge(1);

        Remove(iT0L0,iT0L1,iT0L2);
        if ( iT0E0 == iE )
        {
            Insert(iT0L0,riNextLabel,iT0L2);
            Insert(riNextLabel,iT0L1,iT0L2);
        }
        else if ( iT0E1 == iE )
        {
            Insert(iT0L1,riNextLabel,iT0L0);
            Insert(riNextLabel,iT0L2,iT0L0);
        }
        else
        {
            Insert(iT0L2,riNextLabel,iT0L1);
            Insert(riNextLabel,iT0L0,iT0L1);
        }
    }
    else if ( iT1 >= 0 && iT0 == -1 )
    {
        // Edge shared by only T1.  The Remove(int,int,int) call is not
        // factored outside the conditional statements to avoid potential
        // reallocation side effects that would invalidate the reference rkT1.
        MTTriangle& rkT1 = m_akTriangle[iT1];
        iT1L0 = GetVLabel(rkT1.Vertex(0));
        iT1L1 = GetVLabel(rkT1.Vertex(1));
        iT1L2 = GetVLabel(rkT1.Vertex(2));
        iT1E0 = rkT1.Edge(0);
        iT1E1 = rkT1.Edge(1);

        Remove(iT1L0,iT1L1,iT1L2);
        if ( iT1E0 == iE )
        {
            Insert(iT1L0,riNextLabel,iT1L2);
            Insert(riNextLabel,iT1L1,iT1L2);
        }
        else if ( iT1E1 == iE )
        {
            Insert(iT1L1,riNextLabel,iT1L0);
            Insert(riNextLabel,iT1L2,iT1L0);
        }
        else
        {
            Insert(iT1L2,riNextLabel,iT1L1);
            Insert(riNextLabel,iT1L0,iT1L1);
        }
    }
    else
    {
        assert( iT0 >= 0 && iT1 >= 0 );

        // Edge shared by both T0 and T1.  The Remove(int,int,int) call is not
        // factored outside the conditional statements to avoid potential
        // reallocation side effects that would invalidate the references
        // rkT0 and rkT1.
        MTTriangle& rkT0 = m_akTriangle[iT0];
        iT0L0 = GetVLabel(rkT0.Vertex(0));
        iT0L1 = GetVLabel(rkT0.Vertex(1));
        iT0L2 = GetVLabel(rkT0.Vertex(2));
        iT0E0 = rkT0.Edge(0);
        iT0E1 = rkT0.Edge(1);

        MTTriangle& rkT1 = m_akTriangle[iT1];
        iT1L0 = GetVLabel(rkT1.Vertex(0));
        iT1L1 = GetVLabel(rkT1.Vertex(1));
        iT1L2 = GetVLabel(rkT1.Vertex(2));
        iT1E0 = rkT1.Edge(0);
        iT1E1 = rkT1.Edge(1);

        // Both triangles must be removed before the insertions to guarantee
        // that the common edge is deleted from the mesh first.
        Remove(iT0L0,iT0L1,iT0L2);
        Remove(iT1L0,iT1L1,iT1L2);

        if ( iT0E0 == iE )
        {
            Insert(iT0L0,riNextLabel,iT0L2);
            Insert(riNextLabel,iT0L1,iT0L2);
        }
        else if ( iT0E1 == iE )
        {
            Insert(iT0L1,riNextLabel,iT0L0);
            Insert(riNextLabel,iT0L2,iT0L0);
        }
        else
        {
            Insert(iT0L2,riNextLabel,iT0L1);
            Insert(riNextLabel,iT0L0,iT0L1);
        }

        if ( iT1E0 == iE )
        {
            Insert(iT1L0,riNextLabel,iT1L2);
            Insert(riNextLabel,iT1L1,iT1L2);
        }
        else if ( iT1E1 == iE )
        {
            Insert(iT1L1,riNextLabel,iT1L0);
            Insert(riNextLabel,iT1L2,iT1L0);
        }
        else
        {
            Insert(iT1L2,riNextLabel,iT1L1);
            Insert(riNextLabel,iT1L0,iT1L1);
        }
    }

    riNextLabel++;
    return true;
}
//----------------------------------------------------------------------------
void MTMesh::Print (ofstream& rkOStr) const
{
    int i;

    // print vertices
    rkOStr << "vertex quantity = " << m_akVertex.GetQuantity() << endl;
    for (int iV = 0; iV < m_akVertex.GetQuantity(); iV++)
    {
        const MTVertex& rkV = m_akVertex.Get(iV);

        rkOStr << "vertex<" << iV << ">" << endl;
        rkOStr << "    l: " << rkV.GetLabel() << endl;
        rkOStr << "    e: ";
        for (i = 0; i < rkV.GetEdgeQuantity(); i++)
            rkOStr << rkV.GetEdge(i) << ' ';
        rkOStr << endl;
        rkOStr << "    t: ";
        for (i = 0; i < rkV.GetTriangleQuantity(); i++)
            rkOStr << rkV.GetTriangle(i) << ' ';
        rkOStr << endl;
    }
    rkOStr << endl;

    // print edges
    rkOStr << "edge quantity = " << m_akEdge.GetQuantity() << endl;
    for (int iE = 0; iE < m_akEdge.GetQuantity(); iE++)
    {
        const MTEdge& rkE = m_akEdge.Get(iE);

        rkOStr << "edge<" << iE << ">" << endl;
        rkOStr << "    v: "
              << rkE.GetVertex(0) << ' '
              << rkE.GetVertex(1) << endl;
        rkOStr << "    t: " << rkE.GetTriangle(0) << ' ' << rkE.GetTriangle(1)
              << endl;
    }
    rkOStr << endl;

    // print triangles
    rkOStr << "triangle quantity = " << m_akTriangle.GetQuantity() << endl;
    for (int iT = 0; iT < m_akTriangle.GetQuantity(); iT++)
    {
        const MTTriangle& rkT = m_akTriangle.Get(iT);

        rkOStr << "triangle<" << iT << ">" << endl;
        rkOStr << "    v: "
              << rkT.GetVertex(0) << ' '
              << rkT.GetVertex(1) << ' '
              << rkT.GetVertex(2) << endl;
        rkOStr << "    e: " << rkT.GetEdge(0) << ' ' << rkT.GetEdge(1)
              << ' ' << rkT.GetEdge(2) << endl;
        rkOStr << "    a: " << rkT.GetAdjacent(0) << ' ' << rkT.GetAdjacent(1)
              << ' ' << rkT.GetAdjacent(2) << endl;
    }
    rkOStr << endl;
}
//----------------------------------------------------------------------------
bool MTMesh::Print (const char* acFilename) const
{
    ofstream kOStr(acFilename);
    if ( !kOStr )
        return false;

    Print(kOStr);
    return true;
}
//----------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -