Code:
///////////////////////////////// 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
}
Here is the C++ code for the stuff in my first post:
Code:
///////////////////////////////// HEIGHT \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This returns the height into the height map
/////
///////////////////////////////// HEIGHT \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
int Height(BYTE *pHeightMap, int X, int Y)
{
// This is used to index into our height map array.
// When ever we are dealing with arrays, we want to make sure
// that we don't go outside of them, so we make sure that doesn't
// happen with a %. This way x and y will cap out at (MAX_SIZE - 1)
int x = X % MAP_SIZE; // Error check our x value
int y = Y % MAP_SIZE; // Error check our y value
if(!pHeightMap) return 0; // Make sure our data is valid
// Below, we need to treat the single array like a 2D array.
// We can use the equation: index = (x + (y * arrayWidth) ).
// This is assuming we are using this assumption array[x][y]
// otherwise it's the opposite. Now that we have the correct index,
// we will return the height in that index.
return pHeightMap[x + (y * MAP_SIZE)]; // Index into our height array and return the height
}
///////////////////////////////// SET VERTEX COLOR \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This sets the color value for a particular index, depending on the height index
/////
///////////////////////////////// SET VERTEX COLOR \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void SetVertexColor(BYTE *pHeightMap, int x, int y)
{
if(!pHeightMap) return; // Make sure our height data is valid
// Here we set the color for a vertex based on the height index.
// To make it darker, I start with -0.15f. We also get a ratio
// of the color from 0 to 1.0 by dividing the height by 256.0f;
float fColor = -0.15f + (Height(pHeightMap, x, y ) / 256.0f);
// Assign this green shade to the current vertex
glColor3f(0, fColor, 0 );
}
///////////////////////////////// RENDER HEIGHT MAP \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This renders the height map as QUADS
/////
///////////////////////////////// RENDER HEIGHT MAP \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void RenderHeightMap(BYTE pHeightMap[])
{
int X = 0, Y = 0; // Create some variables to walk the array with.
int x, y, z; // Create some variables for readability
float fColor = 0.0f; // Create a variable to hold our color of the polygon
if(!pHeightMap) return; // Make sure our height data is valid
glBegin( GL_QUADS ); // Render Quads
// Next we actually need to draw the terrain from the height map.
// To do that, we just walk the array of height data and pluck out
// some heights to plot our points. If we could see this happening,
// it would draw the columns first (Y), then draw the rows.
// Notice that we have a STEP_SIZE. This determines how defined our
// height map is. The higher the STEP_SIZE, the more blocky the terrain
// looks, while the lower it gets, the more rounded it becomes.
// If we set STEP_SIZE = 1 it would create a vertex for every pixel in the height map.
// I chose 16 as a decent size. Anything too much less gets to be insane and slow.
// Of course, you can increase the number when you get lighting in.
// Then vertex lighting would cover up the blocky shape. Instead of lighting,
// we just put a color value associated with every poly to simplify the tutorial.
// The higher the polygon, the brighter the color is.
for ( X = 0; X < MAP_SIZE; X += STEP_SIZE )
for ( Y = 0; Y < MAP_SIZE; Y += STEP_SIZE )
{
// Get the (X, Y, Z) value for the bottom left vertex
x = X;
y = Height(pHeightMap, X, Y );
z = Y;
// Set the color value of the current vertice
SetVertexColor(pHeightMap, x, z);
glVertex3i(x, y, z); // Send this vertex to OpenGL to be rendered (integer points are faster)
// Get the (X, Y, Z) value for the top left vertex
x = X;
y = Height(pHeightMap, X, Y + STEP_SIZE );
z = Y + STEP_SIZE ;
// Set the color value of the current vertex
SetVertexColor(pHeightMap, x, z);
glVertex3i(x, y, z); // Send this vertex to OpenGL to be rendered
// Get the (X, Y, Z) value for the top right vertex
x = X + STEP_SIZE;
y = Height(pHeightMap, X + STEP_SIZE, Y + STEP_SIZE );
z = Y + STEP_SIZE ;
// Set the color value of the current vertex
SetVertexColor(pHeightMap, x, z);
glVertex3i(x, y, z); // Send this vertex to OpenGL to be rendered
// Get the (X, Y, Z) value for the bottom right vertex
x = X + STEP_SIZE;
y = Height(pHeightMap, X + STEP_SIZE, Y );
z = Y;
// Set the color value of the current vertice
SetVertexColor(pHeightMap, x, z);
glVertex3i(x, y, z); // Send this vertex to OpenGL to be rendered
}
glEnd();
// Reset the color
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
}
///////////////////////////////// LOAD RAW FILE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This loads a .raw file into an array of bytes. Each value is a height value.
/////
///////////////////////////////// LOAD RAW FILE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void LoadRawFile(LPSTR strName, int nSize, BYTE *pHeightMap)
{
FILE *pFile = NULL;
// Let's open the file in Read/Binary mode.
pFile = fopen( strName, "rb" );
// Check to see if we found the file and could open it
if ( pFile == NULL )
{
// Display our error message and stop the function
MessageBox(NULL, "Can't find the height map!", "Error", MB_OK);
return;
}
// Here we load the .raw file into our pHeightMap data array.
// We are only reading in '1', and the size is the (width * height)
fread( pHeightMap, 1, nSize, pFile );
// After we read the data, it's a good idea to check if everything read fine.
int result = ferror( pFile );
// Check if we received an error.
if (result)
{
MessageBox(NULL, "Can't get data!", "Error", MB_OK);
}
// Close the file.
fclose(pFile);
}
Bookmarks