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

📄 mgcbeziertriangle3.cpp

📁 《3D游戏引擎设计》的源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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
//
// RESTRICTED USE SOURCE CODE
// http://www.magic-software.com/License/restricted.pdf

#include "MgcBezierTriangle3.h"
#include "MgcTriMesh.h"

MgcImplementRTTI(MgcBezierTriangle3,MgcBezierTriangle);
MgcImplementStream(MgcBezierTriangle3);

// macros for initialization in the subdivision
#define XA(i) akCtrlPoint[m_auiIndex[i]]
#define CA(i) akCtrlColor[m_auiIndex[i]]
#define TA(i) akCtrlTexture[m_auiIndex[i]]

//----------------------------------------------------------------------------
MgcBezierTriangle3::MgcBezierTriangle3 (unsigned int* auiIndex)
    :
    MgcBezierTriangle(3,10,auiIndex)
{
}
//----------------------------------------------------------------------------
MgcBezierTriangle3::MgcBezierTriangle3 ()
{
}
//----------------------------------------------------------------------------
void MgcBezierTriangle3::InitializePoints (const MgcVector3* akCtrlPoint,
    BlockParameters& rkBP)
{
    // Xuu
    rkBP.m_aakXuu[0] = 6.0*(XA(0) - 2.0*XA(1) + XA(2));
    rkBP.m_aakXuu[1] = 6.0*(XA(1) - 2.0*XA(2) + XA(3));
    rkBP.m_aakXuu[2] = 6.0*(XA(4) - 2.0*XA(5) + XA(6));

    // Xvv
    rkBP.m_aakXvv[0] = 6.0*(XA(0) - 2.0*XA(4) + XA(7));
    rkBP.m_aakXvv[1] = 6.0*(XA(1) - 2.0*XA(5) + XA(8));
    rkBP.m_aakXvv[2] = 6.0*(XA(4) - 2.0*XA(7) + XA(9));

    // Xhh = Xuu - 2*Xuv + Xvv (d/dh = d/ds - d/dt)
    rkBP.m_aakXhh[0] = 6.0*(XA(2) - 2.0*XA(5) + XA(7));
    rkBP.m_aakXhh[1] = 6.0*(XA(3) - 2.0*XA(6) + XA(8));
    rkBP.m_aakXhh[2] = 6.0*(XA(6) - 2.0*XA(8) + XA(9));
}
//----------------------------------------------------------------------------
void MgcBezierTriangle3::InitializeNormals (const MgcVector3* akCtrlPoint,
    BlockParameters& rkBP)
{
    // Xuuu
    rkBP.m_kXuuu = 6.0*(XA(3) - XA(0) + 2.0*(XA(1) - XA(2)));

    // Xuuv
    rkBP.m_kXuuv = 6.0*(XA(4) + XA(6) - XA(0) - XA(2) + 2.0*(XA(1) - XA(5)));

    // Xuvv
    rkBP.m_kXuvv = 6.0*(XA(1) + XA(8) - XA(0) - XA(7) + 2.0*(XA(4) - XA(5)));

    // Xvvv
    rkBP.m_kXvvv = 6.0*(XA(9) - XA(0) + 2.0*(XA(4) - XA(7)));

    // Xhhu
    rkBP.m_kXhhu = 6.0*(XA(3) + XA(8) - XA(2) - XA(7) + 2.0*(XA(5) - XA(6)));

    // Xhhv
    rkBP.m_kXhhv = 6.0*(XA(6) + XA(9) - XA(2) - XA(7) + 2.0*(XA(5) - XA(8)));
}
//----------------------------------------------------------------------------
void MgcBezierTriangle3::InitializeColors (const MgcColor* akCtrlColor,
    BlockParameters& rkBP)
{
    // Cuu
    rkBP.m_aakCuu[0] = 6.0*(CA(0) - 2.0*CA(1) + CA(2));
    rkBP.m_aakCuu[1] = 6.0*(CA(1) - 2.0*CA(2) + CA(3));
    rkBP.m_aakCuu[2] = 6.0*(CA(4) - 2.0*CA(5) + CA(6));

    // Cvv
    rkBP.m_aakCvv[0] = 6.0*(CA(0) - 2.0*CA(4) + CA(7));
    rkBP.m_aakCvv[1] = 6.0*(CA(1) - 2.0*CA(5) + CA(8));
    rkBP.m_aakCvv[2] = 6.0*(CA(4) - 2.0*CA(7) + CA(9));

    // Chh = Cuu - 2*Cuv + Cvv (d/dh = d/ds - d/dt)
    rkBP.m_aakChh[0] = 6.0*(CA(2) - 2.0*CA(5) + CA(7));
    rkBP.m_aakChh[1] = 6.0*(CA(3) - 2.0*CA(6) + CA(8));
    rkBP.m_aakChh[2] = 6.0*(CA(6) - 2.0*CA(8) + CA(9));
}
//----------------------------------------------------------------------------
void MgcBezierTriangle3::InitializeTextures (const MgcVector2* akCtrlTexture,
    BlockParameters& rkBP)
{
    // Tuu
    rkBP.m_aakTuu[0] = 6.0*(TA(0) - 2.0*TA(1) + TA(2));
    rkBP.m_aakTuu[1] = 6.0*(TA(1) - 2.0*TA(2) + TA(3));
    rkBP.m_aakTuu[2] = 6.0*(TA(4) - 2.0*TA(5) + TA(6));

    // Tvv
    rkBP.m_aakTvv[0] = 6.0*(TA(0) - 2.0*TA(4) + TA(7));
    rkBP.m_aakTvv[1] = 6.0*(TA(1) - 2.0*TA(5) + TA(8));
    rkBP.m_aakTvv[2] = 6.0*(TA(4) - 2.0*TA(7) + TA(9));

    // Thh = Tuu - 2*Tuv + Tvv (d/dh = d/ds - d/dt)
    rkBP.m_aakThh[0] = 6.0*(TA(2) - 2.0*TA(5) + TA(7));
    rkBP.m_aakThh[1] = 6.0*(TA(3) - 2.0*TA(6) + TA(8));
    rkBP.m_aakThh[2] = 6.0*(TA(6) - 2.0*TA(8) + TA(9));
}
//----------------------------------------------------------------------------
void MgcBezierTriangle3::Tessellate (unsigned int uiLevel,
    const MgcVector3* akCtrlPoint, const MgcColor* akCtrlColor,
    const MgcVector2* akCtrlTexture, MgcTriMesh* pkMesh,
    unsigned int& ruiVertexStart, unsigned int& ruiTriangleStart)
{
    GenerateConnectivity(uiLevel,pkMesh,ruiTriangleStart);

    // number of vertices in the subdivision
    unsigned int uiQuantity = GetVerticesPerTrianglePatch(uiLevel);

    // indices of three corners of patch, I0 (w=1), I1 (u=1), I2 (v=1)
    unsigned int uiTwoPowL = (1 << uiLevel);
    BlockParameters kBP;
    kBP.m_uiI0 = 0;
    kBP.m_uiI1 = uiTwoPowL;
    kBP.m_uiI2 = uiTwoPowL*(uiTwoPowL + 3) >> 1;

    // vertices for subdivision
    MgcVector3* akX = pkMesh->Vertices() + ruiVertexStart;
    akX[kBP.m_uiI0] = XA(0);
    akX[kBP.m_uiI1] = XA(3);
    akX[kBP.m_uiI2] = XA(9);

    // derivatives for subdivision (for normal vectors)
    MgcVector3* akXu;
    MgcVector3* akXv;
    if ( pkMesh->Normals() )
    {
        akXu = new MgcVector3[uiQuantity];
        akXu[kBP.m_uiI0] = 3.0*(XA(1) - XA(0));
        akXu[kBP.m_uiI1] = 3.0*(XA(3) - XA(2));
        akXu[kBP.m_uiI2] = 3.0*(XA(8) - XA(7));

        akXv = new MgcVector3[uiQuantity];
        akXv[kBP.m_uiI0] = 3.0*(XA(4) - XA(0));
        akXv[kBP.m_uiI1] = 3.0*(XA(6) - XA(2));
        akXv[kBP.m_uiI2] = 3.0*(XA(9) - XA(7));
    }
    else
    {
        akXu = 0;
        akXv = 0;
    }

    // colors for subdivision
    MgcColor* akColor;
    if ( pkMesh->Colors() )
    {
        akColor = pkMesh->Colors() + ruiVertexStart;
        akColor[kBP.m_uiI0] = CA(0);
        akColor[kBP.m_uiI1] = CA(3);
        akColor[kBP.m_uiI2] = CA(9);
    }
    else
    {
        akColor = 0;
    }

    // textures for subdivision
    MgcVector2* akTexture;
    if ( pkMesh->Textures() )
    {
        akTexture = pkMesh->Textures() + ruiVertexStart;
        akTexture[kBP.m_uiI0] = TA(0);
        akTexture[kBP.m_uiI1] = TA(3);
        akTexture[kBP.m_uiI2] = TA(9);
    }
    else
    {
        akTexture = 0;
    }

    // recursive subdivision
    if ( uiLevel > 0 )
    {
        InitializePoints(akCtrlPoint,kBP);

        if ( akXu )
            InitializeNormals(akCtrlPoint,kBP);

        if ( akCtrlColor )
            InitializeColors(akCtrlColor,kBP);

        if ( akCtrlTexture )
            InitializeTextures(akCtrlTexture,kBP);

        SubdivideLL(--uiLevel,0.25,akX,akXu,akXv,akColor,akTexture,kBP);
    }

    // calculate unit-length normals from derivative vectors
    if ( pkMesh->Normals() )
    {
        MgcVector3* akNormal = pkMesh->Normals() + ruiVertexStart;
        for (unsigned int uiI = 0; uiI < uiQuantity; uiI++)
            akNormal[uiI] = akXu[uiI].UnitCross(akXv[uiI]);
        delete[] akXu;
        delete[] akXv;
    }

    ruiVertexStart += uiQuantity;
}
//----------------------------------------------------------------------------
void MgcBezierTriangle3::SubdivideLL (unsigned int uiLevel, MgcReal fDSqr,
    MgcVector3* akX, MgcVector3* akXu, MgcVector3* akXv, MgcColor* akColor,
    MgcVector2* akTexture, BlockParameters& rkBP)
{
    /*
     i2
     +
     | \
     |   \
     +----+
     i0    i1
    */

    // subdivision indices
    unsigned int uiI01 = (rkBP.m_uiI0 + rkBP.m_uiI1) >> 1;
    unsigned int uiD10 = rkBP.m_uiI1 - rkBP.m_uiI0;
    unsigned int uiI02 = (((rkBP.m_uiI0+rkBP.m_uiI2) << 2)+uiD10*uiD10) >> 3;
    unsigned int uiI12 = uiI02 + (uiD10 >> 1);

    // vertices

    // bottom u-edge subdivision
    MgcVector3 kXuu01 = 0.5*(rkBP.m_aakXuu[0] + rkBP.m_aakXuu[1]);
    MgcVector3 kXvv01 = 0.5*(rkBP.m_aakXvv[0] + rkBP.m_aakXvv[1]);
    MgcVector3 kXhh01 = 0.5*(rkBP.m_aakXhh[0] + rkBP.m_aakXhh[1]);
    akX[uiI01] = 0.5*(akX[rkBP.m_uiI0] + akX[rkBP.m_uiI1] - fDSqr*kXuu01);

    // left v-edge subdivision
    MgcVector3 kXuu02 = 0.5*(rkBP.m_aakXuu[0] + rkBP.m_aakXuu[2]);
    MgcVector3 kXvv02 = 0.5*(rkBP.m_aakXvv[0] + rkBP.m_aakXvv[2]);
    MgcVector3 kXhh02 = 0.5*(rkBP.m_aakXhh[0] + rkBP.m_aakXhh[2]);
    akX[uiI02] = 0.5*(akX[rkBP.m_uiI0] + akX[rkBP.m_uiI2] - fDSqr*kXvv02);

    // hypotenuse edge subdivision
    MgcVector3 kXuu12 = 0.5*(rkBP.m_aakXuu[1] + rkBP.m_aakXuu[2]);
    MgcVector3 kXvv12 = 0.5*(rkBP.m_aakXvv[1] + rkBP.m_aakXvv[2]);
    MgcVector3 kXhh12 = 0.5*(rkBP.m_aakXhh[1] + rkBP.m_aakXhh[2]);
    akX[uiI12] = 0.5*(akX[rkBP.m_uiI1] + akX[rkBP.m_uiI2] - fDSqr*kXhh12);

    // derivatives (for normal vectors)
    if ( akXu )
    {
        // bottom u-edge subdivision
        akXu[uiI01] = 0.5*(akXu[rkBP.m_uiI0] + akXu[rkBP.m_uiI1] -
            fDSqr*rkBP.m_kXuuu);
        akXv[uiI01] = 0.5*(akXv[rkBP.m_uiI0] + akXv[rkBP.m_uiI1] -
            fDSqr*rkBP.m_kXuuv);

        // left v-edge subdivision
        akXu[uiI02] = 0.5*(akXu[rkBP.m_uiI0] + akXu[rkBP.m_uiI2] -
            fDSqr*rkBP.m_kXuvv);
        akXv[uiI02] = 0.5*(akXv[rkBP.m_uiI0] + akXv[rkBP.m_uiI2] -
            fDSqr*rkBP.m_kXvvv);

        // hypotenuse edge subdivision
        akXu[uiI12] = 0.5*(akXu[rkBP.m_uiI1] + akXu[rkBP.m_uiI2] -
            fDSqr*rkBP.m_kXhhu);
        akXv[uiI12] = 0.5*(akXv[rkBP.m_uiI1] + akXv[rkBP.m_uiI2] -
            fDSqr*rkBP.m_kXhhv);
    }

    // colors
    MgcColor kCuu01, kCvv01, kChh01, kCuu02, kCvv02, kChh02, kCuu12, kCvv12,
        kChh12;
    if ( akColor )
    {
        // bottom u-edge subdivision
        kCuu01 = 0.5*(rkBP.m_aakCuu[0] + rkBP.m_aakCuu[1]);
        kCvv01 = 0.5*(rkBP.m_aakCvv[0] + rkBP.m_aakCvv[1]);
        kChh01 = 0.5*(rkBP.m_aakChh[0] + rkBP.m_aakChh[1]);
        akColor[uiI01] = 0.5*(akColor[rkBP.m_uiI0] + akColor[rkBP.m_uiI1] -
            fDSqr*kCuu01);

        // left v-edge subdivision
        kCuu02 = 0.5*(rkBP.m_aakCuu[0] + rkBP.m_aakCuu[2]);
        kCvv02 = 0.5*(rkBP.m_aakCvv[0] + rkBP.m_aakCvv[2]);
        kChh02 = 0.5*(rkBP.m_aakChh[0] + rkBP.m_aakChh[2]);
        akColor[uiI02] = 0.5*(akColor[rkBP.m_uiI0] + akColor[rkBP.m_uiI2] -
            fDSqr*kCvv02);

        // hypotenuse edge subdivision
        kCuu12 = 0.5*(rkBP.m_aakCuu[1] + rkBP.m_aakCuu[2]);
        kCvv12 = 0.5*(rkBP.m_aakCvv[1] + rkBP.m_aakCvv[2]);
        kChh12 = 0.5*(rkBP.m_aakChh[1] + rkBP.m_aakChh[2]);
        akColor[uiI12] = 0.5*(akColor[rkBP.m_uiI1] + akColor[rkBP.m_uiI2] -
            fDSqr*kChh12);
    }

    // textures
    MgcVector2 kTuu01, kTvv01, kThh01, kTuu02, kTvv02, kThh02, kTuu12, kTvv12,
        kThh12;
    if ( akTexture )
    {
        // bottom u-edge subdivision
        kTuu01 = 0.5*(rkBP.m_aakTuu[0] + rkBP.m_aakTuu[1]);
        kTvv01 = 0.5*(rkBP.m_aakTvv[0] + rkBP.m_aakTvv[1]);
        kThh01 = 0.5*(rkBP.m_aakThh[0] + rkBP.m_aakThh[1]);
        akTexture[uiI01] = 0.5*(akTexture[rkBP.m_uiI0]+akTexture[rkBP.m_uiI1]
            - fDSqr*kTuu01);

        // left v-edge subdivision
        kTuu02 = 0.5*(rkBP.m_aakTuu[0] + rkBP.m_aakTuu[2]);
        kTvv02 = 0.5*(rkBP.m_aakTvv[0] + rkBP.m_aakTvv[2]);
        kThh02 = 0.5*(rkBP.m_aakThh[0] + rkBP.m_aakThh[2]);
        akTexture[uiI02] = 0.5*(akTexture[rkBP.m_uiI0]+akTexture[rkBP.m_uiI2]
            - fDSqr*kTvv02);

        // hypotenuse edge subdivision
        kTuu12 = 0.5*(rkBP.m_aakTuu[1] + rkBP.m_aakTuu[2]);
        kTvv12 = 0.5*(rkBP.m_aakTvv[1] + rkBP.m_aakTvv[2]);
        kThh12 = 0.5*(rkBP.m_aakThh[1] + rkBP.m_aakThh[2]);
        akTexture[uiI12] = 0.5*(akTexture[rkBP.m_uiI1]+akTexture[rkBP.m_uiI2]
            - fDSqr*kThh12);
    }

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

        BlockParameters kSubBP;

        // subtriangle <(s0,t0),(sm,t0),(s0,tm)>
        kSubBP.m_uiI0 = rkBP.m_uiI0;
        kSubBP.m_uiI1 = uiI01;
        kSubBP.m_uiI2 = uiI02;
        kSubBP.m_aakXuu[0] = rkBP.m_aakXuu[0];
        kSubBP.m_aakXuu[1] = kXuu01;
        kSubBP.m_aakXuu[2] = kXuu02;
        kSubBP.m_aakXvv[0] = rkBP.m_aakXvv[0];
        kSubBP.m_aakXvv[1] = kXvv01;
        kSubBP.m_aakXvv[2] = kXvv02;
        kSubBP.m_aakXhh[0] = rkBP.m_aakXhh[0];
        kSubBP.m_aakXhh[1] = kXhh01;
        kSubBP.m_aakXhh[2] = kXhh02;

        if ( akColor )
        {
            kSubBP.m_aakCuu[0] = rkBP.m_aakCuu[0];
            kSubBP.m_aakCuu[1] = kCuu01;
            kSubBP.m_aakCuu[2] = kCuu02;
            kSubBP.m_aakCvv[0] = rkBP.m_aakCvv[0];
            kSubBP.m_aakCvv[1] = kCvv01;
            kSubBP.m_aakCvv[2] = kCvv02;
            kSubBP.m_aakChh[0] = rkBP.m_aakChh[0];
            kSubBP.m_aakChh[1] = kChh01;
            kSubBP.m_aakChh[2] = kChh02;
        }

        if ( akTexture )
        {
            kSubBP.m_aakTuu[0] = rkBP.m_aakTuu[0];
            kSubBP.m_aakTuu[1] = kTuu01;
            kSubBP.m_aakTuu[2] = kTuu02;
            kSubBP.m_aakTvv[0] = rkBP.m_aakTvv[0];
            kSubBP.m_aakTvv[1] = kTvv01;
            kSubBP.m_aakTvv[2] = kTvv02;
            kSubBP.m_aakThh[0] = rkBP.m_aakThh[0];
            kSubBP.m_aakThh[1] = kThh01;
            kSubBP.m_aakThh[2] = kThh02;
        }

        SubdivideLL(uiLevel,fDSqr,akX,akXu,akXv,akColor,akTexture,kSubBP);

        // subtriangle <(sm,t0),(s1,t0),(sm,tm)>
        kSubBP.m_uiI0 = uiI01;
        kSubBP.m_uiI1 = rkBP.m_uiI1;
        kSubBP.m_uiI2 = uiI12;
        kSubBP.m_aakXuu[0] = kXuu01;
        kSubBP.m_aakXuu[1] = rkBP.m_aakXuu[1];
        kSubBP.m_aakXuu[2] = kXuu12;
        kSubBP.m_aakXvv[0] = kXvv01;
        kSubBP.m_aakXvv[1] = rkBP.m_aakXvv[1];
        kSubBP.m_aakXvv[2] = kXvv12;
        kSubBP.m_aakXhh[0] = kXhh01;
        kSubBP.m_aakXhh[1] = rkBP.m_aakXhh[1];
        kSubBP.m_aakXhh[2] = kXhh12;

        if ( akColor )
        {
            kSubBP.m_aakCuu[0] = kCuu01;
            kSubBP.m_aakCuu[1] = rkBP.m_aakCuu[1];
            kSubBP.m_aakCuu[2] = kCuu12;
            kSubBP.m_aakCvv[0] = kCvv01;
            kSubBP.m_aakCvv[1] = rkBP.m_aakCvv[1];
            kSubBP.m_aakCvv[2] = kCvv12;
            kSubBP.m_aakChh[0] = kChh01;
            kSubBP.m_aakChh[1] = rkBP.m_aakChh[1];
            kSubBP.m_aakChh[2] = kChh12;
        }

        if ( akTexture )
        {
            kSubBP.m_aakTuu[0] = kTuu01;
            kSubBP.m_aakTuu[1] = rkBP.m_aakTuu[1];
            kSubBP.m_aakTuu[2] = kTuu12;
            kSubBP.m_aakTvv[0] = kTvv01;
            kSubBP.m_aakTvv[1] = rkBP.m_aakTvv[1];
            kSubBP.m_aakTvv[2] = kTvv12;
            kSubBP.m_aakThh[0] = kThh01;
            kSubBP.m_aakThh[1] = rkBP.m_aakThh[1];

⌨️ 快捷键说明

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