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

📄 testbezier.cpp

📁 《3D游戏引擎设计》的源码
💻 CPP
字号:
// Magic Software, Inc.
// http://www.magic-software.com
// Copyright (c) 2000, All Rights Reserved
//
// Source code from Magic Software is supplied under the terms of a license
// agreement and may not be copied or disclosed except in accordance with the
// terms of that agreement.  The various license agreements may be found at
// the Magic Software web site.  This file is subject to the license
//
// FREE SOURCE CODE
// http://www.magic-software.com/License.html/free.pdf

#include "TestBezier.h"

//---------------------------------------------------------------------------
MgcApplication* MgcApplication::Create ()
{
    return new TestBezier;
}
//---------------------------------------------------------------------------
TestBezier::TestBezier ()
    :
    MgcApplication("TestBezier",640,480,0,1)
{
    // set up bindings for camera turret
    m_fTrnSpeed = 0.1;
    m_fRotSpeed = 0.01;
    m_kTurret.BindKeysToTranslateRight('[',']',m_fTrnSpeed);
    m_kTurret.BindKeysToTranslateUp('{','}',m_fTrnSpeed);
    m_kTurret.BindKeysToTranslateDirection(VK_DOWN,VK_UP,m_fTrnSpeed);
    m_kTurret.BindKeysToRotateRight(VK_PRIOR,VK_NEXT,0.1*m_fRotSpeed);
    m_kTurret.BindKeysToRotateUp(VK_RIGHT,VK_LEFT,0.1*m_fRotSpeed);

    // initialize 'last time'
    MeasureTime();
}
//---------------------------------------------------------------------------
MgcBezierMesh* TestBezier::CreateRectangleMesh (unsigned int uiDegree,
    bool bUseNormals, bool bUseColors, bool bUseTextures)
{
    unsigned int uiCtrlQuantity = (uiDegree+1)*(uiDegree+1);
    unsigned int* auiIndex = new unsigned int[uiCtrlQuantity];
    unsigned int uiI;
    for (uiI = 0; uiI < uiCtrlQuantity; uiI++)
        auiIndex[uiI] = uiI;

    MgcVector3* akVertex = new MgcVector3[uiCtrlQuantity];

    MgcColor* akColor;
    if ( bUseColors )
        akColor = new MgcColor[uiCtrlQuantity];
    else
        akColor = 0;

    MgcVector2* akTexture;
    if ( bUseTextures )
        akTexture = new MgcVector2[uiCtrlQuantity];
    else
        akTexture = 0;

    uiI = 0;
    for (unsigned int uiY = 0; uiY <= uiDegree; uiY++)
    {
        MgcReal fV = uiY/MgcReal(uiDegree);
        MgcReal fY = 2.0*fV - 1.0;
        for (unsigned int uiX = 0; uiX <= uiDegree; uiX++)
        {
            MgcReal fU = uiX/MgcReal(uiDegree);
            MgcReal fX = 2.0*fU - 1.0;

            akVertex[uiI].x = fX;
            akVertex[uiI].y = fY;
            akVertex[uiI].z = 1.0 - fX*fX - fY*fY;

            if ( bUseColors )
                akColor[uiI] = MgcColor(fU,0.0,fV);

            if ( bUseTextures )
                akTexture[uiI] = MgcVector2(fU,fV);

            uiI++;
        }
    }

    MgcBezierPatchPtr* aspkPatch = new MgcBezierPatchPtr[1];
    if ( uiDegree == 2 )
        aspkPatch[0] = new MgcBezierRectangle2(auiIndex);
    else
        aspkPatch[0] = new MgcBezierRectangle3(auiIndex);

    MgcBezierMesh* pkMesh = new MgcBezierMesh(uiCtrlQuantity,akVertex,
        bUseNormals,akColor,akTexture,1,aspkPatch);

    return pkMesh;
}
//---------------------------------------------------------------------------
MgcBezierMesh* TestBezier::CreateTriangleMesh (unsigned int uiDegree,
    bool bUseNormals, bool bUseColors, bool bUseTextures)
{
    unsigned int uiCtrlQuantity = (uiDegree+1)*(uiDegree+2)/2;
    unsigned int* auiIndex = new unsigned int[uiCtrlQuantity];
    unsigned int uiI;
    for (uiI = 0; uiI < uiCtrlQuantity; uiI++)
        auiIndex[uiI] = uiI;

    MgcVector3* akVertex = new MgcVector3[uiCtrlQuantity];

    MgcColor* akColor;
    if ( bUseColors )
        akColor = new MgcColor[uiCtrlQuantity];
    else
        akColor = 0;

    MgcVector2* akTexture;
    if ( bUseTextures )
        akTexture = new MgcVector2[uiCtrlQuantity];
    else
        akTexture = 0;

    uiI = 0;
    for (unsigned int uiY = 0; uiY <= uiDegree; uiY++)
    {
        MgcReal fV = uiY/MgcReal(uiDegree);
        MgcReal fY = 2.0*fV - 1.0;
        for (unsigned int uiX = 0; uiX <= uiDegree - uiY; uiX++)
        {
            MgcReal fU = uiX/MgcReal(uiDegree);
            MgcReal fX = 2.0*fU - 1.0;

            akVertex[uiI].x = fX;
            akVertex[uiI].y = fY;
            akVertex[uiI].z = 1.0 - fX*fX - fY*fY;

            if ( bUseColors )
                akColor[uiI] = MgcColor(fU,0.0,fV);

            if ( bUseTextures )
                akTexture[uiI] = MgcVector2(fU,fV);

            uiI++;
        }
    }

    MgcBezierPatchPtr* aspkPatch = new MgcBezierPatchPtr[1];
    if ( uiDegree == 2 )
        aspkPatch[0] = new MgcBezierTriangle2(auiIndex);
    else
        aspkPatch[0] = new MgcBezierTriangle3(auiIndex);

    MgcBezierMesh* pkMesh = new MgcBezierMesh(uiCtrlQuantity,akVertex,
        bUseNormals,akColor,akTexture,1,aspkPatch);

    return pkMesh;
}
//---------------------------------------------------------------------------
MgcBezierMesh* TestBezier::CreateCylinderMesh (unsigned int uiDegree,
    bool bUseNormals, bool bUseColors, bool bUseTextures)
{
    unsigned int uiCtrlQuantity = 2*(uiDegree+1);
    unsigned int* auiIndex = new unsigned int[uiCtrlQuantity];
    unsigned int uiI;
    for (uiI = 0; uiI < uiCtrlQuantity; uiI++)
        auiIndex[uiI] = uiI;

    MgcVector3* akVertex = new MgcVector3[uiCtrlQuantity];

    MgcColor* akColor;
    if ( bUseColors )
        akColor = new MgcColor[uiCtrlQuantity];
    else
        akColor = 0;

    MgcVector2* akTexture;
    if ( bUseTextures )
        akTexture = new MgcVector2[uiCtrlQuantity];
    else
        akTexture = 0;

    uiI = 0;
    for (unsigned int uiY = 0; uiY < 2; uiY++)
    {
        MgcReal fV = MgcReal(uiY);
        MgcReal fY = 2.0*fV - 1.0;
        for (unsigned int uiX = 0; uiX <= uiDegree; uiX++)
        {
            MgcReal fU = uiX/MgcReal(uiDegree);
            MgcReal fX = 2.0*fU - 1.0;

            akVertex[uiI].x = fX;
            akVertex[uiI].y = fY;
            akVertex[uiI].z = 1.0 - fX*fX - fY*fY;

            if ( bUseColors )
                akColor[uiI] = MgcColor(fU,0.0,fV);

            if ( bUseTextures )
                akTexture[uiI] = MgcVector2(fU,fV);

            uiI++;
        }
    }

    MgcBezierPatchPtr* aspkPatch = new MgcBezierPatchPtr[1];
    if ( uiDegree == 2 )
        aspkPatch[0] = new MgcBezierCylinder2(auiIndex);
    else
        aspkPatch[0] = new MgcBezierCylinder3(auiIndex);

    MgcBezierMesh* pkMesh = new MgcBezierMesh(uiCtrlQuantity,akVertex,
        bUseNormals,akColor,akTexture,1,aspkPatch);

    return pkMesh;
}
//---------------------------------------------------------------------------
bool TestBezier::Initialize ()
{
    m_spkRenderer = new MgcOglRenderer(GetWindowHandle(),640,480);
    m_spkRenderer->SetBackgroundColor(MgcColor(0.5f,0.0f,1.0f));

    m_spkCamera = new MgcOglCamera(640,480);
    m_spkCamera->SetFrustum(1.0,100.0,-0.55,0.55,0.4125,-0.4125);

    MgcVector3 kCLoc(-2.78,0.00,3.17);
    MgcVector3 kCLeft(-0.79,0.0,-0.61);
    MgcVector3 kCUp(0.0,1.0,0.0);
    MgcVector3 kCDir(0.61,0.0,-0.79);
    m_spkCamera->SetFrame(kCLoc,kCLeft,kCUp,kCDir);
    m_spkCamera->Update();

    m_spkRenderer->SetCamera(m_spkCamera);

    m_spkScene = new MgcNode;

    bool bUseNormals = false;
    bool bUseColors = true;
    bool bUseTextures = false;

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

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

#if 0
    m_spkMesh = CreateTriangleMesh(2,bUseNormals,bUseColors,bUseTextures);
#endif

#if 0
    m_spkMesh = CreateRectangleMesh(3,bUseNormals,bUseColors,bUseTextures);
#endif

#if 1
    m_spkMesh = CreateCylinderMesh(2,bUseNormals,bUseColors,bUseTextures);
#endif

    m_spkScene->AttachChild(m_spkMesh);

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

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

#if 0
    m_spkDLight = new MgcDirectionalLight;
    m_spkDLight->Direction() = kCDir;
    m_spkDLight->Ambient() = MgcColor(1.0,1.0,1.0);
    m_spkDLight->Diffuse() = MgcColor(1.0,1.0,1.0);
    m_spkLightState = new MgcLightState;
    m_spkLightState->Attach(m_spkDLight);
    m_spkScene->SetRenderState(m_spkLightState);
#endif

    m_spkScene->UpdateGS(0.0);
    m_spkScene->UpdateRS();
    return true;
}
//---------------------------------------------------------------------------
void TestBezier::Terminate ()
{
    m_spkMesh = 0;
    m_spkTexture = 0;
    m_spkTextureState = 0;
    m_spkWireframeState = 0;
    m_spkZBufferState = 0;
    m_spkDLight = 0;
    m_spkLightState = 0;
    m_spkCamera = 0;
    m_spkRenderer = 0;
    m_spkScene = 0;
}
//---------------------------------------------------------------------------
void TestBezier::OnIdle ()
{
    MeasureTime();

    if ( GetFocus() == GetWindowHandle() )
    {
        if ( m_kTurret.ReadKeyboard() )
        {
            m_spkRenderer->GetCamera()->SetFrame(m_kTurret.GetTranslate(),
                m_kTurret.GetRotate());
        }
    }

    m_spkRenderer->ClearBuffers();
    m_spkRenderer->Draw(m_spkScene);
    m_spkRenderer->DisplayBackBuffer();

    DrawFrameRate();
    UpdateClicks();
}
//---------------------------------------------------------------------------
bool TestBezier::WmChar (char cCharCode, long lKeyData)
{
    unsigned int uiLevel, uiP;

    switch ( cCharCode )
    {
    case '0':  // reset frame rate measurements
        ResetTime();
        return true;
    case 'w':
        m_spkWireframeState->Enabled() = !m_spkWireframeState->Enabled();
        return true;
    case '+':
        uiLevel = m_spkMesh->GetTessellationLevel();
        if ( uiLevel < 8 )
            m_spkMesh->Tessellate(uiLevel+1);
        return true;
    case '-':
        uiLevel = m_spkMesh->GetTessellationLevel();
        if ( uiLevel > 0 )
            m_spkMesh->Tessellate(uiLevel-1);
        return true;
    case '<':
        for (uiP = 0; uiP < m_spkMesh->GetPatchQuantity(); uiP++)
        {
            MgcBezierPatchPtr spPatch = m_spkMesh->Patch(uiP);
            if ( spPatch->GetType() == MgcBezierPatch::PT_CYLINDER )
            {
                MgcBezierCylinder* pkCyln =
                    MgcSmartPointerCast(MgcBezierCylinder,spPatch);
                if ( pkCyln->CylinderLevel() > 0 )
                {
                    pkCyln->CylinderLevel()--;
                    m_spkMesh->Tessellate(m_spkMesh->GetTessellationLevel());
                }
            }
        }
        return true;
    case '>':
        for (uiP = 0; uiP < m_spkMesh->GetPatchQuantity(); uiP++)
        {
            MgcBezierPatchPtr spPatch = m_spkMesh->Patch(uiP);
            if ( spPatch->GetType() == MgcBezierPatch::PT_CYLINDER )
            {
                MgcBezierCylinder* pkCyln =
                    MgcSmartPointerCast(MgcBezierCylinder,spPatch);
                if ( pkCyln->CylinderLevel() < 8 )
                {
                    pkCyln->CylinderLevel()++;
                    m_spkMesh->Tessellate(m_spkMesh->GetTessellationLevel());
                }
            }
        }
        return true;
    case 'q':
    case 'Q':
    case VK_ESCAPE:
        PostMessage(GetWindowHandle(),WM_DESTROY,0,0);
        return true;
    }

    return false;
}
//---------------------------------------------------------------------------

⌨️ 快捷键说明

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