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

📄 wmlbeziercylinder2.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 "WmlBezierCylinder2.h"
#include "WmlTriMesh.h"
using namespace Wml;

WmlImplementRTTI(BezierCylinder2,BezierCylinder);
WmlImplementStream(BezierCylinder2);

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

//----------------------------------------------------------------------------
BezierCylinder2::BezierCylinder2 (int* aiIndex)
    :
    BezierCylinder(2,6,aiIndex)
{
}
//----------------------------------------------------------------------------
BezierCylinder2::BezierCylinder2 ()
{
}
//----------------------------------------------------------------------------
void BezierCylinder2::InitializePoints (const Vector3f* akCtrlPoint,
    IntervalParameters& rkIP)
{
    // Xss[t]
    rkIP.m_aakXss[0] = 6.0f*(XA(0) - 2.0f*XA(1) + XA(2));
    rkIP.m_aakXss[1] = 6.0f*(XA(3) - 2.0f*XA(4) + XA(5));
}
//----------------------------------------------------------------------------
void BezierCylinder2::InitializeColors (const ColorRGB* akCtrlColor,
    IntervalParameters& rkIP)
{
    // Css[t]
    rkIP.m_aakCss[0] = 6.0f*(CA(0) - 2.0f*CA(1) + CA(2));
    rkIP.m_aakCss[1] = 6.0f*(CA(3) - 2.0f*CA(4) + CA(5));
}
//----------------------------------------------------------------------------
void BezierCylinder2::InitializeTextures (const Vector2f* akCtrlTexture,
    IntervalParameters& rkIP)
{
    // Tss[t]
    rkIP.m_aakTss[0] = 6.0f*(TA(0) - 2.0f*TA(1) + TA(2));
    rkIP.m_aakTss[1] = 6.0f*(TA(3) - 2.0f*TA(4) + TA(5));
}
//----------------------------------------------------------------------------
void BezierCylinder2::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 four corners of patch, I[s][t]
    int iTwoPowL = (1 << iLevel);
    int iTwoPowC = (1 << m_iCylinderLevel);
    IntervalParameters kIP;
    kIP.m_i00 = 0;
    kIP.m_i01 = iTwoPowC*(iTwoPowL + 1);
    kIP.m_i10 = iTwoPowL;
    kIP.m_i11 = kIP.m_i01 + iTwoPowL;

    // vertices for subdivision
    Vector3f* akX = pkMesh->Vertices() + riVertexStart;
    akX[kIP.m_i00] = XA(0);
    akX[kIP.m_i01] = XA(3);
    akX[kIP.m_i10] = XA(2);
    akX[kIP.m_i11] = XA(5);

    // derivatives for subdivision (for normal vectors)
    Vector3f* akXs;
    Vector3f* akXt;
    if ( pkMesh->Normals() )
    {
        akXs = new Vector3f[iQuantity];
        akXs[kIP.m_i00] = 2.0f*(XA(1) - XA(0));
        akXs[kIP.m_i01] = 2.0f*(XA(4) - XA(3));
        akXs[kIP.m_i10] = 2.0f*(XA(2) - XA(1));
        akXs[kIP.m_i11] = 2.0f*(XA(5) - XA(4));

        akXt = new Vector3f[iQuantity];
        akXt[kIP.m_i00] = 2.0f*(XA(3) - XA(0));
        akXt[kIP.m_i01] = akXt[kIP.m_i00];
        akXt[kIP.m_i10] = 2.0f*(XA(5) - XA(2));
        akXt[kIP.m_i11] = akXt[kIP.m_i10];
    }
    else
    {
        akXs = NULL;
        akXt = NULL;
    }

    // colors for subdivision
    ColorRGB* akColor;
    if ( pkMesh->Colors() )
    {
        akColor = pkMesh->Colors() + riVertexStart;
        akColor[kIP.m_i00] = CA(0);
        akColor[kIP.m_i01] = CA(3);
        akColor[kIP.m_i10] = CA(2);
        akColor[kIP.m_i11] = CA(5);
    }
    else
    {
        akColor = NULL;
    }

    // textures for subdivision
    Vector2f* akTexture;
    if ( pkMesh->Textures() )
    {
        akTexture = pkMesh->Textures() + riVertexStart;
        akTexture[kIP.m_i00] = TA(0);
        akTexture[kIP.m_i01] = TA(3);
        akTexture[kIP.m_i10] = TA(2);
        akTexture[kIP.m_i11] = TA(5);
    }
    else
    {
        akTexture = NULL;
    }

    // recursive subdivision
    if ( iLevel > 0 || m_iCylinderLevel > 0 )
    {
        InitializePoints(akCtrlPoint,kIP);

        if ( akCtrlColor )
            InitializeColors(akCtrlColor,kIP);

        if ( akCtrlTexture )
            InitializeTextures(akCtrlTexture,kIP);
    }

    if ( iLevel > 0 )
        SubdivideBoundary(--iLevel,0.25f,akX,akXs,akXt,akColor,akTexture,kIP);

    if ( m_iCylinderLevel > 0 )
    {
        SubdivideCylinder(m_iCylinderLevel-1,akX,akXs,akXt,akColor,
            akTexture,0,kIP.m_i01,iTwoPowL);
    }

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

    riVertexStart += iQuantity;
}
//----------------------------------------------------------------------------
void BezierCylinder2::SubdivideBoundary (int iLevel, float fDSqr,
    Vector3f* akX, Vector3f* akXs, Vector3f* akXt, ColorRGB* akColor,
    Vector2f* akTexture, IntervalParameters& rkIP)
{
    // subdivision indices
    int iM0 = (rkIP.m_i00 + rkIP.m_i10) >> 1;
    int iM1 = (rkIP.m_i01 + rkIP.m_i11) >> 1;

    // vertices
    akX[iM0] = 0.5f*(akX[rkIP.m_i00] + akX[rkIP.m_i10] -
        fDSqr*rkIP.m_aakXss[0]);
    akX[iM1] = 0.5f*(akX[rkIP.m_i01] + akX[rkIP.m_i11] -
        fDSqr*rkIP.m_aakXss[1]);

    // derivatives (for normal vectors)
    if ( akXs )
    {
        akXs[iM0] = 0.5f*(akXs[rkIP.m_i00] + akXs[rkIP.m_i10]);
        akXs[iM1] = 0.5f*(akXs[rkIP.m_i01] + akXs[rkIP.m_i11]);
        akXt[iM0] = akX[iM1] - akX[iM0];
        akXt[iM1] = akXt[iM0];
    }

    // colors
    if ( akColor )
    {
        akColor[iM0] = 0.5f*(akColor[rkIP.m_i00] + akColor[rkIP.m_i10] -
            fDSqr*rkIP.m_aakCss[0]);
        akColor[iM1] = 0.5f*(akColor[rkIP.m_i01] + akColor[rkIP.m_i11] -
            fDSqr*rkIP.m_aakCss[1]);
    }

    // textures
    if ( akTexture )
    {
        akTexture[iM0] = 0.5f*(akTexture[rkIP.m_i00] +
            akTexture[rkIP.m_i10] - fDSqr*rkIP.m_aakTss[0]);
        akTexture[iM1] = 0.5f*(akTexture[rkIP.m_i01] +
            akTexture[rkIP.m_i11] - fDSqr*rkIP.m_aakTss[1]);
    }

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

        IntervalParameters kSubIP;

        // subinterval [s0,sM]
        kSubIP.m_i00 = rkIP.m_i00;
        kSubIP.m_i01 = rkIP.m_i01;
        kSubIP.m_i10 = iM0;
        kSubIP.m_i11 = iM1;

        kSubIP.m_aakXss[0] = rkIP.m_aakXss[0];
        kSubIP.m_aakXss[1] = rkIP.m_aakXss[1];

        if ( akColor )
        {
            kSubIP.m_aakCss[0] = rkIP.m_aakCss[0];
            kSubIP.m_aakCss[1] = rkIP.m_aakCss[1];
        }

        if ( akTexture )
        {
            kSubIP.m_aakTss[0] = rkIP.m_aakTss[0];
            kSubIP.m_aakTss[1] = rkIP.m_aakTss[1];
        }

        SubdivideBoundary(iLevel,fDSqr,akX,akXs,akXt,akColor,akTexture,
            kSubIP);

        // subinterval [sM,s1]
        kSubIP.m_i00 = iM0;
        kSubIP.m_i01 = iM1;
        kSubIP.m_i10 = rkIP.m_i10;
        kSubIP.m_i11 = rkIP.m_i11;

        kSubIP.m_aakXss[0] = rkIP.m_aakXss[0];
        kSubIP.m_aakXss[1] = rkIP.m_aakXss[1];

        if ( akColor )
        {
            kSubIP.m_aakCss[0] = rkIP.m_aakCss[0];
            kSubIP.m_aakCss[1] = rkIP.m_aakCss[1];
        }

        if ( akTexture )
        {
            kSubIP.m_aakTss[0] = rkIP.m_aakTss[0];
            kSubIP.m_aakTss[1] = rkIP.m_aakTss[1];
        }

        SubdivideBoundary(iLevel,fDSqr,akX,akXs,akXt,akColor,akTexture,
            kSubIP);
    }
}
//----------------------------------------------------------------------------
void BezierCylinder2::SubdivideCylinder (int iCLevel, Vector3f* akX,
    Vector3f* akXs, Vector3f* akXt, ColorRGB* akColor, Vector2f* akTexture,
    int i0, int i1, int iTwoPowL)
{
    // subdivision index
    int iM = (i0 + i1) >> 1;

    int j0 = i0, jM = iM, j1 = i1;
    int iJLast = jM + iTwoPowL;
    for (/**/; jM <= iJLast; j0++, jM++, j1++)
    {
        // vertices
        akX[jM] = 0.5f*(akX[j0] + akX[j1]);

        // derivatives (for normal vectors)
        if ( akXs )
        {
            akXs[jM] = 0.5f*(akXs[j0] + akXs[j1]);
            akXt[jM] = akXt[j0];
        }

        // colors
        if ( akColor )
            akColor[jM] = 0.5f*(akColor[j0] + akColor[j1]);

        // textures
        if ( akTexture )
            akTexture[jM] = 0.5f*(akTexture[j0] + akTexture[j1]);
    }

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

        // subinterval [t0,tM]
        SubdivideCylinder(iCLevel,akX,akXs,akXt,akColor,akTexture,i0,iM,
            iTwoPowL);

        // subinterval [tM,t1]
        SubdivideCylinder(iCLevel,akX,akXs,akXt,akColor,akTexture,iM,i1,
            iTwoPowL);
    }
}
//----------------------------------------------------------------------------

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

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

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

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

⌨️ 快捷键说明

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