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

📄 testboxfrustum.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 <MgcIntrBox3Frustum.h>
#include "TestBoxFrustum.h"

//---------------------------------------------------------------------------
MgcApplication* MgcApplication::Create ()
{
    return new TestBoxFrustum;
}
//---------------------------------------------------------------------------
TestBoxFrustum::TestBoxFrustum ()
    :
    MgcApplication("TestBoxFrustum",640,480,0,1)
{
    // set up bindings for camera turret
    m_fTrnSpeed = 1.0;
    m_fRotSpeed = 0.1;
    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();
}
//---------------------------------------------------------------------------
bool TestBoxFrustum::Initialize ()
{
    // set up renderer
    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,1000.0,-0.55,0.55,0.4125,-0.4125);
    m_spkRenderer->SetCamera(m_spkCamera);

    // render states
    m_spkWireframeState = new MgcWireframeState;
    m_spkZBufferState = new MgcZBufferState;
    m_spkZBufferState->Enabled() = true;
    m_spkZBufferState->Writeable() = true;
    m_spkZBufferState->Compare() = MgcZBufferState::CF_LEQUAL;

    // create scene
    m_spkScene = new MgcNode;
    m_spkScene->SetRenderState(m_spkZBufferState);

    CreateBox();
    m_spkBox->Translate() = 4.0*MgcVector3::UNIT_X;
    m_spkBox->SetRenderState(m_spkWireframeState);
    m_spkScene->AttachChild(m_spkBox);

    CreateFrustum();
    m_spkFrustum->Translate() = -4.0*MgcVector3::UNIT_X;
    m_spkScene->AttachChild(m_spkFrustum);

    m_spkScene->UpdateGS(0.0);
    m_spkScene->UpdateRS();

    m_pkObject = m_spkScene;

    return true;
}
//---------------------------------------------------------------------------
void TestBoxFrustum::Terminate ()
{
    m_spkBox = 0;
    m_spkFrustum = 0;
    m_spkWireframeState = 0;
    m_spkZBufferState = 0;
    m_spkCamera = 0;
    m_spkRenderer = 0;
    m_spkScene = 0;
}
//---------------------------------------------------------------------------
void TestBoxFrustum::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 TestBoxFrustum::Transform (char cCharCode, long lKeyData)
{
    static MgcReal fTime = 0.0;
    MgcMatrix3 rot, incr;

    switch ( cCharCode )
    {
        case 'w':
            m_spkWireframeState->Enabled() = !m_spkWireframeState->Enabled();
            return true;
        case 'c':
            if ( m_pkObject == m_spkScene )
                m_pkObject = m_spkBox;
            else if ( m_pkObject == m_spkBox )
                m_pkObject = m_spkFrustum;
            else // m_pkObject == m_spkFrustum
                m_pkObject = m_spkScene;
            return true;
        case 'x':
            m_pkObject->Translate().x -= m_fTrnSpeed;
            break;
        case 'X':
            m_pkObject->Translate().x += m_fTrnSpeed;
            break;
        case 'y':
            m_pkObject->Translate().y -= m_fTrnSpeed;
            break;
        case 'Y':
            m_pkObject->Translate().y += m_fTrnSpeed;
            break;
        case 'z':
            m_pkObject->Translate().z -= m_fTrnSpeed;
            break;
        case 'Z':
            m_pkObject->Translate().z += m_fTrnSpeed;
            break;
        case 'r':
            rot = m_pkObject->Rotate();
            incr.FromAxisAngle(MgcVector3::UNIT_X,m_fRotSpeed);
            m_pkObject->Rotate() = incr*rot;
            break;
        case 'R':
            rot = m_pkObject->Rotate();
            incr.FromAxisAngle(MgcVector3::UNIT_X,-m_fRotSpeed);
            m_pkObject->Rotate() = incr*rot;
            break;
        case 'a':
            rot = m_pkObject->Rotate();
            incr.FromAxisAngle(MgcVector3::UNIT_Y,m_fRotSpeed);
            m_pkObject->Rotate() = incr*rot;
            break;
        case 'A':
            rot = m_pkObject->Rotate();
            incr.FromAxisAngle(MgcVector3::UNIT_Y,-m_fRotSpeed);
            m_pkObject->Rotate() = incr*rot;
            break;
        case 'p':
            rot = m_pkObject->Rotate();
            incr.FromAxisAngle(MgcVector3::UNIT_Z,m_fRotSpeed);
            m_pkObject->Rotate() = incr*rot;
            break;
        case 'P':
            rot = m_pkObject->Rotate();
            incr.FromAxisAngle(MgcVector3::UNIT_Z,-m_fRotSpeed);
            m_pkObject->Rotate() = incr*rot;
            break;
        default:
            return false;
    }

    m_pkObject->UpdateGS(fTime);

    m_kBox.Center() = m_spkBox->WorldTranslate();
    rot = m_spkBox->WorldRotate();
    m_kBox.Axis(0) = rot.GetColumn(0);
    m_kBox.Axis(1) = rot.GetColumn(1);
    m_kBox.Axis(2) = rot.GetColumn(2);

    m_kFrustum.Origin() = m_spkFrustum->WorldTranslate();
    rot = m_spkFrustum->WorldRotate();
    m_kFrustum.LVector() = rot.GetColumn(0);
    m_kFrustum.UVector() = rot.GetColumn(1);
    m_kFrustum.DVector() = rot.GetColumn(2);

    m_spkWireframeState->Enabled() = MgcTestIntersection(m_kBox,m_kFrustum);

    return true;
}
//---------------------------------------------------------------------------
bool TestBoxFrustum::WmChar (char cCharCode, long lKeyData)
{
    if ( Transform(cCharCode,lKeyData) )
        return true;

    switch ( cCharCode )
    {
    case 'q':
    case 'Q':
    case VK_ESCAPE:
        PostMessage(GetWindowHandle(),WM_DESTROY,0,0);
        return true;
    }

    return false;
}
//---------------------------------------------------------------------------
void TestBoxFrustum::CreateBox ()
{
    m_kBox.Center() = MgcVector3::ZERO;
    m_kBox.Axis(0) = MgcVector3::UNIT_X;
    m_kBox.Axis(1) = MgcVector3::UNIT_Y;
    m_kBox.Axis(2) = MgcVector3::UNIT_Z;
    m_kBox.Extent(0) = 1.0;
    m_kBox.Extent(1) = 1.0;
    m_kBox.Extent(2) = 1.0;

    unsigned int uiVertexQuantity = 8;
    unsigned int uiTriangleQuantity = 12;

    MgcVector3* akVertex = new MgcVector3[uiVertexQuantity];
    m_kBox.ComputeVertices(akVertex);

    MgcVector2* akTexture = new MgcVector2[uiVertexQuantity];
    akTexture[0] = MgcVector2(0,0);
    akTexture[1] = MgcVector2(1,0);
    akTexture[2] = MgcVector2(1,1);
    akTexture[3] = MgcVector2(0,1);
    akTexture[4] = MgcVector2(0,0);
    akTexture[5] = MgcVector2(1,0);
    akTexture[6] = MgcVector2(1,1);
    akTexture[7] = MgcVector2(0,1);

    unsigned int* auiConnect = new unsigned int[3*uiTriangleQuantity];
    auiConnect[ 0] = 0; auiConnect[ 1] = 2; auiConnect[ 2] = 1;
    auiConnect[ 3] = 0; auiConnect[ 4] = 3; auiConnect[ 5] = 2;
    auiConnect[ 6] = 4; auiConnect[ 7] = 5; auiConnect[ 8] = 6;
    auiConnect[ 9] = 4; auiConnect[10] = 6; auiConnect[11] = 7;
    auiConnect[12] = 1; auiConnect[13] = 6; auiConnect[14] = 5;
    auiConnect[15] = 1; auiConnect[16] = 2; auiConnect[17] = 6;
    auiConnect[18] = 0; auiConnect[19] = 7; auiConnect[20] = 3;
    auiConnect[21] = 0; auiConnect[22] = 4; auiConnect[23] = 7;
    auiConnect[24] = 0; auiConnect[25] = 1; auiConnect[26] = 5;
    auiConnect[27] = 0; auiConnect[28] = 5; auiConnect[29] = 4;
    auiConnect[30] = 3; auiConnect[31] = 6; auiConnect[32] = 2;
    auiConnect[33] = 3; auiConnect[34] = 7; auiConnect[35] = 6;

    m_spkBox = new MgcTriMesh(uiVertexQuantity,akVertex,0,0,akTexture,
        uiTriangleQuantity,auiConnect);

    m_spkBox->UpdateModelBound();

    // solid texture
    unsigned int uiYMax = 256, uiXMax = 8;
    unsigned int* auiData = new unsigned int[uiXMax*uiYMax];
    for (unsigned int uiY = 0, uiI = 0; uiY < uiYMax; uiY++)
    {
        unsigned int uiR = uiY;
        unsigned int uiG = uiYMax - 1 - uiY;
        unsigned int uiB = 0;
        unsigned int uiA = 0xFF;
        unsigned int uiColor = (uiR | uiG << 8 | uiB << 16 | uiA << 24);
        for (unsigned int uiX = 0; uiX < uiXMax; uiX++)
            auiData[uiI++] = uiColor;
    }
    MgcImage* pkImage = new MgcImage(MgcImage::IT_RGBA8888,uiXMax,uiYMax,
        (unsigned char*)auiData);

    MgcTexture* pkTexture = new MgcTexture;
    pkTexture->SetImage(pkImage);
    pkTexture->Mipmap() = MgcTexture::MM_LINEAR_LINEAR;

    MgcTextureState* pkTextureState = new MgcTextureState;
    pkTextureState->Set(0,pkTexture);
    m_spkBox->SetRenderState(pkTextureState);
}
//---------------------------------------------------------------------------
void TestBoxFrustum::CreateFrustum ()
{
    m_kFrustum.Origin() = MgcVector3::ZERO;
    m_kFrustum.LVector() = MgcVector3::UNIT_X;
    m_kFrustum.UVector() = MgcVector3::UNIT_Y;
    m_kFrustum.DVector() = MgcVector3::UNIT_Z;
    m_kFrustum.LBound() = 1.0;
    m_kFrustum.UBound() = 1.0;
    m_kFrustum.DMin() = 1.0;
    m_kFrustum.DMax() = 16.0;
    m_kFrustum.Update();

    unsigned int uiVertexQuantity = 8;
    unsigned int uiTriangleQuantity = 12;

    MgcVector3* akVertex = new MgcVector3[uiVertexQuantity];
#if 0
    akVertex[0] = MgcVector3(-1,-1,-1);
    akVertex[1] = MgcVector3(+1,-1,-1);
    akVertex[2] = MgcVector3(+1,+1,-1);
    akVertex[3] = MgcVector3(-1,+1,-1);
    akVertex[4] = MgcVector3(-1,-1,+1);
    akVertex[5] = MgcVector3(+1,-1,+1);
    akVertex[6] = MgcVector3(+1,+1,+1);
    akVertex[7] = MgcVector3(-1,+1,+1);
#else
    m_kFrustum.ComputeVertices(akVertex);
#endif

    MgcVector2* akTexture = new MgcVector2[uiVertexQuantity];
    akTexture[0] = MgcVector2(0,0);
    akTexture[1] = MgcVector2(1,0);
    akTexture[2] = MgcVector2(1,1);
    akTexture[3] = MgcVector2(0,1);
    akTexture[4] = MgcVector2(0,0);
    akTexture[5] = MgcVector2(1,0);
    akTexture[6] = MgcVector2(1,1);
    akTexture[7] = MgcVector2(0,1);

    unsigned int* auiConnect = new unsigned int[3*uiTriangleQuantity];
    auiConnect[ 0] = 0; auiConnect[ 1] = 2; auiConnect[ 2] = 1;
    auiConnect[ 3] = 0; auiConnect[ 4] = 3; auiConnect[ 5] = 2;
    auiConnect[ 6] = 4; auiConnect[ 7] = 5; auiConnect[ 8] = 6;
    auiConnect[ 9] = 4; auiConnect[10] = 6; auiConnect[11] = 7;
    auiConnect[12] = 1; auiConnect[13] = 6; auiConnect[14] = 5;
    auiConnect[15] = 1; auiConnect[16] = 2; auiConnect[17] = 6;
    auiConnect[18] = 0; auiConnect[19] = 7; auiConnect[20] = 3;
    auiConnect[21] = 0; auiConnect[22] = 4; auiConnect[23] = 7;
    auiConnect[24] = 0; auiConnect[25] = 1; auiConnect[26] = 5;
    auiConnect[27] = 0; auiConnect[28] = 5; auiConnect[29] = 4;
    auiConnect[30] = 3; auiConnect[31] = 6; auiConnect[32] = 2;
    auiConnect[33] = 3; auiConnect[34] = 7; auiConnect[35] = 6;

    m_spkFrustum = new MgcTriMesh(uiVertexQuantity,akVertex,0,0,akTexture,
        uiTriangleQuantity,auiConnect);

    m_spkFrustum->UpdateModelBound();

    // alpha-blended texture
    MgcAlphaState* pkAlpha = new MgcAlphaState;
    pkAlpha->Test() = MgcAlphaState::TF_LEQUAL;
    pkAlpha->BlendEnabled() = true;
    m_spkFrustum->SetRenderState(pkAlpha);

    unsigned int uiYMax = 256, uiXMax = 8;
    unsigned int* auiData = new unsigned int[uiXMax*uiYMax];
    for (unsigned int uiY = 0, uiI = 0; uiY < uiYMax; uiY++)
    {
        unsigned int uiR = uiY;
        unsigned int uiG = 0;
        unsigned int uiB = uiYMax - 1 - uiY;
        unsigned int uiA = 0x80;
        unsigned int uiColor = (uiR | uiG << 8 | uiB << 16 | uiA << 24);
        for (unsigned int uiX = 0; uiX < uiXMax; uiX++)
            auiData[uiI++] = uiColor;
    }
    MgcImage* pkImage = new MgcImage(MgcImage::IT_RGBA8888,uiXMax,uiYMax,
        (unsigned char*)auiData);

    MgcTexture* pkTexture = new MgcTexture;
    pkTexture->SetImage(pkImage);
    pkTexture->Mipmap() = MgcTexture::MM_LINEAR_LINEAR;

    MgcTextureState* pkTextureState = new MgcTextureState;
    pkTextureState->Set(0,pkTexture);
    m_spkFrustum->SetRenderState(pkTextureState);
}
//---------------------------------------------------------------------------

⌨️ 快捷键说明

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