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

📄 wmlconvexhull3.cpp

📁 3D Game Engine Design Source Code非常棒
💻 CPP
📖 第 1 页 / 共 2 页
字号:
        }

        // assert( iU != iL );  the theory
        if ( iU == iL )
        {
            // Numerical round-off error causes you to get here.  P is
            // inside the hull, so just return.
            return;
        }

        // construct the counterclockwise-ordered merged-hull vertices
        vector<int> kTmpHull;
        kTmpHull.push_back(iP);
        while ( true )
        {
            kTmpHull.push_back(m_kHullP[iU]);
            if ( iU == iL )
                break;

            if ( ++iU == iSize )
                iU = 0;
        }
        assert( kTmpHull.size() > 2 );

        m_kHullP = kTmpHull;
        return;
    }

    // Hull is about to become spatial.  The current planar hull is a convex
    // polygon that must be tri-fanned to initialize the triangle mesh that
    // represents the final hull.  The triangle order is required to be
    // counterclockwise when viewed from outside the hull.  If the current
    // planar hull has N vertices, the triangle fan has N-2 triangles and
    // P forms N triangles with the planar hull edges, a total of 2*N-2
    // triangles in the initial spatial hull.
    m_iHullType = HULL_SPATIAL;

    int iSize = (int)m_kHullP.size();
    int iQ0 = m_kHullP[0];
    int iQ1 = m_kHullP[1];
    int iQ2;

    if ( fOrder > Math<Real>::EPSILON )
    {
        // insert <P,Q[0],Q[1]>
        InsertTriangle(iP,iQ0,iQ1);

        for (i = 2; i < iSize; iQ1 = iQ2, i++)
        {
            // insert <Q[0],Q[i+1],Q[i]> and <P,Q[i],Q[i+1]>
            iQ2 = m_kHullP[i];
            InsertTriangle(iQ0,iQ2,iQ1);
            InsertTriangle(iP,iQ1,iQ2);
        }

        // insert <P,Q[n-1],Q[0]>
        InsertTriangle(iP,iQ1,iQ0);
    }
    else  // fOrder < -ms_fEpsilon
    {
        // insert <P,Q[1],Q[0]>
        InsertTriangle(iP,iQ1,iQ0);

        for (i = 2; i < iSize; iQ1 = iQ2, i++)
        {
            // insert <Q[0],Q[i],Q[i+1]> and <P,Q[i+1],Q[i]>
            iQ2 = m_kHullP[i];
            InsertTriangle(iQ0,iQ1,iQ2);
            InsertTriangle(iP,iQ2,iQ1);
        }

        // insert <P,Q[0],Q[n-1]>
        InsertTriangle(iP,iQ0,iQ1);
    }
}
//----------------------------------------------------------------------------
template <class Real>
void ConvexHull3<Real>::MergeSpatial (int iP)
{
    // Find the triangle that is "most visible" to P.  Just finding the first
    // visible triangle is not sufficient when floating point round-off errors
    // are present.  The most visible triangle is used to start a
    // breadth-first for the connected mesh of triangles that are visible
    // to P.
    Vector3<Real> kDiff;
    Real fOrder, fMaxOrder = (Real)0.0;
    const Triangle* pkTri;
    const Triangle* pkMaxTri = NULL;
    const ETManifoldMesh::TMap& rkTMap = m_kHullS.GetTriangles();
    ETManifoldMesh::TMap::const_iterator pkTIter;
    for (pkTIter = rkTMap.begin(); pkTIter != rkTMap.end(); pkTIter++)
    {
        pkTri = (const Triangle*)pkTIter->second;
        kDiff = m_akVertex[iP] - m_akVertex[pkTri->V[0]];
        kDiff.Normalize();
        fOrder = pkTri->Normal.Dot(kDiff);
        if ( fOrder > fMaxOrder )
        {
            // triangle is visible to P
            fMaxOrder = fOrder;
            pkMaxTri = pkTri;
        }
    }

    if ( !pkMaxTri || fMaxOrder < Math<Real>::EPSILON )
    {
        // P is inside the current hull
        return;
    }

    // Triangle pkMinTri is visible to P.  Perform a breadth-first search to
    // locate all remaining visible triangles.
    set<const Triangle*> kInterior, kBoundary;
    kInterior.insert(pkMaxTri);
    const Triangle* pkAdj;
    int i;
    for (i = 0; i < 3; i++)
    {
        pkAdj = (const Triangle*)pkMaxTri->T[i];
        assert( pkAdj );
        kBoundary.insert(pkAdj);
    }

    typename set<const Triangle*>::iterator pkIter;
    while ( kBoundary.size() > 0 )
    {
        set<const Triangle*> kExterior;

        // process boundary triangles
        for (pkIter = kBoundary.begin(); pkIter != kBoundary.end(); pkIter++)
        {
            // current boundary triangle to process
            pkTri = (const Triangle*)*pkIter;
            kDiff = m_akVertex[iP] - m_akVertex[pkTri->V[0]];
            kDiff.Normalize();
            fOrder = pkTri->Normal.Dot(kDiff);
            if ( fOrder > (Real)0.0 )
            {
                // triangle is visible to P
                kInterior.insert(pkTri);

                // locate adjacent, exterior triangles for later processing
                for (i = 0; i < 3; i++)
                {
                    pkAdj = (const Triangle*)pkTri->T[i];
                    assert( pkAdj );
                    if ( kInterior.find(pkAdj) == kInterior.end()
                    &&   kBoundary.find(pkAdj) == kBoundary.end() )
                    {
                        kExterior.insert(pkAdj);
                    }
                }
            }
        }

        // exterior triangles are next in line to be processed
        kBoundary = kExterior;
    }

    // locate the terminator edges
    map<int,int> kTerminator;
    int iV0, iV1;
    for (pkIter = kInterior.begin(); pkIter != kInterior.end(); pkIter++)
    {
        // get a visible triangle
        pkTri = (const Triangle*)*pkIter;

        // If an adjacent triangle is not visible, then the shared edge is a
        // terminator edge.
        for (i = 0; i < 3; i++)
        {
            pkAdj = (const Triangle*)pkTri->T[i];
            assert( pkAdj );
            if ( kInterior.find(pkAdj) == kInterior.end() )
            {
                // adjacent triangle is not visible
                iV0 = pkTri->V[i];
                iV1 = pkTri->V[(i+1)%3];
                kTerminator[iV0] = iV1;
            }
        }
    }

    // remove the visible triangles
    for (pkIter = kInterior.begin(); pkIter != kInterior.end(); pkIter++)
    {
        pkTri = (const Triangle*)*pkIter;
        bool bRemoved = m_kHullS.RemoveTriangle(pkTri->V[0],pkTri->V[1],
            pkTri->V[2]);
        assert( bRemoved );
    }

    // add new triangles formed by P and terminator edges
    int iSize = (int)kTerminator.size();
    assert( iSize >= 3 );
    map<int,int>::iterator pkE = kTerminator.begin();
    int iVStart = pkE->first;
    iV0 = iVStart;
    for (i = 0; i < iSize; i++)
    {
        iV1 = pkE->second;

        // insert <P,V0,V1>
        InsertTriangle(iP,iV0,iV1);

        pkE = kTerminator.find(iV1);
        assert( pkE != kTerminator.end() );
        iV0 = iV1;
    }
    assert( iV0 == iVStart );
}
//----------------------------------------------------------------------------
template <class Real>
void ConvexHull3<Real>::InsertTriangle (int iV0, int iV1, int iV2)
{
    Triangle* pkTri = (Triangle*) m_kHullS.InsertTriangle(iV0,iV1,iV2);
    assert( pkTri );

    const Vector3<Real>& rkV0 = m_akVertex[iV0];
    const Vector3<Real>& rkV1 = m_akVertex[iV1];
    const Vector3<Real>& rkV2 = m_akVertex[iV2];
    Vector3<Real> kE1 = rkV1 - rkV0, kE2 = rkV2 - rkV0;
    pkTri->Normal = kE1.UnitCross(kE2);
}
//----------------------------------------------------------------------------
template <class Real>
ETManifoldMesh::Triangle* ConvexHull3<Real>::CreateTriangle (int iV0, int iV1,
    int iV2)
{
    return new Triangle(iV0,iV1,iV2);
}
//----------------------------------------------------------------------------

//----------------------------------------------------------------------------
// explicit instantiation
//----------------------------------------------------------------------------
namespace Wml
{
template class WML_ITEM ConvexHull3<float>;
template class WML_ITEM ConvexHull3<double>;
}
//----------------------------------------------------------------------------

⌨️ 快捷键说明

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