📄 testterrain.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 "TestTerrain.h"
//---------------------------------------------------------------------------
MgcApplication* MgcApplication::Create ()
{
return new TestTerrain;
}
//---------------------------------------------------------------------------
TestTerrain::TestTerrain ()
:
MgcApplication("TestTerrain",640,480,0,2)
{
// initialize 'last time'
MeasureTime();
m_fHeightAboveTerrain = 2.0;
m_fTrnSpeed = 0.5;
m_fRotSpeed = 0.05;
m_bUArrowPressed = false;
m_bDArrowPressed = false;
m_bLArrowPressed = false;
m_bRArrowPressed = false;
m_bPgUpPressed = false;
m_bPgDnPressed = false;
}
//---------------------------------------------------------------------------
void TestTerrain::CreateTerrain ()
{
// Load Windows BMP. It is known that the image is 256-by-256. This
// fact is 'hard-coded' into this block of code.
HBITMAP hImage = (HBITMAP) LoadImage(NULL,"terrain.bmp",IMAGE_BITMAP,0,0,
LR_LOADFROMFILE | LR_CREATEDIBSECTION);
DIBSECTION dibSection;
GetObject(hImage,sizeof(DIBSECTION),&dibSection);
int iWidth = dibSection.dsBm.bmWidth;
int iHeight = dibSection.dsBm.bmHeight;
int iQuantity = dibSection.dsBm.bmWidth*dibSection.dsBm.bmHeight;
assert( iWidth == 256 && iHeight == 256 );
assert( dibSection.dsBm.bmBitsPixel == 24 );
// Windows BMP stores BGR, need to invert to RGB.
unsigned char* acSrc = (unsigned char*) dibSection.dsBm.bmBits;
unsigned char* acDst = new unsigned char[3*iQuantity];
int i, i0, i1, i2;
for (i = 0, i0 = 0, i1 = 1, i2 = 2; i < iQuantity; i++)
{
acDst[i0] = acSrc[i2];
acDst[i1] = acSrc[i1];
acDst[i2] = acSrc[i0];
i0 += 3;
i1 += 3;
i2 += 3;
}
DeleteObject(hImage);
// Image is grey scale. Use one of the channels to generate heights.
unsigned short usSize = 129;
unsigned short* ausHeight = new unsigned short[usSize*usSize];
memset(ausHeight,0,usSize*usSize*sizeof(unsigned short));
for (unsigned short usY = 0; usY < 128; usY++)
{
for (unsigned short usX = 0; usX < 128; usX++)
{
unsigned short usHIndex = usX + usSize*usY;
unsigned int uiDIndex = 6*(usX + iWidth*usY);
ausHeight[usHIndex] = 3*((unsigned short)acDst[uiDIndex]);
}
}
MgcVector2 kOrigin = MgcVector2::ZERO;
MgcReal fMinElevation = 0.0;
MgcReal fMaxElevation = 255.0;
MgcReal fSpacing = 1.0;
// create the terrain
m_spkPage = new MgcTerrainPage(usSize,ausHeight,kOrigin,fMinElevation,
fMaxElevation,fSpacing);
m_spkScene->AttachChild(m_spkPage);
// color remap
MgcReal fFrac;
for (i = 0, i0 = 0, i1 = 1, i2 = 2; i < iQuantity; i++)
{
if ( acDst[i0] < 8 )
{
// blue
fFrac = acDst[i0]/7.0;
acDst[i0] = 0;
acDst[i1] = 0;
acDst[i2] = 192 + (255-192)*fFrac;
}
else if ( acDst[i0] < 72 )
{
// yellow
fFrac = (acDst[i0] - 8.0)/64.0;
acDst[i0] = 128 + (255-128)*fFrac;
acDst[i1] = acDst[i0];
acDst[i2] = 0;
}
else if ( acDst[i0] < 128 )
{
// green
fFrac = (acDst[i0] - 72.0)/56.0;
acDst[i0] = 0;
acDst[i1] = 128+(255-128)*fFrac;
acDst[i2] = 0;
}
else if ( acDst[i0] < 192 )
{
// brown
fFrac = (acDst[i0] - 128.0)/64.0;
acDst[i0] = 64+(128-64)*fFrac;
acDst[i1] = acDst[i0];
acDst[i2] = 32;
}
else
{
// grey
fFrac = (acDst[i0] - 192.0)/64.0;
acDst[i0] = 192+(255-192)*fFrac;
acDst[i1] = acDst[i0];
acDst[i2] = acDst[i0];
}
i0 += 3;
i1 += 3;
i2 += 3;
}
// create the terrain texture
MgcImage* pkImage = new MgcImage(MgcImage::IT_RGB888,iWidth,iHeight,acDst);
MgcTexture* pkTexture = new MgcTexture;
pkTexture->SetImage(pkImage);
pkTexture->Filter() = MgcTexture::FM_LINEAR;
pkTexture->Mipmap() = MgcTexture::MM_LINEAR_LINEAR;
MgcTextureState* pkTextureState = new MgcTextureState;
pkTextureState->Set(0,pkTexture);
m_spkScene->SetRenderState(pkTextureState);
}
//---------------------------------------------------------------------------
bool TestTerrain::Initialize ()
{
// create camera and renderer
m_spkCamera = new MgcOglCamera(640,480);
m_spkCamera->SetFrustum(1.0,1000.0,-0.55,0.55,0.4125,-0.4125);
m_spkRenderer = new MgcOglRenderer(GetWindowHandle(),640,480);
m_spkRenderer->SetBackgroundColor(MgcColor(0.5f,0.0f,1.0f));
m_spkRenderer->SetCamera(m_spkCamera);
// create root of scene graph
MgcStream kStream;
m_spkScene = new MgcNode(1);
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);
// create terrain heights and textures
CreateTerrain();
// position the camera in the middle of the page
MgcReal fHeight = m_spkPage->GetHeight(MgcVector2(64.0,64.0));
MgcVector3 kCLoc(64.0,64.0,fHeight + m_fHeightAboveTerrain);
MgcVector3 kCLeft(0.0,-1.0,0.0);
MgcVector3 kCUp(0.0,0.0,1.0);
MgcVector3 kCDir(-1.0,0,0.0);
m_spkCamera->SetFrame(kCLoc,kCLeft,kCUp,kCDir);
m_spkCamera->Update();
Simplify();
m_spkScene->UpdateGS(0.0);
m_spkScene->UpdateRS();
return true;
}
//---------------------------------------------------------------------------
void TestTerrain::Terminate ()
{
m_spkPage = 0;
m_spkWireframeState = 0;
m_spkZBufferState = 0;
m_spkRenderer = 0;
m_spkScene = 0;
}
//---------------------------------------------------------------------------
void TestTerrain::OnIdle ()
{
MeasureTime();
if ( m_bUArrowPressed )
MoveForward();
else if ( m_bDArrowPressed )
MoveBackward();
if ( m_bLArrowPressed )
TurnLeft();
else if ( m_bRArrowPressed )
TurnRight();
if ( m_bPgUpPressed )
LookUp();
else if ( m_bPgDnPressed )
LookDown();
m_spkRenderer->ClearBuffers();
m_spkRenderer->Draw(m_spkScene);
m_spkRenderer->DisplayBackBuffer();
DrawFrameRate();
DisplayStatistics();
UpdateClicks();
}
//---------------------------------------------------------------------------
bool TestTerrain::WmChar (char cCharCode, long lKeyData)
{
switch ( cCharCode )
{
case '0': // reset frame rate measurements
ResetTime();
return true;
case 'w':
m_spkWireframeState->Enabled() = !m_spkWireframeState->Enabled();
return true;
case 's':
Simplify();
return true;
case '+':
case '=':
m_spkPage->SetPixelTolerance(m_spkRenderer,
m_spkPage->GetPixelTolerance() + 1.0);
Simplify();
return true;
case '-':
case '_':
if ( m_spkPage->GetPixelTolerance() > 1.0 )
{
m_spkPage->SetPixelTolerance(m_spkRenderer,
m_spkPage->GetPixelTolerance() - 1.0);
Simplify();
}
return true;
case 'q':
case 'Q':
case VK_ESCAPE:
PostMessage(GetWindowHandle(),WM_DESTROY,0,0);
return true;
}
return false;
}
//---------------------------------------------------------------------------
bool TestTerrain::WmKeyDown (int iVirtKey, long lKeyData)
{
MgcVector3 kLoc;
MgcReal fHeight;
switch ( iVirtKey )
{
case VK_UP:
m_bUArrowPressed = true;
break;
case VK_DOWN:
m_bDArrowPressed = true;
break;
case VK_LEFT:
m_bLArrowPressed = true;
break;
case VK_RIGHT:
m_bRArrowPressed = true;
break;
case VK_PRIOR:
m_bPgUpPressed = true;
break;
case VK_NEXT:
m_bPgDnPressed = true;
break;
case 'U':
m_fHeightAboveTerrain += 1.0;
kLoc = m_spkCamera->GetLocation();
fHeight = m_spkPage->GetHeight(MgcVector2(kLoc.x,kLoc.y));
kLoc.z = fHeight + m_fHeightAboveTerrain;
m_spkCamera->SetLocation(kLoc);
m_spkCamera->Update();
Simplify();
break;
case 'D':
if ( m_fHeightAboveTerrain >= 1.0 )
m_fHeightAboveTerrain -= 1.0;
kLoc = m_spkCamera->GetLocation();
fHeight = m_spkPage->GetHeight(MgcVector2(kLoc.x,kLoc.y));
kLoc.z = fHeight + m_fHeightAboveTerrain;
m_spkCamera->SetLocation(kLoc);
m_spkCamera->Update();
Simplify();
break;
default:
return false;
}
return true;
}
//---------------------------------------------------------------------------
bool TestTerrain::WmKeyUp (int iVirtKey, long lKeyData)
{
switch ( iVirtKey )
{
case VK_UP:
m_bUArrowPressed = false;
break;
case VK_DOWN:
m_bDArrowPressed = false;
break;
case VK_LEFT:
m_bLArrowPressed = false;
break;
case VK_RIGHT:
m_bRArrowPressed = false;
break;
case VK_PRIOR:
m_bPgUpPressed = false;
break;
case VK_NEXT:
m_bPgDnPressed = false;
break;
default:
return false;
}
return true;
}
//---------------------------------------------------------------------------
void TestTerrain::MoveForward ()
{
MgcVector3 kLoc = m_spkCamera->GetLocation();
MgcReal fHeight = m_spkPage->GetHeight(MgcVector2(kLoc.x,kLoc.y));
kLoc += m_fTrnSpeed*m_spkCamera->GetDirection();
kLoc.z = fHeight + m_fHeightAboveTerrain;
m_spkCamera->SetLocation(kLoc);
m_spkCamera->Update();
Simplify();
}
//---------------------------------------------------------------------------
void TestTerrain::MoveBackward ()
{
MgcVector3 kLoc = m_spkCamera->GetLocation();
MgcReal fHeight = m_spkPage->GetHeight(MgcVector2(kLoc.x,kLoc.y));
kLoc -= m_fTrnSpeed*m_spkCamera->GetDirection();
kLoc.z = fHeight + m_fHeightAboveTerrain;
m_spkCamera->SetLocation(kLoc);
m_spkCamera->Update();
Simplify();
}
//---------------------------------------------------------------------------
void TestTerrain::TurnLeft ()
{
MgcMatrix3 kIncr;
kIncr.FromAxisAngle(m_spkCamera->GetUp(),m_fRotSpeed);
MgcVector3 kLeft = kIncr*m_spkCamera->GetLeft();
MgcVector3 kDirection = kIncr*m_spkCamera->GetDirection();
m_spkCamera->SetAxes(kLeft,m_spkCamera->GetUp(),kDirection);
m_spkCamera->Update();
Simplify();
}
//---------------------------------------------------------------------------
void TestTerrain::TurnRight ()
{
MgcMatrix3 kIncr;
kIncr.FromAxisAngle(m_spkCamera->GetUp(),-m_fRotSpeed);
MgcVector3 kLeft = kIncr*m_spkCamera->GetLeft();
MgcVector3 kDirection = kIncr*m_spkCamera->GetDirection();
m_spkCamera->SetAxes(kLeft,m_spkCamera->GetUp(),kDirection);
m_spkCamera->Update();
Simplify();
}
//---------------------------------------------------------------------------
void TestTerrain::LookUp ()
{
MgcMatrix3 kIncr;
kIncr.FromAxisAngle(m_spkCamera->GetLeft(),-m_fRotSpeed);
MgcVector3 kUp = kIncr*m_spkCamera->GetUp();
MgcVector3 kDirection = kIncr*m_spkCamera->GetDirection();
m_spkCamera->SetAxes(m_spkCamera->GetLeft(),kUp,kDirection);
m_spkCamera->Update();
Simplify();
}
//---------------------------------------------------------------------------
void TestTerrain::LookDown ()
{
MgcMatrix3 kIncr;
kIncr.FromAxisAngle(m_spkCamera->GetLeft(),m_fRotSpeed);
MgcVector3 kUp = kIncr*m_spkCamera->GetUp();
MgcVector3 kDirection = kIncr*m_spkCamera->GetDirection();
m_spkCamera->SetAxes(m_spkCamera->GetLeft(),kUp,kDirection);
m_spkCamera->Update();
Simplify();
}
//---------------------------------------------------------------------------
void TestTerrain::Simplify ()
{
// initialize the page
m_spkPage->ResetBlocks();
// camera location in terrain model space
const MgcVector3& rkWorldEye = m_spkCamera->GetLocation();
MgcVector3 kDiff = rkWorldEye - m_spkPage->WorldTranslate();
MgcReal fInvScale = 1.0/m_spkPage->WorldScale();
MgcVector3 kModelEye = fInvScale*(kDiff*m_spkPage->WorldRotate());
// camera direction in terrain model space
const MgcVector3& rkWorldDir = m_spkCamera->GetDirection();
MgcVector3 kModelDir = rkWorldDir*m_spkPage->WorldRotate();
bool bCloseAssumption = false;
m_spkPage->Simplify(m_spkRenderer,kModelEye,kModelDir,bCloseAssumption);
}
//---------------------------------------------------------------------------
void TestTerrain::DisplayStatistics ()
{
char acMsg[256];
sprintf(acMsg,"vertices = %u triangles = %u",
m_spkPage->GetVertexQuantity(),m_spkPage->GetTriangleQuantity());
unsigned int uiPane = 1;
HWND hStatusWnd = GetStatusWindowHandle();
SendMessage(hStatusWnd,SB_SETTEXT,(WPARAM)uiPane,(LPARAM)acMsg);
SendMessage(hStatusWnd,WM_PAINT,0,0);
}
//---------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -