​​Chap 11/100: ​Terrain with HEIGHT​​
​
What I will Learn here?:
​On this Chapter we will learn how to load a height map terrain.
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​Let's check our current main source tree, except the LIBs:
​
Added source on White:
​
​│ Applicationclass.cpp
│ Applicationclass.h
│ counter.h
│ main.cpp
│ main.h
│
├───camera
│ cameraClass.cpp
│ cameraClass.h
│ frustumClass.cpp
│ frustumClass.h
│ positionClass.cpp
│ positionClass.h
│
├───game
│ playerClass.cpp
│ playerClass.h​
│​
├───graphics
│ spriteClass.cpp
│ spriteClass.h​
│ textClass.cpp
│ textClass.h
│ textFontClass.cpp
│ textFontClass.h
│
├───input
│ inputClass.cpp
│ inputClass.h
│
├───loader
│ objModelV2Class.cpp
│ objModelV2Class.h
│
├───shader
│ shaderClass.cpp
│ shaderClass.h
│
├───system
│ dx11Class.cpp
│ dx11class.h
│ SystemClass.cpp
│ SystemClass.h
│ xml_loader.cpp
│ xml_loader.h​
│
└───terrain
terrainClass.cpp
terrainClass.h
terrainManagerClass.cpp
terrainManagerClass.h​
​
​
​​(main.h) ​
- Set for Chapter 11
​
​​​​​​​​​​​​​​(applicationClass.cpp)​ ​​
​
​
Our Current Main Render Function : bool ApplicationClass::RenderGraphics()​
​
// Render 1 Full FRAME:
// ==================================================================================================================================
bool ApplicationClass::RenderGraphics()
// ==================================================================================================================================
{ static ID3D11DeviceContext* pContext = m_DirectX11->m_deviceContext;
//----------------------------------------------------------------------------------------------------------------------
// [1] CLEAR THE SCENE:
//----------------------------------------------------------------------------------------------------------------------
static float ClearColor[] = // Set color to clear the "back buffer":
#if TUTORIAL_CHAP >= 016 //Fog
{0.5f, 0.5f, 0.5f, 1.0f};
#else
{0.0f, 0.0f, 0.5f, 1.0f}; //Blue
#endif//
// Clear the "back buffer":
pContext->ClearRenderTargetView(m_DirectX11->m_renderTargetView, ClearColor);
// Clear the "depth buffer":
pContext->ClearDepthStencilView(m_DirectX11->m_depthStencilView, D3D10_CLEAR_DEPTH, 1.0f, 0);
//----------------------------------------------------------------------------------------------------------------------
// [2] CONSTRUCT FRUSTRUM: Construct the frustum based on the view and projection matrix.
//----------------------------------------------------------------------------------------------------------------------
#if TUTORIAL_CHAP >= 6
m_Frustum.ConstructFrustum(g_SCREEN_DEPTH, g_projectionMatrix, g_viewMatrix);
#endif//
//#############################################################################################################
// 3D
//#############################################################################################################
// 1. 3D RENDERING: SKY
//----------------------------------------------------------------------------------------------------------------------
#if TUTORIAL_CHAP >= 7
RenderSky();
#endif
// 2. 3D Fixed Infinite Terrain / Water:
//----------------------------------------------------------------------------------------------------------------------
#if TUTORIAL_CHAP >= 4
InfiniteFixedTerraniWater();
#endif
// 3. 3D RENDERING: Terrain
//----------------------------------------------------------------------------------------------------------------------
#if TUTORIAL_CHAP >= 9 && defined (SCENE_TERRAIN)
pContext->ClearDepthStencilView(m_DirectX11->m_depthStencilView, D3D10_CLEAR_DEPTH, 1.0f, 0);
m_TerrainManager.Render(FILL_SOLID);
#endif
//#############################################################################################################
// 2D
//#############################################################################################################
#if TUTORIAL_CHAP >= 7
m_DirectX11->TurnZBufferOff(); //Need
m_DirectX11->TurnOnAlphaBlending(); //need
#endif
// 2D SPRITES: MAIN MAP
//----------------------------------------------------------------------------------------------------------------------
//
{ //else
// 13. SPRITE: BANNER title
//----------------------------------------------------------------------------------------------------------------------
pContext->RSSetState(m_DirectX11->m_rasterStateCullBack[FILL_SOLID]); // RESET
#if TUTORIAL_CHAP >= 7 && defined (SCENE_BANNER)// BANNER 2D TITLE:
IF_NOT_RETURN_FALSE ( m_BannerSprite.RenderRotY (pContext, (g_ScreenWidth - m_BannerSprite.m_bitmapWidth)/2, 0, m_scale) );
#endif//
// XP BAR:
//----------------------------------------------------------------------------------------------------------------------
​
// BAG:
//----------------------------------------------------------------------------------------------------------------------
}
// 14. 2D SPRITES: 2D TEXT elements
//----------------------------------------------------------------------------------------------------------------------
#if TUTORIAL_CHAP >= 8
IF_NOT_RETURN_FALSE ( m_Text.Render() );
#endif//
//----------------------------------------------------------------------------------------------------------------------
// [6] PRINT THE 3D SCENE TO SCREEN, Swap Chain or wait from VSYNC refresh rate, if it is the case
//----------------------------------------------------------------------------------------------------------------------
m_DirectX11->m_swapChain->Present(g_VSYNC_ENABLED, 0);
return true;
}​
​
​RenderGraphics invoke RenderSky():
void ApplicationClass::RenderSky ()
{
static ID3D11DeviceContext* pContext = m_DirectX11->m_deviceContext;
// 1. 3D RENDERING: SKY
//----------------------------------------------------------------------------------------------------------------------
#if TUTORIAL_CHAP >= 7
g_deviceContext->RSSetState(m_DirectX11->m_rasterStateCullBack[FILL_MODE]);
// Generate the view matrix based on the camera's position.
m_CameraSKY.m_rotationY = m_Camera.m_rotationY;
m_CameraSKY.m_rotationX = m_Camera.m_rotationX;
m_CameraSKY.Render();
m_CameraSKY.GetViewMatrix(g_viewMatrixSKY); // Get the world, view, projection, and ortho matrices from the camera and SKY object.
#if defined (SCENE_CLEANSKY)
skyModel[currentSky].render(pContext);
#endif
#endif//
// 1. 3D RENDERING: MOON or SUN as a Single Billboard
//----------------------------------------------------------------------------------------------------------------------
#if TUTORIAL_CHAP >= 10 && defined (SCENE_SUN_MOON)
D3DXMATRIX translateMatrix = g_identMatrix;
translateMatrix._11 = translateMatrix._22 = translateMatrix._33 = 5 * g_skySize;
if (currentSky == 1)
{
translateMatrix._41 = 0;
translateMatrix._42 = 32*g_skySize; // Height of Moon on horizon
translateMatrix._43 = g_SCREEN_DEPTH * g_skySize -15; // Set Moon at "North"
D3DXMatrixRotationY(&m_MoonBill.m_world, atan2(translateMatrix._41, translateMatrix._43));
D3DXMatrixMultiply(&m_MoonBill.m_world, &m_MoonBill.m_world, &translateMatrix); // Finally combine the rotation and translation matrices
m_MoonBill.render(pContext);
} else {
translateMatrix._41 = g_SCREEN_DEPTH/6; // Set Sun at "Este"
translateMatrix._42 = 12; // Height of Sun on horizon
translateMatrix._43 = 0;
m_DirectX11->TurnOnAlphaBlending(); //need to mask Sun
D3DXMatrixRotationY(&m_SunBill.m_world, atan2(translateMatrix._41, translateMatrix._43));
D3DXMatrixMultiply(&m_SunBill.m_world, &m_SunBill.m_world, &translateMatrix); // Finally combine the rotation and translation matrices
m_SunBill.render(pContext, 0, false);
m_DirectX11->TurnOffAlphaBlending(); //not needed any more
}
#endif//
}
RenderGraphics invoke InfiniteFixedTerraniWater()​
void ApplicationClass::InfiniteFixedTerraniWater ()
{
static ID3D11DeviceContext* pContext = m_DirectX11->m_deviceContext;
#if TUTORIAL_CHAP >= 7
m_DirectX11->TurnZBufferOn(); //Z Buffer Needed to be used: To make sure that moon is allways after Terrain
#endif
// 2. 3D Fixed Infinite Water:
//----------------------------------------------------------------------------------------------------------------------
#if (TUTORIAL_CHAP == 4) && defined (SCENE_OBJMODEL)
pContext->RSSetState(m_DirectX11->m_rasterStateCullNone[FILL_SOLID]); // RESET
objModel.render(pContext);
#endif//
#if (TUTORIAL_CHAP == 5) && defined (SCENE_OBJMODEL)
pContext->RSSetState(m_DirectX11->m_rasterStateCullNone[FILL_SOLID]); // RESET
for (float z=g_INIT_CAMZ+2; z < g_INIT_CAMZ+5; z++) {
for (float x=g_INIT_CAMX-2; x <= g_INIT_CAMX+2; x++) {
objModel.m_world._41 = 4*x;
objModel.m_world._42 = 0;
objModel.m_world._43 = 4*z;
objModel.render(pContext);
}
}
#endif//
#if TUTORIAL_CHAP >= 6 && TUTORIAL_CHAP <= 8 && defined (SCENE_OBJMODEL)
pContext->RSSetState(m_DirectX11->m_rasterStateCullNone[FILL_SOLID]); // RESET
#define GROUND_PATCH_SIZE 4
#define N_PATCHEs 6
for (int z=(int)m_Camera.m_positionZ/GROUND_PATCH_SIZE -N_PATCHEs; z < m_Camera.m_positionZ/GROUND_PATCH_SIZE +N_PATCHEs; z++)
{
for (int x=(int)m_Camera.m_positionX/GROUND_PATCH_SIZE -N_PATCHEs; x <= m_Camera.m_positionX/GROUND_PATCH_SIZE +N_PATCHEs; x++)
{
objModel.m_world._41 = (float)GROUND_PATCH_SIZE*x;
objModel.m_world._42 = 0;
objModel.m_world._43 = (float)GROUND_PATCH_SIZE*z;
if (m_Frustum.CheckSphere(objModel.m_world._41, 0, objModel.m_world._43, GROUND_PATCH_SIZE) ) //Because its faster than squar
{
objModel.render(pContext);
}
}
}
#endif//
#if TUTORIAL_CHAP >= 9 && defined (SCENE_OBJMODEL) //Note: CH7 become world sand
g_deviceContext->RSSetState(m_DirectX11->m_rasterStateCullFront[FILL_MODE]);
#define GROUND_PATCH_SIZE 12
#define N_PATCHEs 10
for (int z=(int)m_Camera.m_positionZ/GROUND_PATCH_SIZE -N_PATCHEs; z < m_Camera.m_positionZ/GROUND_PATCH_SIZE +N_PATCHEs; z++)
{
for (int x=(int)m_Camera.m_positionX/GROUND_PATCH_SIZE -N_PATCHEs; x <= m_Camera.m_positionX/GROUND_PATCH_SIZE +N_PATCHEs; x++)
{
objModel.m_world._41 = (float)GROUND_PATCH_SIZE*x;
objModel.m_world._42 = -0.5f; // Height of our water!
objModel.m_world._43 = (float)GROUND_PATCH_SIZE*z;
#if TUTORIAL_CHAP >= 6
if (m_Frustum.CheckSphere(objModel.m_world._41, 0, objModel.m_world._43, GROUND_PATCH_SIZE) ) //Because its faster than squar
#endif
{
objModel.render(pContext);
}
}
}
#endif//
}
​
​(terrainClass.cpp)​ ​​- The relevant changes here is LoadHeightMap(char* filename, float xPos, float zPos)
​The Function responsible for load BMP and transform it into a verttex array.
​
​​
​Project Code:
​
http://woma.no-ip.org/woma/WoMA_PartII_Chap11.zip
​What's next?
On next tutorial we will see how to add a light source to our terrain