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

📄 wmlbeziertriangle3.cpp

📁 3D Game Engine Design Source Code非常棒
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// Magic Software, Inc.
// http://www.magic-software.com
// http://www.wild-magic.com
// Copyright (c) 2003.  All Rights Reserved
//
// The Wild Magic Library (WML) source code is supplied under the terms of
// the license agreement http://www.magic-software.com/License/WildMagic.pdf
// and may not be copied or disclosed except in accordance with the terms of
// that agreement.

#include "WmlBezierTriangle3.h"
#include "WmlTriMesh.h"
using namespace Wml;

WmlImplementRTTI(BezierTriangle3,BezierTriangle);
WmlImplementStream(BezierTriangle3);

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

//----------------------------------------------------------------------------
BezierTriangle3::BezierTriangle3 (int* aiIndex)
    :
    BezierTriangle(3,10,aiIndex)
{
}
//----------------------------------------------------------------------------
BezierTriangle3::BezierTriangle3 ()
{
}
//----------------------------------------------------------------------------
void BezierTriangle3::InitializePoints (const Vector3f* akCtrlPoint,
    BlockParameters& rkBP)
{
    // Xuu
    rkBP.m_aakXuu[0] = 6.0f*(XA(0) - 2.0f*XA(1) + XA(2));
    rkBP.m_aakXuu[1] = 6.0f*(XA(1) - 2.0f*XA(2) + XA(3));
    rkBP.m_aakXuu[2] = 6.0f*(XA(4) - 2.0f*XA(5) + XA(6));

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

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

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

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

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

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

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

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

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

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

    // Thh = Tuu - 2*Tuv + Tvv (d/dh = d/ds - d/dt)
    rkBP.m_aakThh[0] = 6.0f*(TA(2) - 2.0f*TA(5) + TA(7));
    rkBP.m_aakThh[1] = 6.0f*(TA(3) - 2.0f*TA(6) + TA(8));
    rkBP.m_aakThh[2] = 6.0f*(TA(6) - 2.0f*TA(8) + TA(9));
}
//----------------------------------------------------------------------------
void BezierTriangle3::Tessellate (int iLevel, const Vector3f* akCtrlPoint,
    const ColorRGB* akCtrlColor, const Vector2f* akCtrlTexture,
    TriMesh* pkMesh, int& riVertexStart, int& riTriangleStart)
{
    GenerateConnectivity(iLevel,pkMesh,riTriangleStart);

    // number of vertices in the subdivision
    int iQuantity = GetVerticesPerPatch(iLevel);

    // indices of three corners of patch, I0 (w=1), I1 (u=1), I2 (v=1)
    int iTwoPowL = (1 << iLevel);
    BlockParameters kBP;
    kBP.m_i0 = 0;
    kBP.m_i1 = iTwoPowL;
    kBP.m_i2 = iTwoPowL*(iTwoPowL + 3) >> 1;

    // vertices for subdivision
    Vector3f* akX = pkMesh->Vertices() + riVertexStart;
    akX[kBP.m_i0] = XA(0);
    akX[kBP.m_i1] = XA(3);
    akX[kBP.m_i2] = XA(9);

    // derivatives for subdivision (for normal vectors)
    Vector3f* akXu;
    Vector3f* akXv;
    if ( pkMesh->Normals() )
    {
        akXu = new Vector3f[iQuantity];
        akXu[kBP.m_i0] = 3.0f*(XA(1) - XA(0));
        akXu[kBP.m_i1] = 3.0f*(XA(3) - XA(2));
        akXu[kBP.m_i2] = 3.0f*(XA(8) - XA(7));

        akXv = new Vector3f[iQuantity];
        akXv[kBP.m_i0] = 3.0f*(XA(4) - XA(0));
        akXv[kBP.m_i1] = 3.0f*(XA(6) - XA(2));
        akXv[kBP.m_i2] = 3.0f*(XA(9) - XA(7));
    }
    else
    {
        akXu = NULL;
        akXv = NULL;
    }

    // colors for subdivision
    ColorRGB* akColor;
    if ( pkMesh->Colors() )
    {
        akColor = pkMesh->Colors() + riVertexStart;
        akColor[kBP.m_i0] = CA(0);
        akColor[kBP.m_i1] = CA(3);
        akColor[kBP.m_i2] = CA(9);
    }
    else
    {
        akColor = NULL;
    }

    // textures for subdivision
    Vector2f* akTexture;
    if ( pkMesh->Textures() )
    {
        akTexture = pkMesh->Textures() + riVertexStart;
        akTexture[kBP.m_i0] = TA(0);
        akTexture[kBP.m_i1] = TA(3);
        akTexture[kBP.m_i2] = TA(9);
    }
    else
    {
        akTexture = NULL;
    }

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

        if ( akXu )
            InitializeNormals(akCtrlPoint,kBP);

        if ( akCtrlColor )
            InitializeColors(akCtrlColor,kBP);

        if ( akCtrlTexture )
            InitializeTextures(akCtrlTexture,kBP);

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

    // calculate unit-length normals from derivative vectors
    if ( pkMesh->Normals() )
    {
        Vector3f* akNormal = pkMesh->Normals() + riVertexStart;
        for (int i = 0; i < iQuantity; i++)
            akNormal[i] = akXu[i].UnitCross(akXv[i]);
        delete[] akXu;
        delete[] akXv;
    }

    riVertexStart += iQuantity;
}
//----------------------------------------------------------------------------
void BezierTriangle3::SubdivideLL (int iLevel, float fDSqr, Vector3f* akX,
    Vector3f* akXu, Vector3f* akXv, ColorRGB* akColor, Vector2f* akTexture,
    BlockParameters& rkBP)
{
    /*
     i2
     +
     | \
     |   \
     +----+
     i0    i1
    */

    // subdivision indices
    int i01 = (rkBP.m_i0 + rkBP.m_i1) >> 1;
    int iD10 = rkBP.m_i1 - rkBP.m_i0;
    int i02 = (((rkBP.m_i0+rkBP.m_i2) << 2)+iD10*iD10) >> 3;
    int i12 = i02 + (iD10 >> 1);

    // vertices

    // bottom u-edge subdivision
    Vector3f kXuu01 = 0.5f*(rkBP.m_aakXuu[0] + rkBP.m_aakXuu[1]);
    Vector3f kXvv01 = 0.5f*(rkBP.m_aakXvv[0] + rkBP.m_aakXvv[1]);
    Vector3f kXhh01 = 0.5f*(rkBP.m_aakXhh[0] + rkBP.m_aakXhh[1]);
    akX[i01] = 0.5f*(akX[rkBP.m_i0] + akX[rkBP.m_i1] - fDSqr*kXuu01);

    // left v-edge subdivision
    Vector3f kXuu02 = 0.5f*(rkBP.m_aakXuu[0] + rkBP.m_aakXuu[2]);
    Vector3f kXvv02 = 0.5f*(rkBP.m_aakXvv[0] + rkBP.m_aakXvv[2]);
    Vector3f kXhh02 = 0.5f*(rkBP.m_aakXhh[0] + rkBP.m_aakXhh[2]);
    akX[i02] = 0.5f*(akX[rkBP.m_i0] + akX[rkBP.m_i2] - fDSqr*kXvv02);

    // hypotenuse edge subdivision
    Vector3f kXuu12 = 0.5f*(rkBP.m_aakXuu[1] + rkBP.m_aakXuu[2]);
    Vector3f kXvv12 = 0.5f*(rkBP.m_aakXvv[1] + rkBP.m_aakXvv[2]);
    Vector3f kXhh12 = 0.5f*(rkBP.m_aakXhh[1] + rkBP.m_aakXhh[2]);
    akX[i12] = 0.5f*(akX[rkBP.m_i1] + akX[rkBP.m_i2] - fDSqr*kXhh12);

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

        // left v-edge subdivision
        akXu[i02] = 0.5f*(akXu[rkBP.m_i0] + akXu[rkBP.m_i2] -
            fDSqr*rkBP.m_kXuvv);
        akXv[i02] = 0.5f*(akXv[rkBP.m_i0] + akXv[rkBP.m_i2] -
            fDSqr*rkBP.m_kXvvv);

        // hypotenuse edge subdivision
        akXu[i12] = 0.5f*(akXu[rkBP.m_i1] + akXu[rkBP.m_i2] -
            fDSqr*rkBP.m_kXhhu);
        akXv[i12] = 0.5f*(akXv[rkBP.m_i1] + akXv[rkBP.m_i2] -
            fDSqr*rkBP.m_kXhhv);
    }

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

        // left v-edge subdivision
        kCuu02 = 0.5f*(rkBP.m_aakCuu[0] + rkBP.m_aakCuu[2]);
        kCvv02 = 0.5f*(rkBP.m_aakCvv[0] + rkBP.m_aakCvv[2]);
        kChh02 = 0.5f*(rkBP.m_aakChh[0] + rkBP.m_aakChh[2]);
        akColor[i02] = 0.5f*(akColor[rkBP.m_i0] + akColor[rkBP.m_i2] -
            fDSqr*kCvv02);

        // hypotenuse edge subdivision
        kCuu12 = 0.5f*(rkBP.m_aakCuu[1] + rkBP.m_aakCuu[2]);
        kCvv12 = 0.5f*(rkBP.m_aakCvv[1] + rkBP.m_aakCvv[2]);
        kChh12 = 0.5f*(rkBP.m_aakChh[1] + rkBP.m_aakChh[2]);
        akColor[i12] = 0.5f*(akColor[rkBP.m_i1] + akColor[rkBP.m_i2] -
            fDSqr*kChh12);
    }

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

        // left v-edge subdivision
        kTuu02 = 0.5f*(rkBP.m_aakTuu[0] + rkBP.m_aakTuu[2]);
        kTvv02 = 0.5f*(rkBP.m_aakTvv[0] + rkBP.m_aakTvv[2]);
        kThh02 = 0.5f*(rkBP.m_aakThh[0] + rkBP.m_aakThh[2]);
        akTexture[i02] = 0.5f*(akTexture[rkBP.m_i0]+akTexture[rkBP.m_i2]
            - fDSqr*kTvv02);

        // hypotenuse edge subdivision
        kTuu12 = 0.5f*(rkBP.m_aakTuu[1] + rkBP.m_aakTuu[2]);
        kTvv12 = 0.5f*(rkBP.m_aakTvv[1] + rkBP.m_aakTvv[2]);
        kThh12 = 0.5f*(rkBP.m_aakThh[1] + rkBP.m_aakThh[2]);
        akTexture[i12] = 0.5f*(akTexture[rkBP.m_i1]+akTexture[rkBP.m_i2]
            - fDSqr*kThh12);
    }

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

        BlockParameters kSubBP;

        // subtriangle <(s0,t0),(sm,t0),(s0,tm)>
        kSubBP.m_i0 = rkBP.m_i0;
        kSubBP.m_i1 = i01;
        kSubBP.m_i2 = i02;
        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(iLevel,fDSqr,akX,akXu,akXv,akColor,akTexture,kSubBP);

        // subtriangle <(sm,t0),(s1,t0),(sm,tm)>
        kSubBP.m_i0 = i01;
        kSubBP.m_i1 = rkBP.m_i1;
        kSubBP.m_i2 = i12;
        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];
            kSubBP.m_aakThh[2] = kThh12;
        }

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

        // subtriangle <(s0,tm),(sm,tm),(s0,t1)>
        kSubBP.m_i0 = i02;
        kSubBP.m_i1 = i12;
        kSubBP.m_i2 = rkBP.m_i2;
        kSubBP.m_aakXuu[0] = kXuu02;
        kSubBP.m_aakXuu[1] = kXuu12;
        kSubBP.m_aakXuu[2] = rkBP.m_aakXuu[2];

⌨️ 快捷键说明

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