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

📄 mgcbezierrectangle2g.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 "MgcBezierRectangle2G.h"

//----------------------------------------------------------------------------
MgcBezierRectangle2G::MgcBezierRectangle2G (MgcVector3* akCtrlPoint)
    :
    MgcBezierRectangleG(2,akCtrlPoint)
{
}
//----------------------------------------------------------------------------
MgcVector3 MgcBezierRectangle2G::GetPosition (MgcReal fU, MgcReal fV) const
{
    MgcReal fOmU = 1.0 - fU;
    MgcReal afUCoeff[3] =
    {
        fOmU*fOmU,
        2.0*fOmU*fU,
        fU*fU
    };

    MgcReal fOmV = 1.0 - fV;
    MgcReal afVCoeff[3] =
    {
        fOmV*fOmV,
        2.0*fOmV*fV,
        fV*fV
    };

    MgcVector3 kResult = MgcVector3::ZERO;
    for (int iY = 0; iY < 3; iY++)
    {
        for (int iX = 0; iX < 3; iX++)
            kResult += afUCoeff[iX]*afVCoeff[iY]*m_akCtrlPoint[iX + 3*iY];
    }

    return kResult;
}
//----------------------------------------------------------------------------
MgcVector3 MgcBezierRectangle2G::GetDerivativeU (MgcReal fU, MgcReal fV) const
{
    MgcReal fOmU = 1.0 - fU;
    MgcReal afUCoeff[3] =
    {
        -2.0*fOmU,
        2.0*(fOmU - fU),
        2.0*fU
    };

    MgcReal fOmV = 1.0 - fV;
    MgcReal afVCoeff[3] =
    {
        fOmV*fOmV,
        2.0*fOmV*fV,
        fV*fV
    };

    MgcVector3 kResult = MgcVector3::ZERO;
    for (int iY = 0; iY < 3; iY++)
    {
        for (int iX = 0; iX < 3; iX++)
            kResult += afUCoeff[iX]*afVCoeff[iY]*m_akCtrlPoint[iX + 3*iY];
    }

    return kResult;
}
//----------------------------------------------------------------------------
MgcVector3 MgcBezierRectangle2G::GetDerivativeV (MgcReal fU, MgcReal fV) const
{
    MgcReal fOmU = 1.0 - fU;
    MgcReal afUCoeff[3] =
    {
        fOmU*fOmU,
        2.0*fOmU*fU,
        fU*fU
    };

    MgcReal fOmV = 1.0 - fV;
    MgcReal afVCoeff[3] =
    {
        -2.0*fOmV,
        2.0*(fOmV - fV),
        2.0*fV
    };

    MgcVector3 kResult = MgcVector3::ZERO;
    for (int iY = 0; iY < 3; iY++)
    {
        for (int iX = 0; iX < 3; iX++)
            kResult += afUCoeff[iX]*afVCoeff[iY]*m_akCtrlPoint[iX + 3*iY];
    }

    return kResult;
}
//----------------------------------------------------------------------------
MgcVector3 MgcBezierRectangle2G::GetDerivativeUU (MgcReal fU,
    MgcReal fV) const
{
    MgcReal afUCoeff[3] =
    {
        2.0,
        -4.0,
        2.0
    };

    MgcReal fOmV = 1.0 - fV;
    MgcReal afVCoeff[3] =
    {
        fOmV*fOmV,
        2.0*fOmV*fV,
        fV*fV
    };

    MgcVector3 kResult = MgcVector3::ZERO;
    for (int iY = 0; iY < 3; iY++)
    {
        for (int iX = 0; iX < 3; iX++)
            kResult += afUCoeff[iX]*afVCoeff[iY]*m_akCtrlPoint[iX + 3*iY];
    }

    return kResult;
}
//----------------------------------------------------------------------------
MgcVector3 MgcBezierRectangle2G::GetDerivativeUV (MgcReal fU,
    MgcReal fV) const
{
    MgcReal fOmU = 1.0 - fU;
    MgcReal afUCoeff[3] =
    {
        -2.0*fOmU,
        2.0*(fOmU - fU),
        2.0*fU
    };

    MgcReal fOmV = 1.0 - fV;
    MgcReal afVCoeff[3] =
    {
        -2.0*fOmV,
        2.0*(fOmV - fV),
        2.0*fV
    };

    MgcVector3 kResult = MgcVector3::ZERO;
    for (int iY = 0; iY < 3; iY++)
    {
        for (int iX = 0; iX < 3; iX++)
            kResult += afUCoeff[iX]*afVCoeff[iY]*m_akCtrlPoint[iX + 3*iY];
    }

    return kResult;
}
//----------------------------------------------------------------------------
MgcVector3 MgcBezierRectangle2G::GetDerivativeVV (MgcReal fU,
    MgcReal fV) const
{
    MgcReal fOmU = 1.0 - fU;
    MgcReal afUCoeff[3] =
    {
        fOmU*fOmU,
        2.0*fOmU*fU,
        fU*fU
    };

    MgcReal afVCoeff[3] =
    {
        2.0,
        -4.0,
        2.0
    };

    MgcVector3 kResult = MgcVector3::ZERO;
    for (int iY = 0; iY < 3; iY++)
    {
        for (int iX = 0; iX < 3; iX++)
            kResult += afUCoeff[iX]*afVCoeff[iY]*m_akCtrlPoint[iX + 3*iY];
    }

    return kResult;
}
//----------------------------------------------------------------------------
void MgcBezierRectangle2G::Tessellate (unsigned int uiLevel,
    bool bWantNormals)
{
    // allocate arrays and compute connectivity
    Initialize(uiLevel,bWantNormals);

    // indices of four corners of patch, I[u][v]
    unsigned int uiTwoPowL = (1 << uiLevel);
    BlockParameters kBP;
    kBP.m_uiI00 = 0;
    kBP.m_uiI01 = uiTwoPowL*(uiTwoPowL + 1);
    kBP.m_uiI10 = uiTwoPowL;
    kBP.m_uiI11 = kBP.m_uiI01 + uiTwoPowL;

    // vertices for subdivision
    MgcVector3* akX = m_akVertex;
    akX[kBP.m_uiI00] = m_akCtrlPoint[0];
    akX[kBP.m_uiI01] = m_akCtrlPoint[6];
    akX[kBP.m_uiI10] = m_akCtrlPoint[2];
    akX[kBP.m_uiI11] = m_akCtrlPoint[8];

    // derivatives for subdivision (for normal vectors)
    MgcVector3* akXu;
    MgcVector3* akXv;
    if ( bWantNormals )
    {
        akXu = new MgcVector3[m_uiVertexQuantity];
        akXu[kBP.m_uiI00] = 2.0*(m_akCtrlPoint[1] - m_akCtrlPoint[0]);
        akXu[kBP.m_uiI01] = 3.0*(m_akCtrlPoint[7] - m_akCtrlPoint[6]);
        akXu[kBP.m_uiI10] = 3.0*(m_akCtrlPoint[2] - m_akCtrlPoint[1]);
        akXu[kBP.m_uiI11] = 3.0*(m_akCtrlPoint[8] - m_akCtrlPoint[7]);

        akXv = new MgcVector3[m_uiVertexQuantity];
        akXv[kBP.m_uiI00] = 3.0*(m_akCtrlPoint[3] - m_akCtrlPoint[0]);
        akXv[kBP.m_uiI01] = 3.0*(m_akCtrlPoint[6] - m_akCtrlPoint[3]);
        akXv[kBP.m_uiI10] = 3.0*(m_akCtrlPoint[5] - m_akCtrlPoint[2]);
        akXv[kBP.m_uiI11] = 3.0*(m_akCtrlPoint[8] - m_akCtrlPoint[5]);
    }
    else
    {
        akXu = 0;
        akXv = 0;
    }

    // recursive subdivision
    if ( uiLevel > 0 )
    {
        kBP.m_akXuu[0] = 2.0*(m_akCtrlPoint[0] - 2.0*m_akCtrlPoint[1] +
            m_akCtrlPoint[2]);
        kBP.m_akXuu[1] = 2.0*(m_akCtrlPoint[6] - 2.0*m_akCtrlPoint[7] +
            m_akCtrlPoint[8]);
        kBP.m_akXvv[0] = 2.0*(m_akCtrlPoint[0] - 2.0*m_akCtrlPoint[3] +
            m_akCtrlPoint[6]);
        kBP.m_akXvv[1] = 2.0*(m_akCtrlPoint[2] - 2.0*m_akCtrlPoint[5] +
            m_akCtrlPoint[8]);

        MgcVector3 kXuuvv = 4.0*(m_akCtrlPoint[0] + m_akCtrlPoint[2] +
            m_akCtrlPoint[6] + m_akCtrlPoint[8] - 2.0*(m_akCtrlPoint[1] +
            m_akCtrlPoint[3] + m_akCtrlPoint[5] + m_akCtrlPoint[7]) +
            4.0*m_akCtrlPoint[4]);

        if ( bWantNormals )
        {
            kBP.m_akXuuv[0] = 4.0*(m_akCtrlPoint[3] + m_akCtrlPoint[5] -
                m_akCtrlPoint[0] - m_akCtrlPoint[2] + 2.0*(m_akCtrlPoint[1] -
                m_akCtrlPoint[4]));
            kBP.m_akXuuv[1] = 4.0*(m_akCtrlPoint[6] + m_akCtrlPoint[8] -
                m_akCtrlPoint[3] - m_akCtrlPoint[5] + 2.0*(m_akCtrlPoint[4] -
                m_akCtrlPoint[7]));
            kBP.m_akXuvv[0] = 4.0*(m_akCtrlPoint[1] + m_akCtrlPoint[7] -
                m_akCtrlPoint[0] - m_akCtrlPoint[6] + 2.0*(m_akCtrlPoint[3] -
                m_akCtrlPoint[4]));
            kBP.m_akXuvv[1] = 4.0*(m_akCtrlPoint[2] + m_akCtrlPoint[8] - 
                m_akCtrlPoint[1] - m_akCtrlPoint[7] + 2.0*(m_akCtrlPoint[4] -
                m_akCtrlPoint[5]));
        }

        Subdivide(--uiLevel,0.25,akX,akXu,akXv,kXuuvv,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 MgcBezierRectangle2G::Subdivide (unsigned int uiLevel, MgcReal fDSqr,
    MgcVector3* akX, MgcVector3* akXu, MgcVector3* akXv, MgcVector3& rkXuuvv,
    BlockParameters& rkBP)
{
    // subdivision indices
    unsigned int uiIM0 = (rkBP.m_uiI00 + rkBP.m_uiI10) >> 1;
    unsigned int uiIM1 = (rkBP.m_uiI01 + rkBP.m_uiI11) >> 1;
    unsigned int uiI0M = (rkBP.m_uiI00 + rkBP.m_uiI01) >> 1;
    unsigned int uiI1M = (rkBP.m_uiI10 + rkBP.m_uiI11) >> 1;
    unsigned int uiIMM = (uiI0M + uiI1M) >> 1;

    // vertices

    // top and bottom u-edge subdivision
    MgcVector3 kXvvM0 = 0.5*(rkBP.m_akXvv[0]+rkBP.m_akXvv[1]-fDSqr*rkXuuvv);
    akX[uiIM0] = 0.5*(akX[rkBP.m_uiI00] + akX[rkBP.m_uiI10] -
        fDSqr*rkBP.m_akXuu[0]);
    akX[uiIM1] = 0.5*(akX[rkBP.m_uiI01] + akX[rkBP.m_uiI11] -
        fDSqr*rkBP.m_akXuu[1]);

    // left and right v-edge subdivision
    MgcVector3 kXuu0M = 0.5*(rkBP.m_akXuu[0]+rkBP.m_akXuu[1]-fDSqr*rkXuuvv);
    akX[uiI0M] = 0.5*(akX[rkBP.m_uiI00] + akX[rkBP.m_uiI01] -
        fDSqr*rkBP.m_akXvv[0]);
    akX[uiI1M] = 0.5*(akX[rkBP.m_uiI10] + akX[rkBP.m_uiI11] -
        fDSqr*rkBP.m_akXvv[1]);

    // center subdivision
    akX[uiIMM] = 0.5*(akX[uiI0M] + akX[uiI1M] - fDSqr*kXuu0M);

    // derivatives (for normal vectors)
    MgcVector3 kXuuv0M, kXuvvM0;
    if ( akXu )
    {
        // top and bottom u-edge subdivision
        akXu[uiIM0] = 0.5*(akXu[rkBP.m_uiI00] + akXu[rkBP.m_uiI10]);
        akXv[uiIM0] = 0.5*(akXv[rkBP.m_uiI00] + akXv[rkBP.m_uiI10] -
            fDSqr*rkBP.m_akXuuv[0]);
        akXu[uiIM1] = 0.5*(akXu[rkBP.m_uiI01] + akXu[rkBP.m_uiI11]);
        akXv[uiIM1] = 0.5*(akXv[rkBP.m_uiI01] + akXv[rkBP.m_uiI11] -
            fDSqr*rkBP.m_akXuuv[1]);

        kXuvvM0 = 0.5*(rkBP.m_akXuvv[0] + rkBP.m_akXuvv[1]);

        // left and right v-edge subdivision
        akXu[uiI0M] = 0.5*(akXu[rkBP.m_uiI00] + akXu[rkBP.m_uiI01] -
            fDSqr*rkBP.m_akXuvv[0]);
        akXv[uiI0M] = 0.5*(akXv[rkBP.m_uiI00] + akXv[rkBP.m_uiI01]);
        akXu[uiI1M] = 0.5*(akXu[rkBP.m_uiI10] + akXu[rkBP.m_uiI11] -
            fDSqr*rkBP.m_akXuvv[1]);
        akXv[uiI1M] = 0.5*(akXv[rkBP.m_uiI10] + akXv[rkBP.m_uiI11]);

        kXuuv0M = 0.5*(rkBP.m_akXuuv[0] + rkBP.m_akXuuv[1]);

        // center subdivision
        akXu[uiIMM] = 0.5*(akXu[uiI0M] + akXu[uiI1M]);
        akXv[uiIMM] = 0.5*(akXv[uiIM0] + akXv[uiIM1]);
    }

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

        BlockParameters kSubBP;

        // subblock [u0,uM]x[v0,vM]
        kSubBP.m_uiI00 = rkBP.m_uiI00;
        kSubBP.m_uiI01 = uiI0M;
        kSubBP.m_uiI10 = uiIM0;
        kSubBP.m_uiI11 = uiIMM;

        kSubBP.m_akXuu[0] = rkBP.m_akXuu[0];
        kSubBP.m_akXuu[1] = kXuu0M;
        kSubBP.m_akXvv[0] = rkBP.m_akXvv[0];
        kSubBP.m_akXvv[1] = kXvvM0;

        if ( akXu )
        {
            kSubBP.m_akXuuv[0] = rkBP.m_akXuuv[0];
            kSubBP.m_akXuuv[1] = kXuuv0M;
            kSubBP.m_akXuvv[0] = rkBP.m_akXuvv[0];
            kSubBP.m_akXuvv[1] = kXuvvM0;
        }

        Subdivide(uiLevel,fDSqr,akX,akXu,akXv,rkXuuvv,kSubBP);

        // subblock [u0,uM]x[vM,v1]
        kSubBP.m_uiI00 = uiI0M;
        kSubBP.m_uiI01 = rkBP.m_uiI01;
        kSubBP.m_uiI10 = uiIMM;
        kSubBP.m_uiI11 = uiIM1;

        kSubBP.m_akXuu[0] = kXuu0M;
        kSubBP.m_akXuu[1] = rkBP.m_akXuu[1];
        kSubBP.m_akXvv[0] = rkBP.m_akXvv[0];
        kSubBP.m_akXvv[1] = kXvvM0;

        if ( akXu )
        {
            kSubBP.m_akXuuv[0] = kXuuv0M;
            kSubBP.m_akXuuv[1] = rkBP.m_akXuuv[1];
            kSubBP.m_akXuvv[0] = rkBP.m_akXuvv[0];
            kSubBP.m_akXuvv[1] = kXuvvM0;
        }

        Subdivide(uiLevel,fDSqr,akX,akXu,akXv,rkXuuvv,kSubBP);

        // subblock [uM,u1]x[v0,vM]
        kSubBP.m_uiI00 = uiIM0;
        kSubBP.m_uiI01 = uiIMM;
        kSubBP.m_uiI10 = rkBP.m_uiI10;
        kSubBP.m_uiI11 = uiI1M;

        kSubBP.m_akXuu[0] = rkBP.m_akXuu[0];
        kSubBP.m_akXuu[1] = kXuu0M;
        kSubBP.m_akXvv[0] = kXvvM0;
        kSubBP.m_akXvv[1] = rkBP.m_akXvv[1];

        if ( akXu )
        {
            kSubBP.m_akXuuv[0] = rkBP.m_akXuuv[0];
            kSubBP.m_akXuuv[1] = kXuuv0M;
            kSubBP.m_akXuvv[0] = kXuvvM0;
            kSubBP.m_akXuvv[1] = rkBP.m_akXuvv[1];
        }

        Subdivide(uiLevel,fDSqr,akX,akXu,akXv,rkXuuvv,kSubBP);

        // subblock [uM,u1]x[vM,v1]
        kSubBP.m_uiI00 = uiIMM;
        kSubBP.m_uiI01 = uiIM1;
        kSubBP.m_uiI10 = uiI1M;
        kSubBP.m_uiI11 = rkBP.m_uiI11;

        kSubBP.m_akXuu[0] = kXuu0M;
        kSubBP.m_akXuu[1] = rkBP.m_akXuu[1];
        kSubBP.m_akXvv[0] = kXvvM0;
        kSubBP.m_akXvv[1] = rkBP.m_akXvv[1];

        if ( akXu )
        {
            kSubBP.m_akXuuv[0] = kXuuv0M;
            kSubBP.m_akXuuv[1] = rkBP.m_akXuuv[1];
            kSubBP.m_akXuvv[0] = kXuvvM0;
            kSubBP.m_akXuvv[1] = rkBP.m_akXuvv[1];
        }

        Subdivide(uiLevel,fDSqr,akX,akXu,akXv,rkXuuvv,kSubBP);
    }
}
//----------------------------------------------------------------------------

⌨️ 快捷键说明

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