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

📄 wmlstandardmesh.cpp

📁 3D Game Engine Design Source Code非常棒
💻 CPP
📖 第 1 页 / 共 3 页
字号:
}
//----------------------------------------------------------------------------
void Wml::CreateSphereMesh (TriMesh*& rpkMesh, int iZSamples,
    int iRadialSamples, const Vector3f& rkCenter, float fRadius,
    const Vector3f& rkU, const Vector3f& rkV, const Vector3f& rkAxis,
    bool bWantNormals, bool bWantColors, bool bWantUVs, bool bOutsideView)
{
    int iZSm1 = iZSamples-1, iZSm2 = iZSamples-2, iZSm3 = iZSamples-3;
    int iRSp1 = iRadialSamples+1;

    // allocate vertices
    int iVQuantity = iZSm2*iRSp1 + 2;
    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*iZSm2*iRadialSamples;
    int* aiConnect = new int[3*iTQuantity];

    // generate geometry
    float fInvRS = 1.0f/(float)iRadialSamples;
    float fZFactor = 2.0f/(float)iZSm1;
    int iR, iZ, iZStart, i;

    // Generate points on the unit circle to be used in computing the mesh
    // points on a cylinder slice.
    float* afSin = new float[iRSp1];
    float* afCos = new float[iRSp1];
    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 (iZ = 1, i = 0; iZ < iZSm1; iZ++)
    {
        float fZFraction = -1.0f + fZFactor*iZ;  // in (-1,1)
        float fZ = fRadius*fZFraction;

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

        // compute radius of slice
        float fSliceRadius = Mathf::Sqrt(Mathf::FAbs(fRadius*fRadius-fZ*fZ));

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

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

    // south pole
    akVertex[i] = rkCenter - fRadius*rkAxis;
    if ( bWantNormals )
    {
        if ( bOutsideView )
            akNormal[i] = -rkAxis;
        else
            akNormal[i] = rkAxis;
    }
    if ( bWantUVs )
    {
        akUV[i].X() = 0.5f;
        akUV[i].Y() = 0.0f;
    }
    i++;

    // north pole
    akVertex[i] = rkCenter + fRadius*rkAxis;
    if ( bWantNormals )
    {
        if ( bOutsideView )
            akNormal[i] = rkAxis;
        else
            akNormal[i] = -rkAxis;
    }
    if ( bWantUVs )
    {
        akUV[i].X() = 0.5f;
        akUV[i].Y() = 1.0f;
    }
    i++;
    assert( i == iVQuantity );

    // generate connectivity
    int* aiLocalConnect = aiConnect;
    for (iZ = 0, iZStart = 0; iZ < iZSm3; iZ++)
    {
        int i0 = iZStart;
        int i1 = i0 + 1;
        iZStart += iRSp1;
        int i2 = iZStart;
        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++;
            }
        }
    }

    // south pole triangles
    int iVQm2 = iVQuantity-2;
    for (i = 0; i < iRadialSamples; i++, aiLocalConnect += 3)
    {
        if ( bOutsideView )
        {
            aiLocalConnect[0] = i;
            aiLocalConnect[1] = iVQm2;
            aiLocalConnect[2] = i+1;
        }
        else  // inside view
        {
            aiLocalConnect[0] = i;
            aiLocalConnect[1] = i+1;
            aiLocalConnect[2] = iVQm2;
        }
    }

    // north pole triangles
    int iVQm1 = iVQuantity-1, iOffset = iZSm3*iRSp1;
    for (i = 0; i < iRadialSamples; i++, aiLocalConnect += 3)
    {
        if ( bOutsideView )
        {
            aiLocalConnect[0] = i+iOffset;
            aiLocalConnect[1] = i+1+iOffset;
            aiLocalConnect[2] = iVQm1;
        }
        else  // inside view
        {
            aiLocalConnect[0] = i+iOffset;
            aiLocalConnect[1] = iVQm1;
            aiLocalConnect[2] = i+1+iOffset;
        }
    }

    int* aiFinalConnect = aiConnect + 3*iTQuantity;
    assert( aiLocalConnect == aiFinalConnect );

    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);
    }
}
//----------------------------------------------------------------------------
void Wml::CreateTorusMesh (TriMesh*& rpkMesh, int iCircleSamples,
    int iRadialSamples, const Vector3f& rkCenter, const Vector3f& rkU,
    const Vector3f& rkV, const Vector3f& rkAxis, float fOuterRadius,
    float fInnerRadius, bool bWantNormals, bool bWantColors, bool bWantUVs,
    bool bOutsideView)
{
    // allocate vertices
    int iVQuantity = (iCircleSamples+1)*(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*iCircleSamples*iRadialSamples;
    int* aiConnect = new int[3*iTQuantity];

    // generate geometry
    float fInvCS = 1.0f/(float)iCircleSamples;
    float fInvRS = 1.0f/(float)iRadialSamples;
    int iC, iR, i;

    // generate the cylinder itself
    for (iC = 0, i = 0; iC < iCircleSamples; iC++)
    {
        // compute center point on torus circle at specified angle
        float fCircleFraction = iC*fInvCS;  // in [0,1)
        float fTheta = Mathf::TWO_PI*fCircleFraction;
        float fCosTheta = Mathf::Cos(fTheta);
        float fSinTheta = Mathf::Sin(fTheta);
        Vector3f kRadial = fCosTheta*rkU + fSinTheta*rkV;
        Vector3f kTorusMiddle = rkCenter + fOuterRadius*kRadial;

        // compute slice vertices with duplication at end point
        int iSave = i;
        for (iR = 0; iR < iRadialSamples; iR++)
        {
            float fRadialFraction = iR*fInvRS;  // in [0,1)
            float fPhi = Mathf::TWO_PI*fRadialFraction;
            float fCosPhi = Mathf::Cos(fPhi);
            float fSinPhi = Mathf::Sin(fPhi);
            Vector3f kNormal = fCosPhi*kRadial + fSinPhi*rkAxis;
            akVertex[i] = kTorusMiddle + fInnerRadius*kNormal;
            if ( bWantNormals )
            {
                if ( bOutsideView )
                    akNormal[i] = kNormal;
                else
                    akNormal[i] = -kNormal;
            }
            if ( bWantUVs )
            {
                akUV[i].X() = fRadialFraction;
                akUV[i].Y() = fCircleFraction;
            }
            i++;
        }

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

    // duplicate the cylinder ends to form a torus
    for (iR = 0; iR <= iRadialSamples; iR++, i++)
    {
        akVertex[i] = akVertex[iR];
        if ( bWantNormals )
        {
            akNormal[i] = akNormal[iR];
        }
        if ( bWantUVs )
        {
            akUV[i].X() = akUV[iR].X();
            akUV[i].Y() = 1.0f;
        }
    }
    assert( i == iVQuantity );

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

    if ( rpkMesh )
    {
        rpkMesh->Reconstruct(iVQuantity,akVertex,akNormal,akColor,akUV,
            iTQuantity,aiConnect);
    }
    else
    {
        rpkMesh = new TriMesh(iVQuantity,akVertex,akNormal,akColor,akUV,
            iTQuantity,aiConnect);
    }
}
//----------------------------------------------------------------------------
void Wml::CreateTetrahedronMesh (TriMesh*& rpkMesh, bool bWantNormals,
    bool bWantColors, bool bWantUVs, bool bOutsideView)
{
    float fSqrt2Div3 = Mathf::Sqrt(2.0f)/3.0f;
    float fSqrt6Div3 = Mathf::Sqrt(6.0f)/3.0f;
    float fOneThird = 1.0f/3.0f;
    int i;

    // allocate vertices
    int iVQuantity = 4;
    Vector3f* akVertex = new Vector3f[iVQuantity];
    akVertex[0] = Vector3f(0.0f,0.0f,1.0f);
    akVertex[1] = Vector3f(2.0f*fSqrt2Div3,0.0f,-fOneThird);
    akVertex[2] = Vector3f(-fSqrt2Div3,fSqrt6Div3,-fOneThird);
    akVertex[3] = Vector3f(-fSqrt2Div3,-fSqrt6Div3,-fOneThird);

    // allocate normals if requested
    Vector3f* akNormal = NULL;
    if ( bWantNormals )
    {
        akNormal = new Vector3f[iVQuantity];
        for (i = 0; i < iVQuantity; i++)
            akNormal[i] = akVertex[i];
    }

    // 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];
        for (i = 0; i < iVQuantity; i++)
        {
            if ( Mathf::FAbs(akVertex[i].Z()) < 1.0f )
            {
                akUV[i].X() = 0.5f*(1.0f + Mathf::ATan2(akVertex[i].Y(),
                    akVertex[i].X())*Mathf::INV_PI);
            }
            else
            {
                akUV[i].X() = 0.5f;
            }
            akUV[i].Y() = Mathf::ACos(akVertex[i].Z())*Mathf::INV_PI;
        }
    }

    // allocate connectivity
    int iTQuantity = 4;
    int* aiConnect = new int[3*iTQuantity];
    aiConnect[ 0] = 0;  aiConnect[ 1] = 1;  aiConnect[ 2] = 2;
    aiConnect[ 3] = 0;  aiConnect[ 4] = 2;  aiConnect[ 5] = 3;
    aiConnect[ 6] = 0;  aiConnect[ 7] = 3;  aiConnect[ 8] = 1;
    aiConnect[ 9] = 1;  aiConnect[10] = 3;  aiConnect[11] = 2;

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

⌨️ 快捷键说明

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