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

📄 wmlbeziertriangle2.cpp

📁 3D Game Engine Design Source Code非常棒
💻 CPP
字号:
// 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 "WmlBezierTriangle2.h"
#include "WmlTriMesh.h"
using namespace Wml;

WmlImplementRTTI(BezierTriangle2,BezierTriangle);
WmlImplementStream(BezierTriangle2);

// 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]]

//----------------------------------------------------------------------------
BezierTriangle2::BezierTriangle2 (int* aiIndex)
    :
    BezierTriangle(2,6,aiIndex)
{
}
//----------------------------------------------------------------------------
BezierTriangle2::BezierTriangle2 ()
{
}
//----------------------------------------------------------------------------
void BezierTriangle2::InitializePoints (const Vector3f* akCtrlPoint,
    BlockParameters& rkBP)
{
    // Xuu
    rkBP.m_kXuu = 2.0f*(XA(0) - 2.0f*XA(1) + XA(2));

    // Xvv
    rkBP.m_kXvv = 2.0f*(XA(0) - 2.0f*XA(3) + XA(5));

    // Xhh = Xuu - 2*Xuv + Xvv (d/dh = d/ds - d/dt)
    rkBP.m_kXhh = 2.0f*(XA(0) + XA(4) - XA(1) - XA(3));
}
//----------------------------------------------------------------------------
void BezierTriangle2::InitializeColors (const ColorRGB* akCtrlColor,
    BlockParameters& rkBP)
{
    // Cuu
    rkBP.m_kCuu = 2.0f*(CA(0) - 2.0f*CA(1) + CA(2));

    // Cvv
    rkBP.m_kCvv = 2.0f*(CA(0) - 2.0f*CA(3) + CA(5));

    // Chh = Cuu - 2*Cuv + Cvv (d/dh = d/ds - d/dt)
    rkBP.m_kChh = 2.0f*(CA(0) + CA(4) - CA(1) - CA(3));
}
//----------------------------------------------------------------------------
void BezierTriangle2::InitializeTextures (const Vector2f* akCtrlTexture,
    BlockParameters& rkBP)
{
    // Tuu
    rkBP.m_kTuu = 2.0f*(TA(0) - 2.0f*TA(1) + TA(2));

    // Tvv
    rkBP.m_kTvv = 2.0f*(TA(0) - 2.0f*TA(3) + TA(5));

    // Thh = Tuu - 2*Tuv + Tvv (d/dh = d/ds - d/dt)
    rkBP.m_kThh = 2.0f*(TA(0) + TA(4) - TA(1) - TA(3));
}
//----------------------------------------------------------------------------
void BezierTriangle2::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);
    int i0 = 0;
    int i1 = iTwoPowL;
    int i2 = iTwoPowL*(iTwoPowL + 3) >> 1;

    BlockParameters kBP;

    // vertices for subdivision
    Vector3f* akX = pkMesh->Vertices() + riVertexStart;
    akX[i0] = XA(0);
    akX[i1] = XA(2);
    akX[i2] = XA(5);

    // derivatives for subdivision (for normal vectors)
    Vector3f* akXu;
    Vector3f* akXv;
    if ( pkMesh->Normals() )
    {
        akXu = new Vector3f[iQuantity];
        akXu[i0] = 2.0f*(XA(1) - XA(0));
        akXu[i1] = 2.0f*(XA(2) - XA(1));
        akXu[i2] = 2.0f*(XA(4) - XA(3));

        akXv = new Vector3f[iQuantity];
        akXv[i0] = 2.0f*(XA(3) - XA(0));
        akXv[i1] = 2.0f*(XA(5) - XA(3));
        akXv[i2] = 2.0f*(XA(4) - XA(1));
    }
    else
    {
        akXu = NULL;
        akXv = NULL;
    }

    // colors for subdivision
    ColorRGB* akColor;
    if ( pkMesh->Colors() )
    {
        akColor = pkMesh->Colors() + riVertexStart;
        akColor[i0] = CA(0);
        akColor[i1] = CA(2);
        akColor[i2] = CA(5);
    }
    else
    {
        akColor = NULL;
    }

    // textures for subdivision
    Vector2f* akTexture;
    if ( pkMesh->Textures() )
    {
        akTexture = pkMesh->Textures() + riVertexStart;
        akTexture[i0] = TA(0);
        akTexture[i1] = TA(2);
        akTexture[i2] = TA(5);
    }
    else
    {
        akTexture = NULL;
    }

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

        if ( akCtrlColor )
            InitializeColors(akCtrlColor,kBP);

        if ( akCtrlTexture )
            InitializeTextures(akCtrlTexture,kBP);

        SubdivideLL(--iLevel,0.25f,akX,akXu,akXv,akColor,akTexture,i0,i1,i2,
            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 BezierTriangle2::SubdivideLL (int iLevel, float fDSqr, Vector3f* akX,
    Vector3f* akXu, Vector3f* akXv, ColorRGB* akColor, Vector2f* akTexture,
    int i0, int i1, int i2, BlockParameters& rkBP)
{
    /*
     i2
     +
     | \
     |   \
     +----+
     i0    i1
    */

    // subdivision indices
    int i01 = (i0 + i1) >> 1;
    int iD10 = i1 - i0;
    int i02 = (((i0 + i2) << 2) + iD10*iD10) >> 3;
    int i12 = i02 + (iD10 >> 1);

    // vertices

    // bottom u-edge subdivision
    akX[i01] = 0.5f*(akX[i0] + akX[i1] - fDSqr*rkBP.m_kXuu);

    // left v-edge subdivision
    akX[i02] = 0.5f*(akX[i0] + akX[i2] - fDSqr*rkBP.m_kXvv);

    // hypotenuse edge subdivision
    akX[i12] = 0.5f*(akX[i1] + akX[i2] - fDSqr*rkBP.m_kXhh);

    // derivatives (for normal vectors)
    if ( akXu )
    {
        // bottom u-edge subdivision
        akXu[i01] = 0.5f*(akXu[i0] + akXu[i1]);
        akXv[i01] = 0.5f*(akXv[i0] + akXv[i1]);

        // left v-edge subdivision
        akXu[i02] = 0.5f*(akXu[i0] + akXu[i2]);
        akXv[i02] = 0.5f*(akXv[i0] + akXv[i2]);

        // hypotenuse edge subdivision
        akXu[i12] = 0.5f*(akXu[i1] + akXu[i2]);
        akXv[i12] = 0.5f*(akXv[i1] + akXv[i2]);
    }

    // colors
    if ( akColor )
    {
        // bottom u-edge subdivision
        akColor[i01] = 0.5f*(akColor[i0] + akColor[i1] - fDSqr*rkBP.m_kCuu);

        // left v-edge subdivision
        akColor[i02] = 0.5f*(akColor[i0] + akColor[i2] - fDSqr*rkBP.m_kCvv);

        // hypotenuse edge subdivision
        akColor[i12] = 0.5f*(akColor[i1] + akColor[i2] - fDSqr*rkBP.m_kChh);
    }

    // textures
    if ( akTexture )
    {
        // bottom u-edge subdivision
        akTexture[i01] = 0.5f*(akTexture[i0]+akTexture[i1]-fDSqr*rkBP.m_kTuu);

        // left v-edge subdivision
        akTexture[i02] = 0.5f*(akTexture[i0]+akTexture[i2]-fDSqr*rkBP.m_kTvv);

        // hypotenuse edge subdivision
        akTexture[i12] = 0.5f*(akTexture[i1]+akTexture[i2]-fDSqr*rkBP.m_kThh);
    }

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

        // subtriangle <(s0,t0),(sm,t0),(s0,tm)>
        SubdivideLL(iLevel,fDSqr,akX,akXu,akXv,akColor,akTexture,i0,i01,i02,
            rkBP);

        // subtriangle <(sm,t0),(s1,t0),(sm,tm)>
        SubdivideLL(iLevel,fDSqr,akX,akXu,akXv,akColor,akTexture,i01,i1,i12,
            rkBP);

        // subtriangle <(s0,tm),(sm,tm),(s0,t1)>
        SubdivideLL(iLevel,fDSqr,akX,akXu,akXv,akColor,akTexture,i02,i12,i2,
            rkBP);

        // subtriangle <(sm,t0),(sm,tm),(s0,tm)>
        SubdivideUR(iLevel,fDSqr,akX,akXu,akXv,akColor,akTexture,i01,i12,i02,
            rkBP);
    }
}
//----------------------------------------------------------------------------
void BezierTriangle2::SubdivideUR (int iLevel, float fDSqr, Vector3f* akX,
    Vector3f* akXu, Vector3f* akXv, ColorRGB* akColor, Vector2f* akTexture,
    int i0, int i1, int i2, BlockParameters& rkBP)
{
    /*
     i2   i1
     +----+
       \  |
         \|
          +
          i0
    */

    // subdivision indices
    int i12 = (i1 + i2) >> 1;
    int iD12 = i1 - i2;
    int i01 = (((i0 + i1) << 2) + iD12*iD12) >> 3;
    int i02 = i01 - (iD12 >> 1);

    // vertices

    // top u-edge subdivision
    akX[i12] = 0.5f*(akX[i1] + akX[i2] - fDSqr*rkBP.m_kXuu);

    // right v-edge subdivision
    akX[i01] = 0.5f*(akX[i0] + akX[i1] - fDSqr*rkBP.m_kXvv);

    // hypotenuse edge subdivision
    akX[i02] = 0.5f*(akX[i0] + akX[i2] - fDSqr*rkBP.m_kXhh);

    // colors
    if ( akColor )
    {
        // top u-edge subdivision
        akColor[i12] = 0.5f*(akColor[i1] + akColor[i2] - fDSqr*rkBP.m_kCuu);

        // right v-edge subdivision
        akColor[i01] = 0.5f*(akColor[i0] + akColor[i1] - fDSqr*rkBP.m_kCvv);

        // hypotenuse edge subdivision
        akColor[i02] = 0.5f*(akColor[i0] + akColor[i2] - fDSqr*rkBP.m_kChh);
    }

    // textures
    if ( akTexture )
    {
        // top u-edge subdivision
        akTexture[i12] = 0.5f*(akTexture[i1]+akTexture[i2]-fDSqr*rkBP.m_kTuu);

        // right v-edge subdivision
        akTexture[i01] = 0.5f*(akTexture[i0]+akTexture[i1]-fDSqr*rkBP.m_kTvv);

        // hypotenuse edge subdivision
        akTexture[i02] = 0.5f*(akTexture[i0]+akTexture[i2]-fDSqr*rkBP.m_kThh);
    }

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

        // subtriangle <(sm,tm),(sm,t1),(s0,t1)>
        SubdivideUR(iLevel,fDSqr,akX,akXu,akXv,akColor,akTexture,i02,i12,i2,
            rkBP);

        // subtriangle <(s1,tm),(s1,t1),(sm,t1)>
        SubdivideUR(iLevel,fDSqr,akX,akXu,akXv,akColor,akTexture,i01,i1,i12,
            rkBP);

        // subtriangle <(s1,t0),(s1,tm),(sm,tm)>
        SubdivideUR(iLevel,fDSqr,akX,akXu,akXv,akColor,akTexture,i0,i01,i02,
            rkBP);

        // subtriangle <(sm,tm),(s1,tm),(sm,t1)>
        SubdivideLL(iLevel,fDSqr,akX,akXu,akXv,akColor,akTexture,i02,i01,i12,
            rkBP);
    }
}
//----------------------------------------------------------------------------

