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

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

WmlImplementRTTI(BezierCylinder3,BezierCylinder);
WmlImplementStream(BezierCylinder3);

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

//----------------------------------------------------------------------------
BezierCylinder3::BezierCylinder3 (int* aiIndex)
    :
    BezierCylinder(3,8,aiIndex)
{
}
//----------------------------------------------------------------------------
BezierCylinder3::BezierCylinder3 ()
{
}
//----------------------------------------------------------------------------
void BezierCylinder3::InitializePoints (const Vector3f* akCtrlPoint,
    IntervalParameters& rkIP)
{
    // Xss[s][t]
    rkIP.m_aakXss[0][0] = 6.0f*(XA(0) - 2.0f*XA(1) + XA(2));
    rkIP.m_aakXss[0][1] = 6.0f*(XA(4) - 2.0f*XA(5) + XA(6));
    rkIP.m_aakXss[1][0] = 6.0f*(XA(1) - 2.0f*XA(2) + XA(3));
    rkIP.m_aakXss[1][1] = 6.0f*(XA(5) - 2.0f*XA(6) + XA(7));
}
//----------------------------------------------------------------------------
void BezierCylinder3::InitializeNormals (const Vector3f* akCtrlPoint,
    Vector3f akXsss[2])
{
    // Xsss[t]
    akXsss[0] = 6.0f*(XA(3) + 3.0f*(XA(1) - XA(2)) - XA(0));
    akXsss[1] = 6.0f*(XA(7) + 3.0f*(XA(5) - XA(6)) - XA(4));
}
//----------------------------------------------------------------------------
void BezierCylinder3::InitializeColors (const ColorRGB* akCtrlColor,
    IntervalParameters& rkIP)
{
    // Css[s][t]
    rkIP.m_aakCss[0][0] = 6.0f*(CA(0) - 2.0f*CA(1) + CA(2));
    rkIP.m_aakCss[0][1] = 6.0f*(CA(4) - 2.0f*CA(5) + CA(6));
    rkIP.m_aakCss[1][0] = 6.0f*(CA(1) - 2.0f*CA(2) + CA(3));
    rkIP.m_aakCss[1][1] = 6.0f*(CA(5) - 2.0f*CA(6) + CA(7));
}
//----------------------------------------------------------------------------
void BezierCylinder3::InitializeTextures (const Vector2f* akCtrlTexture,
    IntervalParameters& rkIP)
{
    // Tss[s][t]
    rkIP.m_aakTss[0][0] = 6.0f*(TA(0) - 2.0f*TA(1) + TA(2));
    rkIP.m_aakTss[0][1] = 6.0f*(TA(4) - 2.0f*TA(5) + TA(6));
    rkIP.m_aakTss[1][0] = 6.0f*(TA(1) - 2.0f*TA(2) + TA(3));
    rkIP.m_aakTss[1][1] = 6.0f*(TA(5) - 2.0f*TA(6) + TA(7));
}
//----------------------------------------------------------------------------
void BezierCylinder3::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(4);
    akX[kIP.m_i10] = XA(3);
    akX[kIP.m_i11] = XA(7);

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

        akXt = new Vector3f[iQuantity];
        akXt[kIP.m_i00] = 3.0f*(XA(4) - XA(0));
        akXt[kIP.m_i01] = akXt[kIP.m_i00];
        akXt[kIP.m_i10] = 3.0f*(XA(7) - XA(3));
        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(4);
        akColor[kIP.m_i10] = CA(3);
        akColor[kIP.m_i11] = CA(7);
    }
    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(4);
        akTexture[kIP.m_i10] = TA(3);
        akTexture[kIP.m_i11] = TA(7);
    }
    else
    {
        akTexture = NULL;
    }

    // recursive subdivision
    Vector3f akXsss[2];
    if ( iLevel > 0 || m_iCylinderLevel > 0 )
    {
        InitializePoints(akCtrlPoint,kIP);

        if ( akXs )
            InitializeNormals(akCtrlPoint,akXsss);

        if ( akCtrlColor )
            InitializeColors(akCtrlColor,kIP);

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

    if ( iLevel > 0 )
    {
        SubdivideBoundary(--iLevel,0.25f,akX,akXs,akXt,akXsss,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 BezierCylinder3::SubdivideBoundary (int iLevel, float fDSqr,
    Vector3f* akX, Vector3f* akXs, Vector3f* akXt, Vector3f akXsss[2],
    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
    Vector3f kXssM0 = 0.5f*(rkIP.m_aakXss[0][0] + rkIP.m_aakXss[1][0]);
    Vector3f kXssM1 = 0.5f*(rkIP.m_aakXss[0][1] + rkIP.m_aakXss[1][1]);
    akX[iM0] = 0.5f*(akX[rkIP.m_i00] + akX[rkIP.m_i10] - fDSqr*kXssM0);
    akX[iM1] = 0.5f*(akX[rkIP.m_i01] + akX[rkIP.m_i11] - fDSqr*kXssM1);

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

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

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

    // 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][0] = rkIP.m_aakXss[0][0];
        kSubIP.m_aakXss[0][1] = rkIP.m_aakXss[0][1];
        kSubIP.m_aakXss[1][0] = kXssM0;
        kSubIP.m_aakXss[1][1] = kXssM1;

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

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

        SubdivideBoundary(iLevel,fDSqr,akX,akXs,akXt,akXsss,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][0] = kXssM0;
        kSubIP.m_aakXss[0][1] = kXssM1;
        kSubIP.m_aakXss[1][0] = rkIP.m_aakXss[1][0];
        kSubIP.m_aakXss[1][1] = rkIP.m_aakXss[1][1];

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

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

        SubdivideBoundary(iLevel,fDSqr,akX,akXs,akXt,akXsss,akColor,
            akTexture,kSubIP);
    }
}
//----------------------------------------------------------------------------
void BezierCylinder3::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* BezierCylinder3::Factory (Stream& rkStream)
{
    BezierCylinder3* pkObject = new BezierCylinder3;
    Stream::Link* pkLink = new Stream::Link(pkObject);
    pkObject->Load(rkStream,pkLink);
    return pkObject;
}
//----------------------------------------------------------------------------
void BezierCylinder3::Load (Stream& rkStream, Stream::Link* pkLink)
{
    BezierCylinder::Load(rkStream,pkLink);
}
//----------------------------------------------------------------------------
void BezierCylinder3::Link (Stream& rkStream, Stream::Link* pkLink)
{
    BezierCylinder::Link(rkStream,pkLink);
}
//----------------------------------------------------------------------------
bool BezierCylinder3::Register (Stream& rkStream)
{
    return BezierCylinder::Register(rkStream);
}
//----------------------------------------------------------------------------
void BezierCylinder3::Save (Stream& rkStream)
{
    BezierCylinder::Save(rkStream);
}
//----------------------------------------------------------------------------
StringTree* BezierCylinder3::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 BezierCylinder3::GetMemoryUsed () const
{
    int iBaseSize = sizeof(BezierCylinder3) - sizeof(BezierCylinder);
    int iTotalSize = iBaseSize + BezierCylinder::GetMemoryUsed();
    return iTotalSize;
}
//----------------------------------------------------------------------------
int BezierCylinder3::GetDiskUsed () const
{
    return BezierCylinder::GetDiskUsed();
}
//----------------------------------------------------------------------------

⌨️ 快捷键说明

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