terrain.cpp

来自「3D Game Engine Design Source Code非常棒」· C++ 代码 · 共 293 行

CPP
293
字号
// 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 "Terrain.h"

Terrain g_kTheApp;

//----------------------------------------------------------------------------
Terrain::Terrain ()
    :
    Application("Terrain",0,0,640,480,ColorRGB(0.5f,0.0f,1.0f))
{
    m_fHeightAboveTerrain = 2.0f;
    m_bInitialized = false;
}
//----------------------------------------------------------------------------
bool Terrain::CreateTerrain ()
{
    // This file contains a 129-by-129 array of unsigned short.  The values
    // were generated from a 256-by-256 gray scale image where the image
    // intensities were treated as heights.
    FILE* pkHeightFile = fopen("height129x129.raw","rb");
    if ( !pkHeightFile ) return false;
    unsigned short usSize = 129, usQuantity = usSize*usSize;
    unsigned short* ausHeight = new unsigned short[usQuantity];
    fread(ausHeight,sizeof(unsigned short),usQuantity,pkHeightFile);
#ifdef WML_BIG_ENDIAN
    StreamSwapBytes(usQuantity,ausHeight);
#endif
    fclose(pkHeightFile);

    // create the terrain
    Vector2f kOrigin = Vector2f::ZERO;
    float fMinElevation = 0.0f;
    float fMaxElevation = 255.0f;
    float fSpacing = 1.0f;
    m_spkPage = new TerrainPage(usSize,ausHeight,kOrigin,fMinElevation,
        fMaxElevation,fSpacing);
    m_spkScene->AttachChild(m_spkPage);

    // Create the terrain texture.  This is a 256-by-256 RGB image that was
    // the original image used to generate the height field, but with colors
    // set to simulate variations in altitude.
    Texture* pkTexture = new Texture;
    Image* pkImage = Image::Load("texture.mif");
    if ( !pkImage ) return false;
    pkTexture->SetImage(pkImage);
    pkTexture->Filter() = Texture::FM_LINEAR;
    pkTexture->Mipmap() = Texture::MM_LINEAR_LINEAR;
    TextureState* pkTextureState = new TextureState;
    pkTextureState->Set(0,pkTexture);
    m_spkScene->SetRenderState(pkTextureState);

    return true;
}
//----------------------------------------------------------------------------
bool Terrain::OnInitialize ()
{
    if ( !Application::OnInitialize() )
        return false;

    // set up camera
    ms_spkCamera->SetFrustum(1.0f,1000.0f,-0.55f,0.55f,0.4125f,-0.4125f);

    // create root of scene graph
    m_spkScene = new Node(1);
    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);

    // create terrain heights and textures
    if ( !CreateTerrain() )
        return true;

    // position the camera in the middle of the page
    float fHeight = m_spkPage->GetHeight(Vector2f(64.0f,64.0f));
    Vector3f kCLoc(64.0f,64.0f,fHeight + m_fHeightAboveTerrain);
    Vector3f kCLeft(0.0f,-1.0f,0.0f);
    Vector3f kCUp(0.0f,0.0f,1.0f);
    Vector3f kCDir(-1.0f,0.0f,0.0f);
    ms_spkCamera->SetFrame(kCLoc,kCLeft,kCUp,kCDir);
    ms_spkCamera->Update();

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

    m_bTurretActive = true;
    SetTurretAxes();
    m_fTrnSpeed = 0.05f;
    m_fRotSpeed = 0.05f;

    m_bInitialized = true;
    return true;
}
//----------------------------------------------------------------------------
void Terrain::OnTerminate ()
{
    m_spkPage = NULL;
    m_spkWireframeState = NULL;
    m_spkZBufferState = NULL;
    m_spkScene = NULL;

    Application::OnTerminate();
}
//----------------------------------------------------------------------------
void Terrain::DrawStatistics (int iX, int iY, const ColorRGB& rkColor)
{
    if ( ms_spkRenderer )
    {
        char acMessage[256];
        sprintf(acMessage,"vertices = %d  triangles = %d",
            m_spkPage->GetVertexQuantity(),m_spkPage->GetTriangleQuantity());
        ms_spkRenderer->Draw(iX,iY,rkColor,acMessage);
    }
}
//----------------------------------------------------------------------------
void Terrain::OnIdle ()
{
    MeasureTime();

    MoveCamera();

    ms_spkRenderer->ClearBuffers();
    if ( ms_spkRenderer->BeginScene() )
    {
        if ( m_bInitialized )
        {
            ms_spkRenderer->Draw(m_spkScene);
            DrawFrameRate(8,GetHeight()-8,ColorRGB::WHITE);
            DrawStatistics(96,GetHeight()-8,ColorRGB::WHITE);
        }
        else
        {
            ms_spkRenderer->Draw(8,16,ColorRGB::WHITE,
                "Load of height129x129.raw or texture.mif failed.");
            ms_spkRenderer->Draw(8,32,ColorRGB::WHITE,
                "Make sure these files are in the same directory as the "
                "executable.");
        }

        ms_spkRenderer->EndScene();
    }
    ms_spkRenderer->DisplayBackBuffer();

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

    switch ( ucKey )
    {
    case '0':  // reset frame rate measurements
        ResetTime();
        return;
    case 'w':
        m_spkWireframeState->Enabled() = !m_spkWireframeState->Enabled();
        return;
    case 's':
        Simplify();
        return;
    case '+':
    case '=':
        m_spkPage->SetPixelTolerance(ms_spkRenderer,
            m_spkPage->GetPixelTolerance() + 1.0f);
        Simplify();
        return;
    case '-':
    case '_':
        if ( m_spkPage->GetPixelTolerance() > 1.0f )
        {
            m_spkPage->SetPixelTolerance(ms_spkRenderer,
                m_spkPage->GetPixelTolerance() - 1.0f);
            Simplify();
        }
        return;
    }
}
//----------------------------------------------------------------------------
void Terrain::MoveForward ()
{
    Application::MoveForward();

    Vector3f kLoc = ms_spkCamera->GetLocation();
    float fHeight = m_spkPage->GetHeight(Vector2f(kLoc.X(),kLoc.Y()));
    kLoc.Z() = fHeight + m_fHeightAboveTerrain;
    ms_spkCamera->SetLocation(kLoc);
    ms_spkCamera->Update();

    Simplify();
}
//----------------------------------------------------------------------------
void Terrain::MoveBackward ()
{
    Application::MoveBackward();

    Vector3f kLoc = ms_spkCamera->GetLocation();
    float fHeight = m_spkPage->GetHeight(Vector2f(kLoc.X(),kLoc.Y()));
    kLoc.Z() = fHeight + m_fHeightAboveTerrain;
    ms_spkCamera->SetLocation(kLoc);
    ms_spkCamera->Update();

    Simplify();
}
//----------------------------------------------------------------------------
void Terrain::MoveDown ()
{
    if ( m_fHeightAboveTerrain >= 1.0f )
        m_fHeightAboveTerrain -= 1.0f;

    Vector3f kLoc = ms_spkCamera->GetLocation();
    float fHeight = m_spkPage->GetHeight(Vector2f(kLoc.X(),kLoc.Y()));
    kLoc.Z() = fHeight + m_fHeightAboveTerrain;
    ms_spkCamera->SetLocation(kLoc);
    ms_spkCamera->Update();

    Simplify();
}
//----------------------------------------------------------------------------
void Terrain::MoveUp ()
{
    m_fHeightAboveTerrain += 1.0f;

    Vector3f kLoc = ms_spkCamera->GetLocation();
    float fHeight = m_spkPage->GetHeight(Vector2f(kLoc.X(),kLoc.Y()));
    kLoc.Z() = fHeight + m_fHeightAboveTerrain;
    ms_spkCamera->SetLocation(kLoc);
    ms_spkCamera->Update();

    Simplify();
}
//----------------------------------------------------------------------------
void Terrain::TurnLeft ()
{
    Application::TurnLeft();
    Simplify();
}
//----------------------------------------------------------------------------
void Terrain::TurnRight ()
{
    Application::TurnRight();
    Simplify();
}
//----------------------------------------------------------------------------
void Terrain::LookUp ()
{
    Application::LookUp();
    Simplify();
}
//----------------------------------------------------------------------------
void Terrain::LookDown ()
{
    Application::LookDown();
    Simplify();
}
//----------------------------------------------------------------------------
void Terrain::Simplify ()
{
    // initialize the page
    m_spkPage->ResetBlocks();

    // camera location in terrain model space
    const Vector3f& rkWorldEye = ms_spkCamera->GetLocation();
    Vector3f kDiff = rkWorldEye - m_spkPage->WorldTranslate();
    float fInvScale = 1.0f/m_spkPage->WorldScale();
    Vector3f kModelEye = fInvScale*(kDiff*m_spkPage->WorldRotate());

    // camera direction in terrain model space
    const Vector3f& rkWorldDir = ms_spkCamera->GetDirection();
    Vector3f kModelDir = rkWorldDir*m_spkPage->WorldRotate();

    bool bCloseAssumption = false;
    m_spkPage->Simplify(ms_spkRenderer,kModelEye,kModelDir,bCloseAssumption);
}
//----------------------------------------------------------------------------

⌨️ 快捷键说明

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