//----------------------------------------------------------------------------
// streaming
//----------------------------------------------------------------------------
Object* BezierTriangle2::Factory (Stream& rkStream)
{
    BezierTriangle2* pkObject = new BezierTriangle2;
    Stream::Link* pkLink = new Stream::Link(pkObject);
    pkObject->Load(rkStream,pkLink);
    return pkObject;
}
//----------------------------------------------------------------------------
void BezierTriangle2::Load (Stream& rkStream, Stream::Link* pkLink)
{
    BezierTriangle::Load(rkStream,pkLink);
}
//----------------------------------------------------------------------------
void BezierTriangle2::Link (Stream& rkStream, Stream::Link* pkLink)
{
    BezierTriangle::Link(rkStream,pkLink);
}
//----------------------------------------------------------------------------
bool BezierTriangle2::Register (Stream& rkStream)
{
    return BezierTriangle::Register(rkStream);
}
//----------------------------------------------------------------------------
void BezierTriangle2::Save (Stream& rkStream)
{
    BezierTriangle::Save(rkStream);
}
//----------------------------------------------------------------------------
StringTree* BezierTriangle2::SaveStrings ()
{
    StringTree* pkTree = new StringTree(1,0,1,0);

    // strings
    pkTree->SetString(0,MakeString(&ms_kRTTI,GetName()));

    // children
    pkTree->SetChild(0,BezierTriangle::SaveStrings());

    return pkTree;
}
//----------------------------------------------------------------------------
int BezierTriangle2::GetMemoryUsed () const
{
    int iBaseSize = sizeof(BezierTriangle2) - sizeof(BezierTriangle);
    int iTotalSize = iBaseSize + BezierTriangle::GetMemoryUsed();
    return iTotalSize;
}
//----------------------------------------------------------------------------
int BezierTriangle2::GetDiskUsed () const
{
    return BezierTriangle::GetDiskUsed();
}
//----------------------------------------------------------------------------

⌨️ 快捷键说明

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