📄 simpleterrain.cpp
字号:
/* Copyright (C) Greg Snook, 2001.
* All rights reserved worldwide.
*
* This software is provided "as is" without express or implied
* warranties. You may freely copy and compile this source into
* applications you distribute provided that the copyright text
* below is included in the resulting source code, for example:
* "Portions Copyright (C) Greg Snook, 2001"
*/
#ifndef SIMPLETERRAIN_H
#define SIMPLETERRAIN_H
/****************************************************************************************\
SimpleTerrain.cpp
SimpleTerrain component interface for a basic terrain manager.
Part of the Gems II sample code library.
Created 3/27/2001 by Greg Snook
gregsnook@home.com
-------------------------------------------------------------------------------------
Notes/Revisions:
I make no aplogies for spelling errors :)
\****************************************************************************************/
#define STRICT
#include <tchar.h>
#include <stdio.h>
#include <windows.h>
#include <commdlg.h>
#include <d3dx8.h>
#include "D3DApp.h"
#include "D3DFont.h"
#include "D3DUtil.h"
#include "DXUtil.h"
#include "resource.h"
#include "TileDefinitions.h" // <- the index buffers are defined in here
/* SimpleTerrain
------------------------------------------------------------------------------------------
SimpleTerrain is a sample class that demonstrates the terrain method.
It's been written for clarity, not speed.
------------------------------------------------------------------------------------------
*/
#define TILE_VERTS 9 // our tiles are 9x9 vertices
#define TILE_COUNT 16 // our terrain in 16x16 tiles
// the overall terrain is a set of VERTEX_COUNT x VERTEX_COUNT vertices
#define VERTEX_COUNT ((TILE_COUNT*(TILE_VERTS-1))+1)
class SimpleTerrain : public CD3DApplication
{
public:
// Data Types & Constants...
// our sample contains 4 possible detail levels per tile
enum LEVEL
{
LEVEL_0 = 0,
LEVEL_1,
LEVEL_2,
LEVEL_3,
TOTAL_LEVELS
};
// data about each index buffer we create
struct INDEX_BUFFER
{
IDirect3DIndexBuffer8* pIndexBuffer;
int IndexCount;
int TriangleCount;
};
// the index buffers needed for each of our detail levels
struct DETAIL_LEVEL
{
INDEX_BUFFER TileBodies[16];
INDEX_BUFFER TileConnectors[TOTAL_SIDES][TOTAL_LEVELS];
};
// a tile of our terrain
struct TILE
{
LEVEL DetailLevel;// the current detail level to use
IDirect3DVertexBuffer8* VBuffer; // a pile of vertices for this tile
D3DXVECTOR3 Center; // the center point of the tile
};
// our vertex format for this sample
struct TERRAIN_VERTEX
{
D3DXVECTOR3 vert;
D3DXVECTOR3 norm;
float tu,tv;
};
// the FVF code for this sample
enum VERTEX_FVF
{
FVF = D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1
};
// Creators...
SimpleTerrain();
~SimpleTerrain(){};
// Operators...
// Mutators...
void GenerateDetailLevels();
void GenerateTiles();
void DrawTerrain();
HRESULT OneTimeSceneInit();
HRESULT InitDeviceObjects();
HRESULT RestoreDeviceObjects();
HRESULT InvalidateDeviceObjects();
HRESULT DeleteDeviceObjects();
HRESULT Render();
HRESULT FrameMove();
HRESULT FinalCleanup();
LRESULT MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
// Accessors...
private:
// Data...
TILE m_TerrainTile[TILE_COUNT][TILE_COUNT]; // our sample terrain of 32x32 tiles
DETAIL_LEVEL m_DetailLevel[TOTAL_LEVELS]; // data for each detail level
LPDIRECT3DTEXTURE8 m_pMeshTexture; // simple texture for our terrain
LPDIRECT3DSURFACE8 m_pHeightData; // greyscale height information
D3DMATERIAL8 m_MeshMaterial; // a basic material for the terrain
CD3DFont* m_pFont; // Font for outputting frame stats
CD3DArcBall m_ArcBall; // Mouse rotation utility
D3DXVECTOR3 m_vObjectCenter; // Center of bounding sphere of object
FLOAT m_fObjectRadius; // Radius of bounding sphere of object
D3DXMATRIX m_matWorld; // the world transform matrix
D3DXVECTOR3 m_CameraPos; // position of the camera
int m_FacesDrawn; // count of faces actually rendered each frame
bool m_bWireframe; // wireframe mode toggle
float m_CameraOffset; // camera's zoom factor
// Private Functions...
// Nonexistant Functions...
SimpleTerrain( const SimpleTerrain& Src);
SimpleTerrain& operator=( const SimpleTerrain& Src);
};
//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: Entry point to the program. Initializes everything, and goes into a
// message-processing loop. Idle time is used to render the scene.
//-----------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
SimpleTerrain d3dApp;
if( FAILED( d3dApp.Create( hInst ) ) )
return 0;
return d3dApp.Run();
}
//-----------------------------------------------------------------------------
// Name: SimpleTerrain()
// Desc: Constructor
//-----------------------------------------------------------------------------
SimpleTerrain::SimpleTerrain()
{
// Override base class members
m_strWindowTitle = _T("GEMS II: Simple Terrain");
m_bUseDepthBuffer = TRUE;
m_bShowCursorWhenFullscreen = TRUE;
// Initialize member variables
m_pFont = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD );
m_pMeshTexture = 0;
m_pHeightData = 0;
D3DUtil_InitMaterial(m_MeshMaterial, 0.5f, 0.6f, 0.5f, 1.0f);
ZeroMemory(m_TerrainTile, sizeof(TILE)*TILE_COUNT*TILE_COUNT);
ZeroMemory(m_DetailLevel, sizeof(DETAIL_LEVEL)*TOTAL_LEVELS);
m_FacesDrawn = 0;
m_bWireframe = false;
m_CameraOffset = -2.0f;
}
//-----------------------------------------------------------------------------
// Name: OneTimeSceneInit()
// Desc: Called during initial app startup, this function performs all the
// permanent initialization.
//-----------------------------------------------------------------------------
HRESULT SimpleTerrain::OneTimeSceneInit()
{
// Set cursor to indicate that user can move the object with the mouse
#ifdef _WIN64
SetClassLongPtr( m_hWnd, GCLP_HCURSOR, (LONG_PTR)LoadCursor( NULL, IDC_SIZEALL ) );
#else
SetClassLong( m_hWnd, GCL_HCURSOR, (LONG)LoadCursor( NULL, IDC_SIZEALL ) );
#endif
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: FrameMove()
// Desc: Called once per frame, the call is the entry point for animating
// the scene.
//-----------------------------------------------------------------------------
HRESULT SimpleTerrain::FrameMove()
{
// Setup world matrix
D3DXMATRIX matWorld;
D3DXMATRIX matRotationInverse;
D3DXMatrixTranslation( &matWorld, -m_vObjectCenter.x,
-m_vObjectCenter.y,
-m_vObjectCenter.z );
D3DXMatrixInverse( &matRotationInverse, NULL, m_ArcBall.GetRotationMatrix() );
D3DXMatrixMultiply( &matWorld, &matWorld, &matRotationInverse );
D3DXMatrixMultiply( &matWorld, &matWorld, m_ArcBall.GetTranslationMatrix() );
m_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
m_CameraPos = D3DXVECTOR3( 0, 0, m_CameraOffset*m_fObjectRadius );
D3DXMATRIX matView;
D3DXMatrixLookAtLH( &matView, &m_CameraPos,
&D3DXVECTOR3( 0, 0, 0 ),
&D3DXVECTOR3( 0, 1, 0 ) );
m_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
// transform the camera point into model space
D3DXMATRIX matWorldInv;
D3DXMatrixInverse( &matWorldInv, NULL, &matWorld);
D3DXVECTOR4 NewCamera;
D3DXVec3Transform(&NewCamera, &m_CameraPos, &matWorldInv);
// store this value as our camera position in model space
m_CameraPos.x = NewCamera.x;
m_CameraPos.y = NewCamera.y;
m_CameraPos.z = NewCamera.z;
// calc the minnimim distance for each detail level
float detail_step = m_fObjectRadius/4.0f;
float min_level3 = detail_step;
float min_level2 = detail_step * 2.0f;
float min_level1 = detail_step * 3.0f;
// choose detail levels for each tile
for (int i=0;i<TILE_COUNT;++i)
{
for (int j=0;j<TILE_COUNT;++j)
{
D3DXVECTOR3 VectorToCamera(m_TerrainTile[i][j].Center - m_CameraPos);
float DistanceToCamera = D3DXVec3Length(&VectorToCamera) - m_fObjectRadius;
if (DistanceToCamera < min_level3)
{
m_TerrainTile[i][j].DetailLevel = LEVEL_3;
}
else if (DistanceToCamera < min_level2)
{
m_TerrainTile[i][j].DetailLevel = LEVEL_2;
}
else if (DistanceToCamera < min_level1)
{
m_TerrainTile[i][j].DetailLevel = LEVEL_1;
}
else
{
m_TerrainTile[i][j].DetailLevel = LEVEL_0;
}
}
}
// allow the user to drive the camera closer or further away
// using the Up/Down arrow keys
if (GetAsyncKeyState(VK_DOWN) & 0x8000)
{
m_CameraOffset -= 0.01f;
}
else if (GetAsyncKeyState(VK_UP) & 0x8000)
{
m_CameraOffset += 0.01f;
if (m_CameraOffset >= 0.0f)
{
m_CameraOffset = -0.01f;
}
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: Render()
// Desc: Called once per frame, the call is the entry point for 3d
// rendering. This function sets up render states, clears the
// viewport, and renders the scene.
//-----------------------------------------------------------------------------
HRESULT SimpleTerrain::Render()
{
D3DXMATRIX matWorld;
D3DXMATRIX matTemp;
FLOAT fTrisPerSec;
TCHAR strInfo[120];
// Clear the scene
m_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
0x000000ff, 1.0f, 0x00000000 );
// Draw scene
if( SUCCEEDED( m_pd3dDevice->BeginScene() ) )
{
// setup the proper material and texture
m_pd3dDevice->SetMaterial( &m_MeshMaterial);
m_pd3dDevice->SetTexture( 0, m_pMeshTexture);
if (m_bWireframe)
{
m_pd3dDevice->SetRenderState(D3DRS_FILLMODE , D3DFILL_WIREFRAME );
}
else
{
m_pd3dDevice->SetRenderState(D3DRS_FILLMODE , D3DFILL_SOLID );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -