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

📄 wmlvetmesh.cpp

📁 3D Game Engine Design Source Code非常棒
💻 CPP
📖 第 1 页 / 共 2 页
字号:
            const SmallSet<Triangle>& rkTSet = pkE->second.m_kTSet;
            for (int j = 0; j < rkTSet.GetSize(); j++)
            {
                const Triangle& rkTAdj = rkTSet[j];
                pkVI = kVisitedMap.find(rkTAdj);
                assert( pkVI != kVisitedMap.end() );
                if ( pkVI->second == false )
                {
                    // this adjacent triangle not yet visited
                    kStack.push(rkTAdj);
                    pkVI->second = true;
                    iTSize--;
                }
            }
        }
    }

    return iTSize == 0;
}
//----------------------------------------------------------------------------
void VETMesh::GetComponents (vector<VETMesh*>& rkComponents)
{
    // Do a depth-first search of the mesh to find connected components.
    int iTSize = (int)m_kTMap.size();
    if ( iTSize == 0 )
        return;

    // for marking visited triangles during the traversal
    map<Triangle,bool> kVisitedMap;
    MTCIter pkT;
    for (pkT = m_kTMap.begin(); pkT != m_kTMap.end(); pkT++)
        kVisitedMap.insert(make_pair(pkT->first,false));

    while ( iTSize > 0 )
    {
        // find an unvisited triangle in the mesh
        stack<Triangle> kStack;
        map<Triangle,bool>::iterator pkVI = kVisitedMap.begin();
        while ( pkVI != kVisitedMap.end() )
        {
            if ( pkVI->second == false )
            {
                kStack.push(pkVI->first);
                pkVI->second = true;
                iTSize--;
                break;
            }
            pkVI++;
        }

        // traverse the connected component of the starting triangle
        VETMesh* pkComponent = Create();
        while ( !kStack.empty() )
        {
            // start at the current triangle
            Triangle kT = kStack.top();
            kStack.pop();
            pkComponent->InsertTriangle(kT);

            for (int i = 0; i < 3; i++)
            {
                // get an edge of the current triangle
                Edge kE(kT.m_aiV[i],kT.m_aiV[(i+1)%3]);
                MECIter pkE = m_kEMap.find(kE);

                // visit each adjacent triangle
                const SmallSet<Triangle>& rkTSet = pkE->second.m_kTSet;
                for (int j = 0; j < rkTSet.GetSize(); j++)
                {
                    const Triangle& rkTAdj = rkTSet[i];
                    pkVI = kVisitedMap.find(rkTAdj);
                    assert( pkVI != kVisitedMap.end() );
                    if ( pkVI->second == false )
                    {
                        // this adjacent triangle not yet visited
                        kStack.push(rkTAdj);
                        pkVI->second = true;
                        iTSize--;
                    }
                }
            }
        }
        rkComponents.push_back(pkComponent);
    }
}
//----------------------------------------------------------------------------
void VETMesh::GetComponents (vector<int>& rkIndex, int*& raiConnect)
{
    rkIndex.clear();

    // Do a depth-first search of the mesh to find connected components.
    int iTSize = (int)m_kTMap.size();
    if ( iTSize == 0 )
    {
        raiConnect = NULL;
        return;
    }

    int iIQuantity = 3*iTSize;
    int iIndex = 0;
    raiConnect = new int[iIQuantity];

    // for marking visited triangles during the traversal
    map<Triangle,bool> kVisitedMap;
    MTCIter pkT;
    for (pkT = m_kTMap.begin(); pkT != m_kTMap.end(); pkT++)
        kVisitedMap.insert(make_pair(pkT->first,false));

    while ( iTSize > 0 )
    {
        // find an unvisited triangle in the mesh
        stack<Triangle> kStack;
        map<Triangle,bool>::iterator pkVI = kVisitedMap.begin();
        while ( pkVI != kVisitedMap.end() )
        {
            if ( pkVI->second == false )
            {
                kStack.push(pkVI->first);
                pkVI->second = true;
                iTSize--;
                break;
            }
            pkVI++;
        }

        // traverse the connected component of the starting triangle
        VETMesh* pkComponent = Create();
        while ( !kStack.empty() )
        {
            // start at the current triangle
            Triangle kT = kStack.top();
            kStack.pop();
            pkComponent->InsertTriangle(kT);

            for (int i = 0; i < 3; i++)
            {
                // get an edge of the current triangle
                Edge kE(kT.m_aiV[i],kT.m_aiV[(i+1)%3]);
                MECIter pkE = m_kEMap.find(kE);

                // visit each adjacent triangle
                const SmallSet<Triangle>& rkTSet = pkE->second.m_kTSet;
                for (int j = 0; j < rkTSet.GetSize(); j++)
                {
                    const Triangle& rkTAdj = rkTSet[i];
                    pkVI = kVisitedMap.find(rkTAdj);
                    assert( pkVI != kVisitedMap.end() );
                    if ( pkVI->second == false )
                    {
                        // this adjacent triangle not yet visited
                        kStack.push(rkTAdj);
                        pkVI->second = true;
                        iTSize--;
                    }
                }
            }
        }

        // store the connectivity information for this component
        set<Triangle> kTSet;
        pkComponent->GetTriangles(kTSet);
        delete pkComponent;

        rkIndex.push_back(iIndex);
        set<Triangle>::iterator pkTIter;
        for (pkTIter = kTSet.begin(); pkTIter != kTSet.end(); pkTIter++)
        {
            assert( iIndex+3 <= iIQuantity );
            const Triangle& rkT = *pkTIter;
            raiConnect[iIndex++] = rkT.m_aiV[0];
            raiConnect[iIndex++] = rkT.m_aiV[1];
            raiConnect[iIndex++] = rkT.m_aiV[2];
        }

    }
    
    rkIndex.push_back(iIQuantity);
}
//----------------------------------------------------------------------------
void VETMesh::RemoveComponent (int& riIQuantity, int* aiConnect)
{
    // Do a depth-first search of the mesh to find connected components.  The
    // input array is assumed to be large enough to hold the component (see
    // the comments in WmlTriangleMesh.h for RemoveComponent).
    riIQuantity = 0;

    int iTSize = (int)m_kTMap.size();
    if ( iTSize == 0 )
        return;

    // Find the connected component containing the first triangle in the mesh.
    // A set is used instead of a stack to avoid having a large-memory
    // 'visited' map.
    set<Triangle> kVisited;
    kVisited.insert(m_kTMap.begin()->first);

    // traverse the connected component
    while ( !kVisited.empty() )
    {
        // start at the current triangle
        Triangle kT = *kVisited.begin();

        // add adjacent triangles to the set for recursive processing
        for (int i = 0; i < 3; i++)
        {
            // get an edge of the current triangle
            Edge kE(kT.m_aiV[i],kT.m_aiV[(i+1)%3]);
            MECIter pkE = m_kEMap.find(kE);
            assert( pkE != m_kEMap.end() );

            // visit each adjacent triangle
            const SmallSet<Triangle>& rkTSet = pkE->second.m_kTSet;
            for (int j = 0; j < rkTSet.GetSize(); j++)
            {
                Triangle kTAdj = rkTSet[j];
                if ( kTAdj != kT )
                    kVisited.insert(kTAdj);
            }
        }

        // add triangle to connectivity array
        aiConnect[riIQuantity++] = kT.m_aiV[0];
        aiConnect[riIQuantity++] = kT.m_aiV[1];
        aiConnect[riIQuantity++] = kT.m_aiV[2];

        // remove the current triangle (visited, no longer needed)
        kVisited.erase(kT);
        RemoveTriangle(kT);
    }
}
//----------------------------------------------------------------------------
bool VETMesh::GetConsistentComponents (vector<VETMesh*>& rkComponents)
{
    if ( !IsManifold() )
        return false;

    // Do a depth-first search of the mesh to find connected components.
    int iTSize = (int)m_kTMap.size();
    if ( iTSize == 0 )
        return true;

    // for marking visited triangles during the traversal
    map<Triangle,bool> kVisitedMap;
    MTCIter pkT;
    for (pkT = m_kTMap.begin(); pkT != m_kTMap.end(); pkT++)
        kVisitedMap.insert(make_pair(pkT->first,false));

    while ( iTSize > 0 )
    {
        // Find an unvisited triangle in the mesh.  Any triangle pushed onto
        // the stack is considered to have a consistent ordering.
        stack<Triangle> kStack;
        map<Triangle,bool>::iterator pkVI = kVisitedMap.begin();
        while ( pkVI != kVisitedMap.end() )
        {
            if ( pkVI->second == false )
            {
                kStack.push(pkVI->first);
                pkVI->second = true;
                iTSize--;
                break;
            }
            pkVI++;
        }

        // traverse the connected component of the starting triangle
        VETMesh* pkComponent = Create();
        while ( !kStack.empty() )
        {
            // start at the current triangle
            Triangle kT = kStack.top();
            kStack.pop();
            pkComponent->InsertTriangle(kT);

            for (int i = 0; i < 3; i++)
            {
                // get an edge of the current triangle
                int iV0 = kT.m_aiV[i], iV1 = kT.m_aiV[(i+1)%3], iV2;
                Edge kE(iV0,iV1);
                MECIter pkE = m_kEMap.find(kE);

                int iSize = pkE->second.m_kTSet.GetSize();
                assert( iSize == 1 || iSize == 2 );  // mesh is manifold
                const Triangle* pkTAdj = &pkE->second.m_kTSet[0];
                if ( iSize == 2 )
                {
                    // get the adjacent triangle to the current one
                    if ( *pkTAdj == kT )
                        pkTAdj = &pkE->second.m_kTSet[1];

                    pkVI = kVisitedMap.find(*pkTAdj);
                    assert( pkVI != kVisitedMap.end() );
                    if ( pkVI->second == false )
                    {
                        // adjacent triangle not yet visited
                        if ((pkTAdj->m_aiV[0]==iV0 && pkTAdj->m_aiV[1]==iV1)
                        ||  (pkTAdj->m_aiV[1]==iV0 && pkTAdj->m_aiV[2]==iV1)
                        ||  (pkTAdj->m_aiV[2]==iV0 && pkTAdj->m_aiV[0]==iV1))
                        {
                            // adjacent triangle must be reordered
                            iV0 = pkTAdj->m_aiV[0];
                            iV1 = pkTAdj->m_aiV[1];
                            iV2 = pkTAdj->m_aiV[2];
                            kVisitedMap.erase(*pkTAdj);
                            RemoveTriangle(iV0,iV1,iV2);
                            InsertTriangle(iV1,iV0,iV2);
                            kVisitedMap.insert(make_pair(Triangle(iV1,iV0,
                                iV2),false));

                            // refresh the iterators since maps changed
                            pkE = m_kEMap.find(kE);
                            pkTAdj = &pkE->second.m_kTSet[0];
                            if ( *pkTAdj == kT )
                                pkTAdj = &pkE->second.m_kTSet[1];
                            pkVI = kVisitedMap.find(*pkTAdj);
                            assert( pkVI != kVisitedMap.end() );
                        }

                        kStack.push(*pkTAdj);
                        pkVI->second = true;
                        iTSize--;
                    }
                }
            }
        }
        rkComponents.push_back(pkComponent);
    }

    return true;
}
//----------------------------------------------------------------------------
VETMesh* VETMesh::GetReversedOrderMesh () const
{
    VETMesh* pkReversed = Create();

    for (MTCIter pkT = m_kTMap.begin(); pkT != m_kTMap.end(); pkT++)
    {
        pkReversed->InsertTriangle(pkT->first.m_aiV[0],pkT->first.m_aiV[2],
            pkT->first.m_aiV[1]);
    }

    return pkReversed;
}
//----------------------------------------------------------------------------
void VETMesh::GetStatistics (int& riVQuantity, int& riEQuantity,
    int& riTQuantity, float& rfAverageEdgesPerVertex,
    float& rfAverageTrianglesPerVertex, float& rfAverageTrianglesPerEdge,
    int& riMaximumEdgesPerVertex, int& riMaximumTrianglesPerVertex,
    int& riMaximumTrianglesPerEdge)
{
    riVQuantity = (int)m_kVMap.size();
    riEQuantity = (int)m_kEMap.size();
    riTQuantity = (int)m_kTMap.size();

    int iESumForV = 0;
    int iTSumForV = 0;
    riMaximumEdgesPerVertex = 0;
    riMaximumTrianglesPerVertex = 0;

    int iESize, iTSize;
    
    for (MVCIter pkV = m_kVMap.begin(); pkV != m_kVMap.end(); pkV++)
    {
        iESize = pkV->second.m_kESet.GetSize();
        iTSize = pkV->second.m_kTSet.GetSize();
        iESumForV += iESize;
        iTSumForV += iTSize;
        if ( iESize > riMaximumEdgesPerVertex )
            riMaximumEdgesPerVertex = iESize;
        if ( iTSize > riMaximumTrianglesPerVertex )
            riMaximumTrianglesPerVertex = iTSize;
    }
    
    int iTSumForE = 0;
    riMaximumTrianglesPerEdge = 0;
    for (MECIter pkE = m_kEMap.begin(); pkE != m_kEMap.end(); pkE++)
    {
        iTSize = pkE->second.m_kTSet.GetSize();
        iTSumForE += iTSize;
        if ( iTSize > riMaximumTrianglesPerEdge )
            riMaximumTrianglesPerEdge = iTSize;
    }
    
    rfAverageEdgesPerVertex = ((float)iESumForV)/riVQuantity;
    rfAverageTrianglesPerVertex = ((float)iTSumForV)/riVQuantity;
    rfAverageTrianglesPerEdge = ((float)iTSumForE)/riEQuantity;
}
//----------------------------------------------------------------------------

⌨️ 快捷键说明

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