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

📄 wmlconvexclipper.cpp

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

        int iV1 = rkE.m_aiVertex[1];
        m_akVertex[iV1].m_iOccurs++;
        if ( m_akVertex[iV1].m_iOccurs > 2 )
            bOkay = false;
    }

    if ( !bOkay )
    {
#ifdef _DEBUG
        // If you reach this block, there is a good chance that floating
        // point round-off error had caused this face to be needle-like and
        // what was theoretically a narrow V-shaped portion (a vertex shared
        // by two edges forming a small angle) has collapsed into a single
        // line segment.
        //
        // NOTE.  Once I added PostProcess, I have not gotten to this block.
        ofstream kOStr("error.txt");
        pkIter = rkF.m_akEdge.begin();
        while ( pkIter != rkF.m_akEdge.end() )
        {
            int iE = *pkIter++;
            Edge& rkE = m_akEdge[iE];
            kOStr << "e<" << iE << "> = <" << rkE.m_aiVertex[0] << ","
                  << rkE.m_aiVertex[1] << "|" << rkE.m_aiFace[0] << ","
                  << rkE.m_aiFace[1] << "> ";
            if ( rkE.m_bVisible )
                kOStr << "T" << endl;
            else
                kOStr << "F" << endl;
        }
        kOStr.close();

        assert( false );
#else
        return false;
#endif
    }

    // determine if the polyline is open
    pkIter = rkF.m_akEdge.begin();
    riVStart = -1;
    riVFinal = -1;
    while ( pkIter != rkF.m_akEdge.end() )
    {
        int iE = *pkIter++;
        Edge& rkE = m_akEdge[iE];

        int iV0 = rkE.m_aiVertex[0];
        if ( m_akVertex[iV0].m_iOccurs == 1 )
        {
            if ( riVStart == -1 )
            {
                riVStart = iV0;
            }
            else if ( riVFinal == -1 )
            {
                riVFinal = iV0;
            }
            else
            {
                // If you reach this assert, there is a good chance that the
                // polyhedron is not convex.  To check this, use the function
                // ValidateHalfSpaceProperty() on your polyhedron right after
                // you construct it.
                assert( false );
            }
        }

        int iV1 = rkE.m_aiVertex[1];
        if ( m_akVertex[iV1].m_iOccurs == 1 )
        {
            if ( riVStart == -1 )
            {
                riVStart = iV1;
            }
            else if ( riVFinal == -1 )
            {
                riVFinal = iV1;
            }
            else
            {
                // If you reach this assert, there is a good chance that the
                // polyhedron is not convex.  To check this, use the function
                // ValidateHalfSpaceProperty() on your polyhedron right after
                // you construct it.
                assert( false );
            }
        }
    }

    assert( (riVStart == -1 && riVFinal == -1)
        ||  (riVStart != -1 && riVFinal != -1) );

    return riVStart != -1;
}
//----------------------------------------------------------------------------
template <class Real>
void ConvexClipper<Real>::OrderVertices (Face& rkF, vector<int>& aiVOrdered)
{
    // copy edge indices into contiguous memory
    int i = 0, iQuantity = (int)rkF.m_akEdge.size();
    vector<int> aiEOrdered(iQuantity);
    set<int>::iterator pkIter = rkF.m_akEdge.begin();
    while ( pkIter != rkF.m_akEdge.end() )
        aiEOrdered[i++] = *pkIter++;

    // bubble sort (yes, it is...)
    for (int i0 = 0, i1 = 1, iChoice = 1; i1 < iQuantity-1; i0 = i1, i1++)
    {
        Edge& rkECurr = m_akEdge[aiEOrdered[i0]];
        int j, iCurr = rkECurr.m_aiVertex[iChoice];
        for (j = i1; j < iQuantity; j++)
        {
            Edge& rkETemp = m_akEdge[aiEOrdered[j]];
            int iSave;
            if ( rkETemp.m_aiVertex[0] == iCurr )
            {
                iSave = aiEOrdered[i1];
                aiEOrdered[i1] = aiEOrdered[j];
                aiEOrdered[j] = iSave;
                iChoice = 1;
                break;
            }
            if ( rkETemp.m_aiVertex[1] == iCurr )
            {
                iSave = aiEOrdered[i1];
                aiEOrdered[i1] = aiEOrdered[j];
                aiEOrdered[j] = iSave;
                iChoice = 0;
                break;
            }
        }
        assert( j < iQuantity );
    }

    aiVOrdered[0] = m_akEdge[aiEOrdered[0]].m_aiVertex[0];
    aiVOrdered[1] = m_akEdge[aiEOrdered[0]].m_aiVertex[1];
    for (i = 1; i < iQuantity; i++)
    {
        Edge& rkE = m_akEdge[aiEOrdered[i]];
        if ( rkE.m_aiVertex[0] == aiVOrdered[i] )
            aiVOrdered[i+1] = rkE.m_aiVertex[1];
        else
            aiVOrdered[i+1] = rkE.m_aiVertex[0];
    }
}
//----------------------------------------------------------------------------
template <class Real>
void ConvexClipper<Real>::GetTriangles (vector<int>& raiConnect,
    vector<Plane3<Real> >& rakPlane)
{
    for (int iF = 0; iF < (int)m_akFace.size(); iF++)
    {
        Face& rkF = m_akFace[iF];
        if ( rkF.m_bVisible )
        {
            int iQuantity = (int)rkF.m_akEdge.size();
            assert( iQuantity >= 3 );
            vector<int> aiOrdered(iQuantity+1);
            OrderVertices(rkF,aiOrdered);

            int iV0 = aiOrdered[0], iV2 = aiOrdered[iQuantity-1];
            int iV1 = aiOrdered[(iQuantity-1) >> 1];
            Vector3<Real> kD1 = m_akVertex[iV1].m_kPoint -
                m_akVertex[iV0].m_kPoint;
            Vector3<Real> kD2 = m_akVertex[iV2].m_kPoint -
                m_akVertex[iV0].m_kPoint;
            Real fTSP = rkF.m_kPlane.GetNormal().Dot(kD1.Cross(kD2));
            if ( fTSP > (Real)0.0 )
            {
                // clockwise, need to swap
                for (int i = 1; i+1 < iQuantity; i++)
                {
                    raiConnect.push_back(iV0);
                    raiConnect.push_back(aiOrdered[i+1]);
                    raiConnect.push_back(aiOrdered[i]);
                    rakPlane.push_back(rkF.m_kPlane);
                }
            }
            else
            {
                // counterclockwise
                for (int i = 1; i+1 < iQuantity; i++)
                {
                    raiConnect.push_back(iV0);
                    raiConnect.push_back(aiOrdered[i]);
                    raiConnect.push_back(aiOrdered[i+1]);
                    rakPlane.push_back(rkF.m_kPlane);
                }
            }
        }
    }
}
//----------------------------------------------------------------------------
template <class Real>
void ConvexClipper<Real>::Convert (ConvexPolyhedron3<Real>& rkPoly)
{
    // get visible vertices
    int iVQuantity = (int)m_akVertex.size();
    vector<Vector3<Real> > akPoint;
    int* aiVMap = new int[iVQuantity];
    memset(aiVMap,0xFF,iVQuantity*sizeof(int));
    for (int iV = 0; iV < iVQuantity; iV++)
    {
        const Vertex& rkV = m_akVertex[iV];
        if ( rkV.m_bVisible )
        {
            aiVMap[iV] = (int)akPoint.size();
            akPoint.push_back(rkV.m_kPoint);
        }
    }

    vector<int> aiConnect;
    vector<Plane3<Real> > akPlane;
    GetTriangles(aiConnect,akPlane);

    // re-order
    int iNewVQuantity = (int)akPoint.size();
    for (int iC = 0; iC < (int)aiConnect.size(); iC++)
    {
        int iOldC = aiConnect[iC];
        assert( 0 <= iOldC && iOldC < iVQuantity );
        int iNewC = aiVMap[iOldC];
        assert( 0 <= iNewC && iNewC < iNewVQuantity );
        aiConnect[iC] = iNewC;
    }

    delete[] aiVMap;

    rkPoly.Create(akPoint,aiConnect,akPlane);
}
//----------------------------------------------------------------------------
template <class Real>
bool ConvexClipper<Real>::Print (const char* acFilename) const
{
    ofstream kOStr(acFilename);
    if ( !kOStr )
        return false;

    int iVQuantity = (int)m_akVertex.size();
    int iEQuantity = (int)m_akEdge.size();
    int iFQuantity = (int)m_akFace.size();
    int iVDigits = (int)(ceil(log10((double)iVQuantity)));
    int iEDigits = (int)(ceil(log10((double)iEQuantity)));
    int iFDigits = (int)(ceil(log10((double)iFQuantity)));
    char acMsg[1024];

    kOStr << iVQuantity << " vertices" << endl;
    for (int iV = 0; iV < iVQuantity; iV++)
    {
        const Vertex& rkV = m_akVertex[iV];
        sprintf(acMsg,"v<%*d> %c: (%f,%f,%f)",
            iVDigits,iV,(rkV.m_bVisible ? 'T' : 'F'),
            rkV.m_kPoint.X(),
            rkV.m_kPoint.Y(),
            rkV.m_kPoint.Z());
        kOStr << acMsg << endl;
    }
    kOStr << endl;

    kOStr << iEQuantity << " edges" << endl;
    for (int iE = 0; iE < iEQuantity; iE++)
    {
        const Edge& rkE = m_akEdge[iE];
        sprintf(acMsg,"e<%*d> %c: v[%*d,%*d], t[%*d,%*d]",
            iEDigits,iE,(rkE.m_bVisible ? 'T' : 'F'),
            iVDigits,rkE.m_aiVertex[0],
            iVDigits,rkE.m_aiVertex[1],
            iFDigits,rkE.m_aiFace[0],
            iFDigits,rkE.m_aiFace[1]);
        kOStr << acMsg << endl;
    }
    kOStr << endl;

    kOStr << iFQuantity << " faces" << endl;
    for (int iF = 0; iF < iFQuantity; iF++)
    {
        const Face& rkF = m_akFace[iF];
        sprintf(acMsg,"t<%*d> %d: e = ",
            iFDigits,iF,(rkF.m_bVisible ? 'T' : 'F'));
        kOStr << acMsg;

        set<int>::const_iterator pkIter = rkF.m_akEdge.begin();
        while ( pkIter != rkF.m_akEdge.end() )
        {
            kOStr << *pkIter << ' ';
            pkIter++;
        }
        kOStr << endl;
    }

    return true;
}
//----------------------------------------------------------------------------

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

⌨️ 快捷键说明

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