Выбрать главу

Further down in the code you will notice bRender. If bRender is set to true (which it is by default), we will drawn solid polygons. If bRender is set to false, we will draw the landscape in wire frame.

#define MAP_SIZE 1024 // Size Of Our .RAW Height Map ( NEW )

#define STEP_SIZE 16 // Width And Height Of Each Quad ( NEW )

#define HEIGHT_RATIO 1.5f // Ratio That The Y Is Scaled According To The X And Z ( NEW )

HDC hDC=NULL; // Private GDI Device Context

HGLRC hRC=NULL; // Permanent Rendering Context

HWND hWnd=NULL; // Holds Our Window Handle

HINSTANCE hInstance; // Holds The Instance Of The Application

bool keys[256]; // Array Used For The Keyboard Routine

bool active=TRUE; // Window Active Flag Set To TRUE By Default

bool fullscreen=TRUE; // Fullscreen Flag Set To TRUE By Default

bool bRender = TRUE; // Polygon Flag Set To TRUE By Default ( NEW )

Here we make an array (g_HeightMap[ ]) 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 the values as height values, with 255 being the highest point, and 0 being the lowest point. We also create a variable called scaleValue for scaling the entire scene. This gives the user the ability to zoom in and out.

BYTE g_HeightMap[MAP_SIZE*MAP_SIZE]; // Holds The Height Map Data ( NEW )

float scaleValue = 0.15f; // Scale Value For The Terrain ( NEW )

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration For WndProc

The ReSizeGLScene() code is the same as lesson 1 except the farthest distance has been changed from 100.0f to 500.0f.

GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // Resize And Initialize The GL Window {

 … CUT …

}

The following code loads in the .RAW file. Not too complex! We open the file in Read/Binary mode. We then check to make sure the file was found and that it could be opened. If there was a problem opening the file for whatever reason, an error message will be displayed.

// Loads The .RAW File And Stores It In pHeightMap

void LoadRawFile(LPSTR strName, int nSize, BYTE *pHeightMap) {

 FILE *pFile = NULL;

 // 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 Error Message And Stop The Function

  MessageBox(NULL, "Can't Find The Height Map!", "Error", MB_OK);

  return;

 }

If we've gotten this far, then it's safe to assume there were no problems opening the file. With the file open, we can now read in the data. We do this with fread(). pHeightMap is the storage location for the data (pointer to our g_Heightmap array). 1 is the number of items to load (1 byte at a time), nSize is the maximum number of items to read (the image size in bytes — width of image × height of image). Finally, pFile is a pointer to our file structure!

After reading in the data, we check to see if there were any errors. We store the results in result and then check result. If an error did occur, we pop up an error message.

The last thing we do is close the file with fclose(pFile).

 // Here We Load The .RAW File Into Our pHeightMap Data Array

 // We Are Only Reading In '1', And The Size Is (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, "Failed To Get Data!", "Error", MB_OK);

 }

 // Close The File

 fclose(pFile);

}

The init code is pretty basic. We set the background clear color to black, set up depth testing, polygon smoothing, etc. After doing all that, we load in our .RAW file. To do this, we pass the filename ("Data/Terrain.raw"), the dimensions of the .RAW file (MAP_SIZE * MAP_SIZE) and finally our HeightMap array (g_HeightMap) to LoadRawFile(). This will jump to the .RAW loading code above. The .RAW file will be loaded, and the data will be stored in our Heightmap array (g_HeightMap).

int InitGL(GLvoid) // All Setup For OpenGL Goes Here

{

 glShadeModel(GL_SMOOTH); // Enable Smooth Shading

 glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background

 glClearDepth(1.0f); // Depth Buffer Setup

 glEnable(GL_DEPTH_TEST); // Enables Depth Testing

 glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do

 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations

 // 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("Data/Terrain.raw", MAP_SIZE * MAP_SIZE, g_HeightMap); // ( NEW )

 return TRUE; // Initialization Went OK

}

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. To make sure that doesn't happen we use %. % will prevent our x / y values from exceeding MAX_SIZE – 1.

We check to make sure pHeightMap points to valid data, if not, we return 0.

Otherwise, we return the value stored at x, y in our height map. By now, you should know that we have to multiply y by the width of the image MAP_SIZE to move through the data. More on this below!

int Height(BYTE *pHeightMap, int X, int Y) // This Returns The Height From A Height Map Index

{

 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

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 visualizing it like: pHeightMap[x][y], otherwise it's the opposite: (y + (x * arrayWidth) ).

Now that we have the correct index, we will return the height at that index (data at x, y in our array).

 return pHeightMap[x + (y * MAP_SIZE)]; // Index Into Our Height Array And Return The Height

}

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.0f to 1.0f by dividing the height by 256.0f. If there is no data this function returns without setting the color. If everything goes ok, we set the color to a shade of blue using glColor3f(0.0f, fColor, 0.0f). Try moving fColor to the red or green spots to change the color of the landscape.

void SetVertexColor(BYTE *pHeightMap, int x, int y) // This Sets The Color Value For A Particular Index

{ // Depending On The Height Index

 if (!pHeightMap) return; // Make Sure Our Height Data Is Valid