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

📄 beziersurface.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 "BezierSurface.h"

BezierSurface g_kTheApp;

//----------------------------------------------------------------------------
BezierSurface::BezierSurface ()
    :
    Application("BezierSurface",0,0,640,480,ColorRGB(0.5f,0.0f,1.0f))
{
}
//----------------------------------------------------------------------------
BezierMesh* BezierSurface::CreateRectangleMesh (int iDegree, bool bUseNormals,
    bool bUseColors, bool bUseTextures)
{
    int iCtrlQuantity = (iDegree+1)*(iDegree+1);
    int* aiIndex = new int[iCtrlQuantity];
    int i;
    for (i = 0; i < iCtrlQuantity; i++)
        aiIndex[i] = i;

    Vector3f* akVertex = new Vector3f[iCtrlQuantity];

    ColorRGB* akColor;
    if ( bUseColors )
        akColor = new ColorRGB[iCtrlQuantity];
    else
        akColor = NULL;

    Vector2f* akTexture;
    if ( bUseTextures )
        akTexture = new Vector2f[iCtrlQuantity];
    else
        akTexture = NULL;

    i = 0;
    for (int iY = 0; iY <= iDegree; iY++)
    {
        float fV = iY/float(iDegree);
        float fY = 2.0f*fV - 1.0f;
        for (int iX = 0; iX <= iDegree; iX++)
        {
            float fU = iX/float(iDegree);
            float fX = 2.0f*fU - 1.0f;

            akVertex[i].X() = fX;
            akVertex[i].Y() = fY;
            akVertex[i].Z() = 1.0f - fX*fX - fY*fY;

            if ( bUseColors )
                akColor[i] = ColorRGB(fU,0.0f,fV);

            if ( bUseTextures )
                akTexture[i] = Vector2f(fU,fV);

            i++;
        }
    }

    BezierPatchPtr* aspkPatch = new BezierPatchPtr[1];
    if ( iDegree == 2 )
        aspkPatch[0] = new BezierRectangle2(aiIndex);
    else
        aspkPatch[0] = new BezierRectangle3(aiIndex);

    BezierMesh* pkMesh = new BezierMesh(iCtrlQuantity,akVertex,
        bUseNormals,akColor,akTexture,1,aspkPatch);

    return pkMesh;
}
//----------------------------------------------------------------------------
BezierMesh* BezierSurface::CreateTriangleMesh (int iDegree,
    bool bUseNormals, bool bUseColors, bool bUseTextures)
{
    int iCtrlQuantity = (iDegree+1)*(iDegree+2)/2;
    int* aiIndex = new int[iCtrlQuantity];
    int i;
    for (i = 0; i < iCtrlQuantity; i++)
        aiIndex[i] = i;

    Vector3f* akVertex = new Vector3f[iCtrlQuantity];

    ColorRGB* akColor;
    if ( bUseColors )
        akColor = new ColorRGB[iCtrlQuantity];
    else
        akColor = NULL;

    Vector2f* akTexture;
    if ( bUseTextures )
        akTexture = new Vector2f[iCtrlQuantity];
    else
        akTexture = NULL;

    i = 0;
    for (int iY = 0; iY <= iDegree; iY++)
    {
        float fV = iY/float(iDegree);
        float fY = 2.0f*fV - 1.0f;
        for (int iX = 0; iX <= iDegree - iY; iX++)
        {
            float fU = iX/float(iDegree);
            float fX = 2.0f*fU - 1.0f;

            akVertex[i].X() = fX;
            akVertex[i].Y() = fY;
            akVertex[i].Z() = 1.0f - fX*fX - fY*fY;

            if ( bUseColors )
                akColor[i] = ColorRGB(fU,0.0f,fV);

            if ( bUseTextures )
                akTexture[i] = Vector2f(fU,fV);

            i++;
        }
    }

    BezierPatchPtr* aspkPatch = new BezierPatchPtr[1];
    if ( iDegree == 2 )
        aspkPatch[0] = new BezierTriangle2(aiIndex);
    else
        aspkPatch[0] = new BezierTriangle3(aiIndex);

    BezierMesh* pkMesh = new BezierMesh(iCtrlQuantity,akVertex,
        bUseNormals,akColor,akTexture,1,aspkPatch);

    return pkMesh;
}
//----------------------------------------------------------------------------
BezierMesh* BezierSurface::CreateCylinderMesh (int iDegree,
    bool bUseNormals, bool bUseColors, bool bUseTextures)
{
    int iCtrlQuantity = 2*(iDegree+1);
    int* aiIndex = new int[iCtrlQuantity];
    int i;
    for (i = 0; i < iCtrlQuantity; i++)
        aiIndex[i] = i;

    Vector3f* akVertex = new Vector3f[iCtrlQuantity];

    ColorRGB* akColor;
    if ( bUseColors )
        akColor = new ColorRGB[iCtrlQuantity];
    else
        akColor = 0;

    Vector2f* akTexture;
    if ( bUseTextures )
        akTexture = new Vector2f[iCtrlQuantity];
    else
        akTexture = 0;

    i = 0;
    for (int iY = 0; iY < 2; iY++)
    {
        float fV = float(iY);
        float fY = 2.0f*fV - 1.0f;
        for (int iX = 0; iX <= iDegree; iX++)
        {
            float fU = iX/float(iDegree);
            float fX = 2.0f*fU - 1.0f;

            akVertex[i].X() = fX;
            akVertex[i].Y() = fY;
            akVertex[i].Z() = 1.0f - fX*fX - fY*fY;

            if ( bUseColors )
                akColor[i] = ColorRGB(fU,0.0f,fV);

            if ( bUseTextures )
                akTexture[i] = Vector2f(fU,fV);

            i++;
        }
    }

    BezierPatchPtr* aspkPatch = new BezierPatchPtr[1];
    if ( iDegree == 2 )
        aspkPatch[0] = new BezierCylinder2(aiIndex);
    else
        aspkPatch[0] = new BezierCylinder3(aiIndex);

    BezierMesh* pkMesh = new BezierMesh(iCtrlQuantity,akVertex,
        bUseNormals,akColor,akTexture,1,aspkPatch);

    return pkMesh;
}
//----------------------------------------------------------------------------
bool BezierSurface::OnInitialize ()
{
    if ( !Application::OnInitialize() )
        return false;

    // set up camera
    ms_spkCamera->SetFrustum(1.0f,100.0f,-0.55f,0.55f,0.4125f,-0.4125f);
    Vector3f kCLoc(-2.78f,0.00f,3.17f);
    Vector3f kCLeft(-0.79f,0.0f,-0.61f);
    Vector3f kCUp(0.0f,1.0f,0.0f);
    Vector3f kCDir(0.61f,0.0f,-0.79f);
    ms_spkCamera->SetFrame(kCLoc,kCLeft,kCUp,kCDir);

    // set up scene graph
    m_spkScene = new Node;

    bool bUseN = false;
    bool bUseC = true;
    bool bUseT = false;

    if ( bUseT )
    {
        unsigned int* auiData = new unsigned int[32*32];
        for (int i = 0; i < 32*32; i++)
        {
            auiData[i] =
                (rand() % 256) |
                ((rand() % 256) << 8) |
                ((rand() % 256) << 16);
        }
        Image* pkImage = new Image(Image::IT_RGBA8888,32,32,
            (unsigned char*)auiData);

        m_spkTexture = new Texture;
        m_spkTexture->SetImage(pkImage);
        m_spkTexture->Mipmap() = Texture::MM_NONE;
        m_spkTextureState = new TextureState;
        m_spkTextureState->Set(0,m_spkTexture);
        m_spkScene->SetRenderState(m_spkTextureState);
    }

    if ( GetCommand() )
    {
        if ( GetCommand()->Boolean("t") )
        {
            m_spkMesh = CreateTriangleMesh(2,bUseN,bUseC,bUseT);
        }
        else if ( GetCommand()->Boolean("r") )
        {
            m_spkMesh = CreateRectangleMesh(3,bUseN,bUseC,bUseT);
        }
        else if ( GetCommand()->Boolean("c") )
        {
            m_spkMesh = CreateCylinderMesh(2,bUseN,bUseC,bUseT);
        }
        else
        {
            m_spkMesh = CreateTriangleMesh(2,bUseN,bUseC,bUseT);
        }
    }
    else
    {
        m_spkMesh = CreateTriangleMesh(2,bUseN,bUseC,bUseT);
    }

    m_spkScene->AttachChild(m_spkMesh);

    m_spkWireframeState = new WireframeState;
    m_spkScene->SetRenderState(m_spkWireframeState);

    m_spkZBufferState = new ZBufferState;
    m_spkZBufferState->Enabled() = true;
    m_spkZBufferState->Writeable() = true;
    m_spkZBufferState->Compare() = ZBufferState::CF_LEQUAL;
    m_spkScene->SetRenderState(m_spkZBufferState);

    // initial update of objects
    ms_spkCamera->Update();
    m_spkScene->UpdateGS(0.0f);
    m_spkScene->UpdateRS();

    m_bTurretActive = true;
    SetTurretAxes();
    m_fTrnSpeed = 0.1f;
    m_fRotSpeed = 0.01f;

    return true;
}
//----------------------------------------------------------------------------
void BezierSurface::OnTerminate ()
{
    m_spkMesh = NULL;
    m_spkTexture = NULL;
    m_spkTextureState = NULL;
    m_spkWireframeState = NULL;
    m_spkZBufferState = NULL;
    m_spkScene = NULL;

    Application::OnTerminate();
}
//----------------------------------------------------------------------------
void BezierSurface::OnIdle ()
{
    MeasureTime();
    MoveCamera();

    ms_spkRenderer->ClearBuffers();
    if ( ms_spkRenderer->BeginScene() )
    {
        ms_spkRenderer->Draw(m_spkScene);
        DrawFrameRate(8,GetHeight()-8,ColorRGB::WHITE);
        ms_spkRenderer->EndScene();
    }
    ms_spkRenderer->DisplayBackBuffer();

    UpdateClicks();
}
//----------------------------------------------------------------------------
void BezierSurface::OnKeyDown (unsigned char ucKey, int, int)
{
    if ( ucKey == 'q' || ucKey == 'Q' || ucKey == KEY_ESCAPE )
    {
        RequestTermination();
        return;
    }

    int iLevel, iP;

    switch ( ucKey )
    {
    case '0':  // reset frame rate measurements
        ResetTime();
        return;
    case 'w':
        m_spkWireframeState->Enabled() = !m_spkWireframeState->Enabled();
        return;
    case '+':
        iLevel = m_spkMesh->GetTessellationLevel();
        if ( iLevel < 8 )
            m_spkMesh->Tessellate(iLevel+1);
        return;
    case '-':
        iLevel = m_spkMesh->GetTessellationLevel();
        if ( iLevel > 0 )
            m_spkMesh->Tessellate(iLevel-1);
        return;
    case '<':
        for (iP = 0; iP < m_spkMesh->GetPatchQuantity(); iP++)
        {
            BezierPatchPtr spPatch = m_spkMesh->Patch(iP);
            if ( spPatch->GetType() == BezierPatch::PT_CYLINDER )
            {
                BezierCylinder* pkCyln =
                    WmlSmartPointerCast(BezierCylinder,spPatch);
                if ( pkCyln->CylinderLevel() > 0 )
                {
                    pkCyln->CylinderLevel()--;
                    m_spkMesh->Tessellate(m_spkMesh->GetTessellationLevel());
                }
            }
        }
        return;
    case '>':
        for (iP = 0; iP < m_spkMesh->GetPatchQuantity(); iP++)
        {
            BezierPatchPtr spPatch = m_spkMesh->Patch(iP);
            if ( spPatch->GetType() == BezierPatch::PT_CYLINDER )
            {
                BezierCylinder* pkCyln =
                    WmlSmartPointerCast(BezierCylinder,spPatch);
                if ( pkCyln->CylinderLevel() < 8 )
                {
                    pkCyln->CylinderLevel()++;
                    m_spkMesh->Tessellate(m_spkMesh->GetTessellationLevel());
                }
            }
        }
        return;
    }
}
//----------------------------------------------------------------------------
void BezierSurface::OnMouseClick (int iButton, int iState, int iX, int iY,
    unsigned int uiModifiers)
{
    if ( iButton != MOUSE_LEFT_BUTTON || iState != MOUSE_DOWN )
        return;

    Vector3f kOrigin, kDirection;
    ms_spkCamera->GetPickRay(iX,iY,GetWidth(),GetHeight(),kOrigin,kDirection);

    // determine if the mesh or background was picked
    Spatial::PickArray kResults;
    m_spkScene->DoPick(kOrigin,kDirection,kResults);

    float fRayT;
    ColorRGB* akColor = new ColorRGB[1];

    if ( kResults.size() > 0 )
    {
        // The mesh was picked.  Increase the tessellation level if a shift
        // key is simultaneously pressed with the left button.  Decrease the
        // tessellation level otherwise.
        int iLevel;
        if ( uiModifiers & KEY_SHIFT )
        {
            iLevel = m_spkMesh->GetTessellationLevel();
            if ( iLevel < 8 )
                m_spkMesh->Tessellate(iLevel+1);
        }
        else
        {
            iLevel = m_spkMesh->GetTessellationLevel();
            if ( iLevel > 0 )
                m_spkMesh->Tessellate(iLevel-1);
        }

        // Create a point slightly in front of the mesh where the mouse was
        // clicked.
        BezierMesh::PickRecord* pkRec = (BezierMesh::PickRecord*)kResults[0];
        fRayT = 0.99f*pkRec->m_fRayT;
        akColor[0].r = 1.0f;
        akColor[0].g = 1.0f;
        akColor[0].b = 1.0f;

        for (int i = 0; i < (int)kResults.size(); i++)
            delete kResults[i];
    }
    else
    {
        // The background was picked.  Draw a single point where the mouse was
        // clicked.
        fRayT = 0.5f*(ms_spkCamera->GetFrustumNear() +
            ms_spkCamera->GetFrustumFar());
        akColor[0].r = Mathf::UnitRandom();
        akColor[0].g = Mathf::UnitRandom();
        akColor[0].b = Mathf::UnitRandom();
    }

    Vector3f* akVertex = new Vector3f[1];
    akVertex[0] = kOrigin + fRayT*kDirection;

    Polypoint* pkPoints = new Polypoint(1,akVertex,NULL,akColor,NULL);
    m_spkScene->AttachChild(pkPoints);
    m_spkScene->UpdateGS(0.0f);
    m_spkScene->UpdateRS();
}
//----------------------------------------------------------------------------

⌨️ 快捷键说明

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