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

📄 mgcbeziertriangle2g.cpp

📁 《3D游戏引擎设计》的源码
💻 CPP
字号:
// Magic Software, Inc.
// http://www.magic-software.com
// Copyright (c) 2000, All Rights Reserved
//
// Source code from Magic Software is supplied under the terms of a license
// agreement and may not be copied or disclosed except in accordance with the
// terms of that agreement.  The various license agreements may be found at
// the Magic Software web site.  This file is subject to the license
//
// FREE SOURCE CODE
// http://www.magic-software.com/License/free.pdf

#include "MgcBezierTriangle2G.h"

//----------------------------------------------------------------------------
MgcBezierTriangle2G::MgcBezierTriangle2G (MgcVector3* akCtrlPoint)
    :
    MgcBezierTriangleG(2,akCtrlPoint)
{
}
//----------------------------------------------------------------------------
MgcVector3 MgcBezierTriangle2G::GetPosition (MgcReal fU, MgcReal fV) const
{
    MgcReal fW = 1.0 - fU - fV;
    MgcReal fU2 = fU*fU, fV2 = fV*fV, fW2 = fW*fW;
    MgcReal f2UV = 2.0*fU*fV, f2UW = 2.0*fU*fW, f2VW = 2.0*fV*fW;

    return fW2*m_akCtrlPoint[0] + f2UW*m_akCtrlPoint[1] +
        fU2*m_akCtrlPoint[2] + f2VW*m_akCtrlPoint[3] + f2UV*m_akCtrlPoint[4] +
        fV2*m_akCtrlPoint[5];
}
//----------------------------------------------------------------------------
MgcVector3 MgcBezierTriangle2G::GetDerivativeU (MgcReal fU, MgcReal fV) const
{
    MgcReal fW = 1.0 - fU - fV;

    return 2.0*(-fW*m_akCtrlPoint[0] + (fW-fU)*m_akCtrlPoint[1] +
        fU*m_akCtrlPoint[2] - fV*m_akCtrlPoint[3] + fV*m_akCtrlPoint[4]);
}
//----------------------------------------------------------------------------
MgcVector3 MgcBezierTriangle2G::GetDerivativeV (MgcReal fU, MgcReal fV) const
{
    MgcReal fW = 1.0 - fU - fV;

    return 2.0*(-fW*m_akCtrlPoint[0] - fU*m_akCtrlPoint[1] +
        (fW-fU)*m_akCtrlPoint[3] + fU*m_akCtrlPoint[4] +
        fV*m_akCtrlPoint[5]);
}
//----------------------------------------------------------------------------
MgcVector3 MgcBezierTriangle2G::GetDerivativeUU (MgcReal fU, MgcReal fV) const
{
    return 2.0*(m_akCtrlPoint[0] - 2.0*m_akCtrlPoint[1] + m_akCtrlPoint[2]);
}
//----------------------------------------------------------------------------
MgcVector3 MgcBezierTriangle2G::GetDerivativeUV (MgcReal fU, MgcReal fV) const
{
    return 2.0*(m_akCtrlPoint[0] - m_akCtrlPoint[1] - m_akCtrlPoint[3] +
        m_akCtrlPoint[4]);
}
//----------------------------------------------------------------------------
MgcVector3 MgcBezierTriangle2G::GetDerivativeVV (MgcReal fU, MgcReal fV) const
{
    return 2.0*(m_akCtrlPoint[0] - 2.0*m_akCtrlPoint[3] + m_akCtrlPoint[5]);
}
//----------------------------------------------------------------------------
void MgcBezierTriangle2G::Tessellate (unsigned int uiLevel, bool bWantNormals)
{
    // allocate arrays and compute connectivity
    Initialize(uiLevel,bWantNormals);

    // indices of three corners of patch, I0 (w=1), I1 (u=1), I2 (v=1)
    unsigned int uiTwoPowL = (1 << uiLevel);
    unsigned int uiI0 = 0;
    unsigned int uiI1 = uiTwoPowL;
    unsigned int uiI2 = uiTwoPowL*(uiTwoPowL + 3) >> 1;

    // vertices for subdivision
    MgcVector3* akX = m_akVertex;
    akX[uiI0] = m_akCtrlPoint[0];
    akX[uiI1] = m_akCtrlPoint[2];
    akX[uiI2] = m_akCtrlPoint[5];

    // derivatives for subdivision (for normal vectors)
    MgcVector3* akXu;
    MgcVector3* akXv;
    if ( bWantNormals )
    {
        akXu = new MgcVector3[m_uiVertexQuantity];
        akXu[uiI0] = 2.0*(m_akCtrlPoint[1] - m_akCtrlPoint[0]);
        akXu[uiI1] = 2.0*(m_akCtrlPoint[2] - m_akCtrlPoint[1]);
        akXu[uiI2] = 2.0*(m_akCtrlPoint[4] - m_akCtrlPoint[3]);

        akXv = new MgcVector3[m_uiVertexQuantity];
        akXv[uiI0] = 2.0*(m_akCtrlPoint[3] - m_akCtrlPoint[0]);
        akXv[uiI1] = 2.0*(m_akCtrlPoint[5] - m_akCtrlPoint[3]);
        akXv[uiI2] = 2.0*(m_akCtrlPoint[4] - m_akCtrlPoint[1]);
    }
    else
    {
        akXu = 0;
        akXv = 0;
    }

    // recursive subdivision
    if ( uiLevel > 0 )
    {
        BlockParameters kBP;
        kBP.m_kXuu = 2.0*(m_akCtrlPoint[0] - 2.0*m_akCtrlPoint[1] +
            m_akCtrlPoint[2]);
        kBP.m_kXvv = 2.0*(m_akCtrlPoint[0] - 2.0*m_akCtrlPoint[3] +
            m_akCtrlPoint[5]);
        kBP.m_kXhh = 2.0*(m_akCtrlPoint[0] + m_akCtrlPoint[4] -
            m_akCtrlPoint[1] - m_akCtrlPoint[3]);

        SubdivideLL(--uiLevel,0.25,akX,akXu,akXv,uiI0,uiI1,uiI2,kBP);
    }

    // calculate unit-length normals from derivative vectors
    if ( bWantNormals )
    {
        for (unsigned int uiI = 0; uiI < m_uiVertexQuantity; uiI++)
            m_akNormal[uiI] = akXu[uiI].UnitCross(akXv[uiI]);
        delete[] akXu;
        delete[] akXv;
    }
}
//----------------------------------------------------------------------------
void MgcBezierTriangle2G::SubdivideLL (unsigned int uiLevel, MgcReal fDSqr,
    MgcVector3* akX, MgcVector3* akXu, MgcVector3* akXv, unsigned int uiI0,
    unsigned int uiI1, unsigned int uiI2, BlockParameters& rkBP)
{
    /*
     i2
     +
     | \
     |   \
     +----+
     i0    i1
    */

    // subdivision indices
    unsigned int uiI01 = (uiI0 + uiI1) >> 1;
    unsigned int uiD10 = uiI1 - uiI0;
    unsigned int uiI02 = (((uiI0 + uiI2) << 2) + uiD10*uiD10) >> 3;
    unsigned int uiI12 = uiI02 + (uiD10 >> 1);

    // vertices

    // bottom u-edge subdivision
    akX[uiI01] = 0.5*(akX[uiI0] + akX[uiI1] - fDSqr*rkBP.m_kXuu);

    // left v-edge subdivision
    akX[uiI02] = 0.5*(akX[uiI0] + akX[uiI2] - fDSqr*rkBP.m_kXvv);

    // hypotenuse edge subdivision
    akX[uiI12] = 0.5*(akX[uiI1] + akX[uiI2] - fDSqr*rkBP.m_kXhh);

    // derivatives (for normal vectors)
    if ( akXu )
    {
        // bottom u-edge subdivision
        akXu[uiI01] = 0.5*(akXu[uiI0] + akXu[uiI1]);
        akXv[uiI01] = 0.5*(akXv[uiI0] + akXv[uiI1]);

        // left v-edge subdivision
        akXu[uiI02] = 0.5*(akXu[uiI0] + akXu[uiI2]);
        akXv[uiI02] = 0.5*(akXv[uiI0] + akXv[uiI2]);

        // hypotenuse edge subdivision
        akXu[uiI12] = 0.5*(akXu[uiI1] + akXu[uiI2]);
        akXv[uiI12] = 0.5*(akXv[uiI1] + akXv[uiI2]);
    }

    // recurse on four children
    if ( uiLevel > 0 )
    {
        uiLevel--;
        fDSqr *= 0.25;

        // subtriangle <(s0,t0),(sm,t0),(s0,tm)>
        SubdivideLL(uiLevel,fDSqr,akX,akXu,akXv,uiI0,uiI01,uiI02,rkBP);

        // subtriangle <(sm,t0),(s1,t0),(sm,tm)>
        SubdivideLL(uiLevel,fDSqr,akX,akXu,akXv,uiI01,uiI1,uiI12,rkBP);

        // subtriangle <(s0,tm),(sm,tm),(s0,t1)>
        SubdivideLL(uiLevel,fDSqr,akX,akXu,akXv,uiI02,uiI12,uiI2,rkBP);

        // subtriangle <(sm,t0),(sm,tm),(s0,tm)>
        SubdivideUR(uiLevel,fDSqr,akX,akXu,akXv,uiI01,uiI12,uiI02,rkBP);
    }
}
//----------------------------------------------------------------------------
void MgcBezierTriangle2G::SubdivideUR (unsigned int uiLevel, MgcReal fDSqr,
    MgcVector3* akX, MgcVector3* akXu, MgcVector3* akXv, unsigned int uiI0,
    unsigned int uiI1, unsigned int uiI2, BlockParameters& rkBP)
{
    /*
     i2   i1
     +----+
       \  |
         \|
          +
          i0
    */

    // subdivision indices
    unsigned int uiI12 = (uiI1 + uiI2) >> 1;
    unsigned int uiD12 = uiI1 - uiI2;
    unsigned int uiI01 = (((uiI0 + uiI1) << 2) + uiD12*uiD12) >> 3;
    unsigned int uiI02 = uiI01 - (uiD12 >> 1);

    // vertices

    // top u-edge subdivision
    akX[uiI12] = 0.5*(akX[uiI1] + akX[uiI2] - fDSqr*rkBP.m_kXuu);

    // right v-edge subdivision
    akX[uiI01] = 0.5*(akX[uiI0] + akX[uiI1] - fDSqr*rkBP.m_kXvv);

    // hypotenuse edge subdivision
    akX[uiI02] = 0.5*(akX[uiI0] + akX[uiI2] - fDSqr*rkBP.m_kXhh);

    // recurse on four children
    if ( uiLevel > 0 )
    {
        uiLevel--;
        fDSqr *= 0.25;

        // subtriangle <(sm,tm),(sm,t1),(s0,t1)>
        SubdivideUR(uiLevel,fDSqr,akX,akXu,akXv,uiI02,uiI12,uiI2,rkBP);

        // subtriangle <(s1,tm),(s1,t1),(sm,t1)>
        SubdivideUR(uiLevel,fDSqr,akX,akXu,akXv,uiI01,uiI1,uiI12,rkBP);

        // subtriangle <(s1,t0),(s1,tm),(sm,tm)>
        SubdivideUR(uiLevel,fDSqr,akX,akXu,akXv,uiI0,uiI01,uiI02,rkBP);

        // subtriangle <(sm,tm),(s1,tm),(sm,t1)>
        SubdivideLL(uiLevel,fDSqr,akX,akXu,akXv,uiI02,uiI01,uiI12,rkBP);
    }
}
//----------------------------------------------------------------------------

⌨️ 快捷键说明

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