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

📄 wmlstandardmesh.cpp

📁 3D Game Engine Design Source Code非常棒
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// 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 "WmlStandardMesh.h"
using namespace Wml;

//----------------------------------------------------------------------------
void Wml::CreateRectangleMesh (TriMesh*& rpkMesh, const Vector3f& rkCenter,
    const Vector3f& rkU, const Vector3f& rkV, const Vector3f& rkAxis,
    float fUExtent, float fVExtent, bool bWantNormals,  bool bWantColors,
    bool bWantUVs)
{
    // allocate vertices
    int iVQuantity = 4;
    Vector3f* akVertex = new Vector3f[iVQuantity];

    // allocate normals if requested
    Vector3f* akNormal = NULL;
    if ( bWantNormals )
        akNormal = new Vector3f[iVQuantity];

    // allocate colors if requested
    ColorRGB* akColor = NULL;
    if ( bWantColors )
    {
        akColor = new ColorRGB[iVQuantity];
        memset(akColor,0,iVQuantity*sizeof(ColorRGB));
    }

    // allocate texture coordinates if requested
    Vector2f* akUV = NULL;
    if ( bWantUVs )
        akUV = new Vector2f[iVQuantity];

    // allocate connectivity
    int iTQuantity = 2;
    int* aiConnect = new int[3*iTQuantity];

    // generate geometry
    Vector3f kUTerm = fUExtent*rkU;
    Vector3f kVTerm = fVExtent*rkV;
    akVertex[0] = rkCenter - kUTerm - kVTerm;
    akVertex[1] = rkCenter + kUTerm - kVTerm;
    akVertex[2] = rkCenter + kUTerm + kVTerm;
    akVertex[3] = rkCenter - kUTerm + kVTerm;

    if ( bWantNormals )
    {
        for (int i = 0; i < iVQuantity; i++)
            akNormal[i] = rkAxis;
    }

    if ( bWantUVs )
    {
        akUV[0] = Vector2f(0.0f,0.0f);
        akUV[1] = Vector2f(1.0f,0.0f);
        akUV[2] = Vector2f(1.0f,1.0f);
        akUV[3] = Vector2f(0.0f,1.0f);
    }

    // generate connectivity
    aiConnect[0] = 0;  aiConnect[1] = 1;  aiConnect[2] = 2;
    aiConnect[3] = 0;  aiConnect[4] = 2;  aiConnect[5] = 3;

    if ( rpkMesh )
    {
        rpkMesh->Reconstruct(iVQuantity,akVertex,akNormal,akColor,akUV,
            iTQuantity,aiConnect);
    }
    else
    {
        rpkMesh = new TriMesh(iVQuantity,akVertex,akNormal,akColor,akUV,
            iTQuantity,aiConnect);
    }
}
//----------------------------------------------------------------------------
void Wml::CreateDiskMesh (TriMesh*& rpkMesh, int iShellSamples,
    int iRadialSamples, const Vector3f& rkCenter, float fRadius,
    const Vector3f& rkU, const Vector3f& rkV, const Vector3f& rkAxis,
    bool bWantNormals, bool bWantColors, bool bWantUVs)
{
    int iRSm1 = iRadialSamples - 1, iSSm1 = iShellSamples - 1;

    // allocate vertices
    int iVQuantity = 1 + iRadialSamples*iSSm1;
    Vector3f* akVertex = new Vector3f[iVQuantity];

    // allocate normals if requested
    Vector3f* akNormal = NULL;
    if ( bWantNormals )
        akNormal = new Vector3f[iVQuantity];

    // allocate colors if requested
    ColorRGB* akColor = NULL;
    if ( bWantColors )
    {
        akColor = new ColorRGB[iVQuantity];
        memset(akColor,0,iVQuantity*sizeof(ColorRGB));
    }

    // allocate texture coordinates if requested
    Vector2f* akUV = NULL;
    if ( bWantUVs )
        akUV = new Vector2f[iVQuantity];

    // allocate connectivity
    int iTQuantity = iRadialSamples*(2*iSSm1-1);
    int* aiConnect = new int[3*iTQuantity];

    // generate geometry
    int iR, iS, i;

    // center of disk
    akVertex[0] = Vector3f::ZERO;
    if ( bWantNormals )
    {
        akNormal[0] = rkAxis;
    }
    if ( bWantUVs )
    {
        akUV[0].X() = 0.5f;
        akUV[0].Y() = 0.5f;
    }

    float fInvSSm1 = 1.0f/(float)iSSm1;
    float fInvRS = 1.0f/(float)iRadialSamples;
    for (iR = 0; iR < iRadialSamples; iR++)
    {
        float fAngle = Mathf::TWO_PI*fInvRS*iR;
        float fCos = Mathf::Cos(fAngle);
        float fSin = Mathf::Sin(fAngle);
        Vector3f kRadial = fCos*rkU + fSin*rkV;

        for (iS = 1; iS < iShellSamples; iS++)
        {
            float fFraction = fInvSSm1*iS;  // in (0,R]
            Vector3f kFracRadial = fFraction*kRadial;
            i = iS+iSSm1*iR;
            akVertex[i] = fRadius*kFracRadial;
            if ( bWantNormals )
            {
                akNormal[i] = rkAxis;
            }
            if ( bWantUVs )
            {
                akUV[i].X() = 0.5f*(1.0f+kFracRadial.X());
                akUV[i].Y() = 0.5f*(1.0f+kFracRadial.Y());
            }
        }
    }

    // rotate and translate disk to specified center
    for (i = 0; i < iVQuantity; i++)
        akVertex[i] += rkCenter;

    // generate connectivity
    int* aiLocalConnect = aiConnect;
    int iT = 0;
    for (int iR0 = iRSm1, iR1 = 0; iR1 < iRadialSamples; iR0 = iR1++)
    {
        aiLocalConnect[0] = 0;
        aiLocalConnect[1] = 1+iSSm1*iR0;
        aiLocalConnect[2] = 1+iSSm1*iR1;
        aiLocalConnect += 3;
        iT++;
        for (int iS = 1; iS < iSSm1; iS++, aiLocalConnect += 6)
        {
            int i00 = iS+iSSm1*iR0;
            int i01 = iS+iSSm1*iR1;
            int i10 = i00+1;
            int i11 = i01+1;
            aiLocalConnect[0] = i00;
            aiLocalConnect[1] = i10;
            aiLocalConnect[2] = i11;
            aiLocalConnect[3] = i00;
            aiLocalConnect[4] = i11;
            aiLocalConnect[5] = i01;
            iT += 2;
        }
    }
    assert( iT == iTQuantity );

    if ( rpkMesh )
    {
        rpkMesh->Reconstruct(iVQuantity,akVertex,akNormal,akColor,akUV,
            iTQuantity,aiConnect);
    }
    else
    {
        rpkMesh = new TriMesh(iVQuantity,akVertex,akNormal,akColor,akUV,
            iTQuantity,aiConnect);
    }
}
//----------------------------------------------------------------------------
void Wml::CreateBoxMesh (TriMesh*& rpkMesh, const Vector3f& rkCenter,
    const Vector3f& rkU, const Vector3f& rkV, const Vector3f& rkW,
    float fUExtent, float fVExtent, float fWExtent, bool bWantNormals,
    bool bWantColors, bool bWantUVs, bool bOutsideView)
{
    // allocate vertices
    int iVQuantity = 8;
    Vector3f* akVertex = new Vector3f[iVQuantity];

    // allocate normals if requested
    Vector3f* akNormal = NULL;
    if ( bWantNormals )
        akNormal = new Vector3f[iVQuantity];

    // allocate colors if requested
    ColorRGB* akColor = NULL;
    if ( bWantColors )
    {
        akColor = new ColorRGB[iVQuantity];
        memset(akColor,0,iVQuantity*sizeof(ColorRGB));
    }

    // allocate texture coordinates if requested
    Vector2f* akUV = NULL;
    if ( bWantUVs )
        akUV = new Vector2f[iVQuantity];

    // allocate connectivity
    int iTQuantity = 12;
    int* aiConnect = new int[3*iTQuantity];

    // generate geometry
    Vector3f kUTerm = fUExtent*rkU;
    Vector3f kVTerm = fVExtent*rkV;
    Vector3f kWTerm = fWExtent*rkW;
    akVertex[0] = rkCenter - kUTerm - kVTerm - kWTerm;
    akVertex[1] = rkCenter + kUTerm - kVTerm - kWTerm;
    akVertex[2] = rkCenter + kUTerm + kVTerm - kWTerm;
    akVertex[3] = rkCenter - kUTerm + kVTerm - kWTerm;
    akVertex[4] = rkCenter - kUTerm - kVTerm + kWTerm;
    akVertex[5] = rkCenter + kUTerm - kVTerm + kWTerm;
    akVertex[6] = rkCenter + kUTerm + kVTerm + kWTerm;
    akVertex[7] = rkCenter - kUTerm + kVTerm + kWTerm;

    if ( bWantUVs )
    {
        akUV[0] = Vector2f(0.25f,0.75f);
        akUV[1] = Vector2f(0.75f,0.75f);
        akUV[2] = Vector2f(0.75f,0.25f);
        akUV[3] = Vector2f(0.25f,0.25f);
        akUV[4] = Vector2f(0.0f,1.0f);
        akUV[5] = Vector2f(1.0f,1.0f);
        akUV[6] = Vector2f(1.0f,0.0f);
        akUV[7] = Vector2f(0.0f,0.0f);
    }

    // generate connectivity (outside view)
    aiConnect[ 0] = 0;  aiConnect[ 1] = 2;  aiConnect[ 2] = 1;
    aiConnect[ 3] = 0;  aiConnect[ 4] = 3;  aiConnect[ 5] = 2;
    aiConnect[ 6] = 0;  aiConnect[ 7] = 1;  aiConnect[ 8] = 5;
    aiConnect[ 9] = 0;  aiConnect[10] = 5;  aiConnect[11] = 4;
    aiConnect[12] = 0;  aiConnect[13] = 4;  aiConnect[14] = 7;
    aiConnect[15] = 0;  aiConnect[16] = 7;  aiConnect[17] = 3;
    aiConnect[18] = 6;  aiConnect[19] = 4;  aiConnect[20] = 5;
    aiConnect[21] = 6;  aiConnect[22] = 7;  aiConnect[23] = 4;
    aiConnect[24] = 6;  aiConnect[25] = 5;  aiConnect[26] = 1;
    aiConnect[27] = 6;  aiConnect[28] = 1;  aiConnect[29] = 2;
    aiConnect[30] = 6;  aiConnect[31] = 2;  aiConnect[32] = 3;
    aiConnect[33] = 6;  aiConnect[34] = 3;  aiConnect[35] = 7;

    if ( !bOutsideView )
    {
        int* aiLocalConnect = aiConnect;
        for (int iT = 0; iT < iTQuantity; iT++, aiLocalConnect +=3)
        {
            int iSave = aiLocalConnect[1];
            aiLocalConnect[1] = aiLocalConnect[2];
            aiLocalConnect[2] = iSave;
        }
    }

    if ( rpkMesh )
    {
        rpkMesh->Reconstruct(iVQuantity,akVertex,akNormal,akColor,akUV,
            iTQuantity,aiConnect);
    }
    else
    {
        rpkMesh = new TriMesh(iVQuantity,akVertex,akNormal,akColor,akUV,
            iTQuantity,aiConnect);
    }

    if ( bWantNormals )
        rpkMesh->UpdateModelNormals();
}
//----------------------------------------------------------------------------
void Wml::CreateCylinderMesh (TriMesh*& rpkMesh, int iAxisSamples,
    int iRadialSamples, const Vector3f& rkCenter, const Vector3f& rkU,
    const Vector3f& rkV, const Vector3f& rkAxis, float fRadius,
    float fHeight, bool bWantNormals, bool bWantColors, bool bWantUVs,
    bool bOutsideView)
{
    // allocate vertices
    int iVQuantity = iAxisSamples*(iRadialSamples+1);
    Vector3f* akVertex = new Vector3f[iVQuantity];

    // allocate normals if requested
    Vector3f* akNormal = NULL;
    if ( bWantNormals )
        akNormal = new Vector3f[iVQuantity];

    // allocate colors if requested
    ColorRGB* akColor = NULL;
    if ( bWantColors )
    {
        akColor = new ColorRGB[iVQuantity];
        memset(akColor,0,iVQuantity*sizeof(ColorRGB));
    }

    // allocate texture coordinates if requested
    Vector2f* akUV = NULL;
    if ( bWantUVs )
        akUV = new Vector2f[iVQuantity];

    // allocate connectivity
    int iTQuantity = 2*(iAxisSamples-1)*iRadialSamples;
    int* aiConnect = new int[3*iTQuantity];

    // generate geometry
    float fInvRS = 1.0f/(float)iRadialSamples;
    float fInvASm1 = 1.0f/(float)(iAxisSamples-1);
    float fHalfHeight = 0.5f*fHeight;
    int iR, iA, iAStart, i;

    // Generate points on the unit circle to be used in computing the mesh
    // points on a cylinder slice.
    float* afSin = new float[iRadialSamples+1];
    float* afCos = new float[iRadialSamples+1];
    for (iR = 0; iR < iRadialSamples; iR++)
    {
        float fAngle = Mathf::TWO_PI*fInvRS*iR;
        afCos[iR] = Mathf::Cos(fAngle);
        afSin[iR] = Mathf::Sin(fAngle);
    }
    afSin[iRadialSamples] = afSin[0];
    afCos[iRadialSamples] = afCos[0];

    // generate the cylinder itself
    for (iA = 0, i = 0; iA < iAxisSamples; iA++)
    {
        float fAxisFraction = iA*fInvASm1;  // in [0,1]
        float fZ = -fHalfHeight + fHeight*fAxisFraction;

        // compute center of slice
        Vector3f kSliceCenter = rkCenter + fZ*rkAxis;

        // compute slice vertices with duplication at end point
        int iSave = i;
        for (iR = 0; iR < iRadialSamples; iR++)
        {
            float fRadialFraction = iR*fInvRS;  // in [0,1)
            Vector3f kNormal = afCos[iR]*rkU + afSin[iR]*rkV;
            akVertex[i] = kSliceCenter + fRadius*kNormal;
            if ( bWantNormals )
            {
                if ( bOutsideView )
                    akNormal[i] = kNormal;
                else
                    akNormal[i] = -kNormal;
            }
            if ( bWantUVs )
            {
                akUV[i].X() = fRadialFraction;
                akUV[i].Y() = fAxisFraction;
            }
            i++;
        }

        akVertex[i] = akVertex[iSave];
        if ( bWantNormals )
        {
            akNormal[i] = akNormal[iSave];
        }
        if ( bWantUVs )
        {
            akUV[i].X() = 1.0f;
            akUV[i].Y() = fAxisFraction;
        }
        i++;
    }

    // generate connectivity
    int* aiLocalConnect = aiConnect;
    for (iA = 0, iAStart = 0; iA < iAxisSamples-1; iA++)
    {
        int i0 = iAStart;
        int i1 = i0 + 1;
        iAStart += iRadialSamples + 1;
        int i2 = iAStart;
        int i3 = i2 + 1;
        for (i = 0; i < iRadialSamples; i++, aiLocalConnect += 6)
        {
            if ( bOutsideView )
            {
                aiLocalConnect[0] = i0++;
                aiLocalConnect[1] = i1;
                aiLocalConnect[2] = i2;
                aiLocalConnect[3] = i1++;
                aiLocalConnect[4] = i3++;
                aiLocalConnect[5] = i2++;
            }
            else // inside view
            {
                aiLocalConnect[0] = i0++;
                aiLocalConnect[1] = i2;
                aiLocalConnect[2] = i1;
                aiLocalConnect[3] = i1++;
                aiLocalConnect[4] = i2++;
                aiLocalConnect[5] = i3++;
            }
        }
    }

    delete[] afCos;
    delete[] afSin;

    if ( rpkMesh )
    {
        rpkMesh->Reconstruct(iVQuantity,akVertex,akNormal,akColor,akUV,
            iTQuantity,aiConnect);
    }
    else
    {
        rpkMesh = new TriMesh(iVQuantity,akVertex,akNormal,akColor,akUV,
            iTQuantity,aiConnect);
    }

⌨️ 快捷键说明

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