www.pudn.com > Map.GL.FPS.zip > Main.cpp
//***********************************************************************//
// //
// - "Talk to me like a 3 year old!" Programming Lessons - //
// //
// $Author: DigiBen DigiBen@GameTutorials.com //
// //
// $Program: Height Map //
// //
// $Description: This shows how render a height map from a file. //
// //
// $Date: 7/12/01 //
// //
//***********************************************************************//
// This is a compiler directive that includes libraries (For Visual Studio)
// You can manually include the libraries in the "Project->settings" menu under
// the "Link" tab. You need these libraries to compile this program.
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glu32.lib")
#pragma comment(lib, "winmm.lib")
#include "main.h" // This includes our main header file
#include "camera.h" // This is our camera header file
bool g_bFullScreen = true; // Set full screen as default
HWND g_hWnd; // This is the handle for the window
RECT g_rRect; // This holds the window dimensions
HDC g_hDC; // General HDC - (handle to device context)
HGLRC g_hRC; // General OpenGL_DC - Our Rendering Context for OpenGL
HINSTANCE g_hInstance; // This holds the global hInstance for UnregisterClass() in DeInit()
/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// *
// Here we make an array of bytes to hold our height map data. Since we are reading
// in a .raw file that just stores values from 0 to 255, we can use them as height values,
// with 255 being the highest point, and 0 being the lowest point.
// This holds the height map data
BYTE g_HeightMap[MAP_SIZE*MAP_SIZE];
// This tells us if we want lines or fill mode
bool g_bRenderMode = true;
// This is our global camera object
CCamera g_Camera;
/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// *
///////////////////////////////// INIT \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This function initializes the application
/////
///////////////////////////////// INIT \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void Init(HWND hWnd)
{
g_hWnd = hWnd; // Assign the window handle to a global window handle
GetClientRect(g_hWnd, &g_rRect); // Assign the windows rectangle to a global RECT
InitializeOpenGL(g_rRect.right, g_rRect.bottom); // Init OpenGL with the global rect
/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// *
// Here we read read in the height map from the .raw file and put it in our
// g_HeightMap array. We also pass in the size of the .raw file (1024).
LoadRawFile("Terrain.raw", MAP_SIZE * MAP_SIZE, g_HeightMap);
// Here we set the camera in a obscure position to get a
// good outside view of the terrain.
// Give our camera a decent starting point in the world
g_Camera.PositionCamera(1200, 300, 1150, 1199, 300, 1150, 0, 1, 0);
/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// *
}
///////////////////////////////// MAIN GAME LOOP \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This function Handles the main game loop
/////
///////////////////////////////// MAIN GAME LOOP \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
WPARAM MainLoop()
{
MSG msg;
while(1) // Do our infinate loop
{ // Check if there was a message
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if(msg.message == WM_QUIT) // If the message wasnt to quit
break;
TranslateMessage(&msg); // Find out what the message does
DispatchMessage(&msg); // Execute the message
}
else // if there wasn't a message
{
g_Camera.Update(); // Update the camera data
RenderScene(); // Render the scene every frame
}
}
DeInit(); // Clean up and free all allocated memory
return(msg.wParam); // Return from the program
}
///////////////////////////////// RENDER SCENE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This function renders the entire scene.
/////
///////////////////////////////// RENDER SCENE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void RenderScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The matrix
/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// *
// Give OpenGL our camera position
g_Camera.Look();
// If we pass the g_HeightMap data into our RenderHeightMap() function it will
// render the terrain in QUADS. If you are going to make any use of this function,
// it might be a good idea to put in an (X, Y) parameter to draw it at, or just use
// OpenGL's matrix operations (glTranslatef() glRotate(), etc...)
RenderHeightMap(g_HeightMap); // Render the height map
/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// *
SwapBuffers(g_hDC); // Swap the backbuffers to the foreground
}
///////////////////////////////// WIN PROC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This function handles the window messages.
/////
///////////////////////////////// WIN PROC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
LRESULT CALLBACK WinProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
switch (uMsg)
{
case WM_SIZE: // If the window is resized
if(!g_bFullScreen) // Do this only if we are NOT in full screen
{
SizeOpenGLScreen(LOWORD(lParam),HIWORD(lParam));// LoWord=Width, HiWord=Height
GetClientRect(hWnd, &g_rRect); // Get the window rectangle
}
break;
case WM_PAINT: // If we need to repaint the scene
BeginPaint(hWnd, &ps); // Init the paint struct
EndPaint(hWnd, &ps); // EndPaint, Clean up
break;
/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// *
case WM_LBUTTONDOWN: // If the left mouse button was clicked
// We want to be able to turn wire frame on and off, so let's switch it
g_bRenderMode = !g_bRenderMode;
// Change the rendering mode to and from lines or triangles
if(g_bRenderMode)
{
// Render the triangles in fill mode
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
else
{
// Render the triangles in wire frame mode
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}
break;
/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// *
case WM_KEYDOWN:
switch(wParam)
{
case VK_ESCAPE: // Check if we hit the ESCAPE key.
PostQuitMessage(0); // Tell windows we want to quit
break;
}
break;
case WM_CLOSE: // If the window is closed
PostQuitMessage(0); // Tell windows we want to quit
break;
}
return DefWindowProc (hWnd, uMsg, wParam, lParam); // Return the default
}
/////////////////////////////////////////////////////////////////////////////////
//
// * QUICK NOTES *
//
// Not to much extra going on in this file. We load and make the call to RenderHeightMap().
// You can turn wire frame mode on and off by clicking the left mouse button. The camera
// controls are as normal. The mouse and the obvious keyboard keys move around.
//
// Let's go over the steps that we accomplished during this tutorial: (Explained more in Terrain.h)
//
// 1) First, we need to read the height map from the .raw file. This is simple because
// there is no header to a .raw file, it is just the image bits. This file format
// isn't what you generally want to use because you have to either know what the
// size and type are, or guess, but I thought it fitting for this tutorial.
//
// 2) After we read our height map data, we then needed to display it. This was
// also a simple function because we are just making QUADS with a set size.
// I chose to do 16 by 16 quads, but you can change this to what ever you want.
// With our height map array, we treated it as a 2D array and did 2 for loops
// to draw each quad for each row and column. Instead of doing lighting, I
// just gave each vertex a green intensity, depending on it's height. This makes
// the terrain look like there is lighting applied. This also makes it easier to
// see the definition in the terrain until lighting and texture maps are applied.
//
// That's it!
//
// If you want to create your own .raw files, you can either use Photoshop and use the
// Render->Clouds option, then save it as a .raw format, or use Paint Shop Pro. There are
// probably many more programs that doing it, but those are the most popular ones. You can
// also create your own in code, then fwrite() the bytes to a .raw file. That's all it is.
// If you are interested in learning how to generate random height map values, let me know
// and I will be happy to send you some source code. The technique is called Perlin Noise.
//
// If you have any feedback or suggestions, please send them. I am always interested.
//
//
// Ben Humphrey (DigiBen)
// Game Programmer
// DigiBen@GameTutorials.com
// Co-Web Host of www.GameTutorials.com
// © 2000-2003 GameTutorials
//