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

📄 mgcbeziercylinder3g.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 "MgcBezierCylinder3G.h"

//----------------------------------------------------------------------------
MgcBezierCylinder3G::MgcBezierCylinder3G (MgcVector3* akCtrlPoint)
    :
    MgcBezierCylinderG(3,akCtrlPoint)
{
}
//----------------------------------------------------------------------------
MgcVector3 MgcBezierCylinder3G::GetPosition (MgcReal fU, MgcReal fV) const
{
    MgcReal fOmU = 1.0 - fU, fU2 = fU*fU, fOmU2 = fOmU*fOmU;
    MgcReal afUCoeff[4] =
    {
        fOmU*fOmU2,
        3.0*fOmU2*fU,
        3.0*fOmU*fU2,
        fU*fU2
    };

    MgcReal fOmV = 1.0 - fV;

    MgcVector3 kB0 = MgcVector3::ZERO, kB1 = MgcVector3::ZERO;
    for (int iX = 0; iX < 4; iX++)
    {
        kB0 += afUCoeff[iX]*m_akCtrlPoint[iX];
        kB1 += afUCoeff[iX]*m_akCtrlPoint[iX + 4];
    }

    MgcVector3 kResult = fOmV*kB0 + fV*kB1;
    return kResult;
}
//----------------------------------------------------------------------------
MgcVector3 MgcBezierCylinder3G::GetDerivativeU (MgcReal fU, MgcReal fV) const
{
    MgcReal fOmU = 1.0 - fU, fU2 = fU*fU, fOmU2 = fOmU*fOmU;
    MgcReal afUCoeff[4] =
    {
        -3.0*fOmU2,
        3.0*fOmU*(fOmU - 2.0*fU),
        3.0*fU*(2.0*fOmU - fU),
        3.0*fU2
    };

    MgcReal fOmV = 1.0 - fV;

    MgcVector3 kB0 = MgcVector3::ZERO, kB1 = MgcVector3::ZERO;
    for (int iX = 0; iX < 4; iX++)
    {
        kB0 += afUCoeff[iX]*m_akCtrlPoint[iX];
        kB1 += afUCoeff[iX]*m_akCtrlPoint[iX + 4];
    }

    MgcVector3 kResult = fOmV*kB0 + fV*kB1;
    return kResult;
}
//----------------------------------------------------------------------------
MgcVector3 MgcBezierCylinder3G::GetDerivativeV (MgcReal fU, MgcReal fV) const
{
    MgcReal fOmU = 1.0 - fU, fU2 = fU*fU, fOmU2 = fOmU*fOmU;
    MgcReal afUCoeff[4] =
    {
        fOmU*fOmU2,
        3.0*fOmU2*fU,
        3.0*fOmU*fU2,
        fU*fU2
    };

    MgcVector3 kB0 = MgcVector3::ZERO, kB1 = MgcVector3::ZERO;
    for (int iX = 0; iX < 4; iX++)
    {
        kB0 += afUCoeff[iX]*m_akCtrlPoint[iX];
        kB1 += afUCoeff[iX]*m_akCtrlPoint[iX + 4];
    }

    MgcVector3 kResult = kB1 - kB0;
    return kResult;
}
//----------------------------------------------------------------------------
MgcVector3 MgcBezierCylinder3G::GetDerivativeUU (MgcReal fU, MgcReal fV) const
{
    MgcReal fOmU = 1.0 - fU;
    MgcReal afUCoeff[4] =
    {
        6.0*fOmU,
        6.0*(fU - 2.0*fOmU),
        6.0*(fOmU - 2.0*fU),
        6.0*fU
    };

    MgcReal fOmV = 1.0 - fV;

    MgcVector3 kB0 = MgcVector3::ZERO, kB1 = MgcVector3::ZERO;
    for (int iX = 0; iX < 4; iX++)
    {
        kB0 += afUCoeff[iX]*m_akCtrlPoint[iX];
        kB1 += afUCoeff[iX]*m_akCtrlPoint[iX + 4];
    }

    MgcVector3 kResult = fOmV*kB0 + fV*kB1;
    return kResult;
}
//----------------------------------------------------------------------------
MgcVector3 MgcBezierCylinder3G::GetDerivativeUV (MgcReal fU, MgcReal fV) const
{
    MgcReal fOmU = 1.0 - fU, fU2 = fU*fU, fOmU2 = fOmU*fOmU;
    MgcReal afUCoeff[4] =
    {
        -3.0*fOmU2,
        3.0*fOmU*(fOmU - 2.0*fU),
        3.0*fU*(2.0*fOmU - fU),
        3.0*fU2
    };

    MgcVector3 kB0 = MgcVector3::ZERO, kB1 = MgcVector3::ZERO;
    for (int iX = 0; iX < 4; iX++)
    {
        kB0 += afUCoeff[iX]*m_akCtrlPoint[iX];
        kB1 += afUCoeff[iX]*m_akCtrlPoint[iX + 4];
    }

    MgcVector3 kResult = kB1 - kB0;
    return kResult;
}
//----------------------------------------------------------------------------
MgcVector3 MgcBezierCylinder3G::GetDerivativeVV (MgcReal fU, MgcReal fV) const
{
    return MgcVector3::ZERO;
}
//----------------------------------------------------------------------------
void MgcBezierCylinder3G::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);
    unsigned int uiTwoPowC = (1 << m_uiCylinderLevel);
    IntervalParameters kIP;
    kIP.m_uiI00 = 0;
    kIP.m_uiI01 = uiTwoPowC*(uiTwoPowL + 1);
    kIP.m_uiI10 = uiTwoPowL;
    kIP.m_uiI11 = kIP.m_uiI01 + uiTwoPowL;

    // vertices for subdivision
    MgcVector3* akX = m_akVertex;
    akX[kIP.m_uiI00] = m_akCtrlPoint[0];
    akX[kIP.m_uiI01] = m_akCtrlPoint[4];
    akX[kIP.m_uiI10] = m_akCtrlPoint[3];
    akX[kIP.m_uiI11] = m_akCtrlPoint[7];

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

        akXv = new MgcVector3[m_uiVertexQuantity];
        akXv[kIP.m_uiI00] = 3.0*(m_akCtrlPoint[4] - m_akCtrlPoint[0]);
        akXv[kIP.m_uiI01] = akXv[kIP.m_uiI00];
        akXv[kIP.m_uiI10] = 3.0*(m_akCtrlPoint[7] - m_akCtrlPoint[3]);
        akXv[kIP.m_uiI11] = akXv[kIP.m_uiI10];
    }
    else
    {
        akXu = 0;
        akXv = 0;
    }

    // recursive subdivision
    MgcVector3 akXuuu[2];
    if ( uiLevel > 0 || m_uiCylinderLevel > 0 )
    {
        kIP.m_aakXuu[0][0] = 6.0*(m_akCtrlPoint[0] - 2.0*m_akCtrlPoint[1] +
            m_akCtrlPoint[2]);
        kIP.m_aakXuu[0][1] = 6.0*(m_akCtrlPoint[4] - 2.0*m_akCtrlPoint[5] +
            m_akCtrlPoint[6]);
        kIP.m_aakXuu[1][0] = 6.0*(m_akCtrlPoint[1] - 2.0*m_akCtrlPoint[2] +
            m_akCtrlPoint[3]);
        kIP.m_aakXuu[1][1] = 6.0*(m_akCtrlPoint[5] - 2.0*m_akCtrlPoint[6] +
            m_akCtrlPoint[7]);

        if ( akXu )
        {
            akXuuu[0] = 6.0*(m_akCtrlPoint[3] + 3.0*(m_akCtrlPoint[1] -
                m_akCtrlPoint[2]) - m_akCtrlPoint[0]);
            akXuuu[1] = 6.0*(m_akCtrlPoint[7] + 3.0*(m_akCtrlPoint[5] -
                m_akCtrlPoint[6]) - m_akCtrlPoint[4]);
        }
    }

    if ( uiLevel > 0 )
    {
        SubdivideBoundary(--uiLevel,0.25,akX,akXu,akXv,akXuuu,kIP);
    }

    if ( m_uiCylinderLevel > 0 )
    {
        SubdivideCylinder(m_uiCylinderLevel-1,akX,akXu,akXv,0,kIP.m_uiI01,
            uiTwoPowL);
    }

    // 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 MgcBezierCylinder3G::SubdivideBoundary (unsigned int uiLevel,
    MgcReal fDSqr, MgcVector3* akX, MgcVector3* akXu, MgcVector3* akXv,
    MgcVector3 akXuuu[2], IntervalParameters& rkIP)
{
    // subdivision indices
    unsigned int uiIM0 = (rkIP.m_uiI00 + rkIP.m_uiI10) >> 1;
    unsigned int uiIM1 = (rkIP.m_uiI01 + rkIP.m_uiI11) >> 1;

    // vertices
    MgcVector3 kXssM0 = 0.5*(rkIP.m_aakXuu[0][0] + rkIP.m_aakXuu[1][0]);
    MgcVector3 kXssM1 = 0.5*(rkIP.m_aakXuu[0][1] + rkIP.m_aakXuu[1][1]);
    akX[uiIM0] = 0.5*(akX[rkIP.m_uiI00] + akX[rkIP.m_uiI10] - fDSqr*kXssM0);
    akX[uiIM1] = 0.5*(akX[rkIP.m_uiI01] + akX[rkIP.m_uiI11] - fDSqr*kXssM1);

    // derivatives (for normal vectors)
    if ( akXu )
    {
        akXu[uiIM0] = 0.5*(akXu[rkIP.m_uiI00] + akXu[rkIP.m_uiI10] -
            fDSqr*akXuuu[0]);
        akXu[uiIM1] = 0.5*(akXu[rkIP.m_uiI01] + akXu[rkIP.m_uiI11] -
            fDSqr*akXuuu[1]);
        akXv[uiIM0] = akX[uiIM1] - akX[uiIM0];
        akXv[uiIM1] = akXv[uiIM0];
    }

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

        IntervalParameters kSubIP;

        // subinterval [u0,uM]
        kSubIP.m_uiI00 = rkIP.m_uiI00;
        kSubIP.m_uiI01 = rkIP.m_uiI01;
        kSubIP.m_uiI10 = uiIM0;
        kSubIP.m_uiI11 = uiIM1;

        kSubIP.m_aakXuu[0][0] = rkIP.m_aakXuu[0][0];
        kSubIP.m_aakXuu[0][1] = rkIP.m_aakXuu[0][1];
        kSubIP.m_aakXuu[1][0] = kXssM0;
        kSubIP.m_aakXuu[1][1] = kXssM1;

        SubdivideBoundary(uiLevel,fDSqr,akX,akXu,akXv,akXuuu,kSubIP);

        // subinterval [uM,u1]
        kSubIP.m_uiI00 = uiIM0;
        kSubIP.m_uiI01 = uiIM1;
        kSubIP.m_uiI10 = rkIP.m_uiI10;
        kSubIP.m_uiI11 = rkIP.m_uiI11;

        kSubIP.m_aakXuu[0][0] = kXssM0;
        kSubIP.m_aakXuu[0][1] = kXssM1;
        kSubIP.m_aakXuu[1][0] = rkIP.m_aakXuu[1][0];
        kSubIP.m_aakXuu[1][1] = rkIP.m_aakXuu[1][1];

        SubdivideBoundary(uiLevel,fDSqr,akX,akXu,akXv,akXuuu,kSubIP);
    }
}
//----------------------------------------------------------------------------
void MgcBezierCylinder3G::SubdivideCylinder (unsigned int uiCLevel,
    MgcVector3* akX, MgcVector3* akXu, MgcVector3* akXv, unsigned int uiI0,
    unsigned int uiI1, unsigned int uiTwoPowL)
{
    // subdivision index
    unsigned int uiIM = (uiI0 + uiI1) >> 1;

    unsigned int uiJ0 = uiI0, uiJM = uiIM, uiJ1 = uiI1;
    unsigned int uiJLast = uiJM + uiTwoPowL;
    for (/**/; uiJM <= uiJLast; uiJ0++, uiJM++, uiJ1++)
    {
        // vertices
        akX[uiJM] = 0.5*(akX[uiJ0] + akX[uiJ1]);

        // derivatives (for normal vectors)
        if ( akXu )
        {
            akXu[uiJM] = 0.5*(akXu[uiJ0] + akXu[uiJ1]);
            akXv[uiJM] = akXv[uiJ0];
        }
    }

    // recurse on two children
    if ( uiCLevel > 0 )
    {
        uiCLevel--;

        // subinterval [v0,vM]
        SubdivideCylinder(uiCLevel,akX,akXu,akXv,uiI0,uiIM,uiTwoPowL);

        // subinterval [vM,v1]
        SubdivideCylinder(uiCLevel,akX,akXu,akXv,uiIM,uiI1,uiTwoPowL);
    }
}
//----------------------------------------------------------------------------

⌨️ 快捷键说明

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