-
Notifications
You must be signed in to change notification settings - Fork 1
/
terrain.cpp~
261 lines (212 loc) · 11.1 KB
/
terrain.cpp~
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
//***********************************************************************//
// //
// - "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 //
// //
//***********************************************************************//
#include "main.h"
/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// *
// This file handles all of the terrain functions.
//
// * NOTE *
//
// The terrain might look small on the screen, and considering how fast we
// move about it, but it's actually quite huge and could be a whole world
// to walk around. So don't be fooled :)
//
//
//
///////////////////////////////// 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(char *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
cerr << "Can't find the height map!" << endl;
Quit(1);
}
// 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)
{
cerr << "Can't get data!" << endl;
}
// Close the file.
fclose(pFile);
}
/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// *
/////////////////////////////////////////////////////////////////////////////////
//
// * QUICK NOTES *
//
// Though being one of the simplest ways to display terrain from a height map,
// it's a good start. The next step we would take would be to make a quad tree
// that only displayed the vertices that we could see from our view frustum.
// This would allow us to display large terrains, but not have to push so many polygons.
// This is a form of space partitioning. There isn't as many good places to learn
// about space partitioning as I would like, but the best place is www.GameInstitute.com.
// They have an excellent terrain rendering course that deals with all of these problems,
// including line of sight, terrain rendering techniques, adaptable meshes, geomorphing, etc..
//
// Let's go over the steps that we accomplished during this tutorial
//
// 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 pretty much it. As for doing texturing, this would be a good way to do
// texture tiling. You can go into a paint program and create a blank
// file the size of your height map. This will allow you to set up your textures
// to see how you want it to look. Then, make a 2D array that stores an index
// into your texture array, then just bind that texture to the current quad that matches.
// it's X and Y position. Maybe we will write a tutorial on this.
//
// The other option is to let OpenGL find the texture coordinates for you, or you can
// find them yourself by stretching a texture over the whole thing (which isn't always desirable),
// or wrap it. Remember, (0, 0) is the top left corner and (1,1) is the bottom right corner.
// You will have to find the ratio you want to wrap it with. Here is an example:
//
// glTexCoord2f( (float)x / (float)MAP_SIZE,
// - (float)z / (float)MAP_SIZE );
//
// Make sure you cast integers to floats when necessary otherwise it will truncate it.
// The z is actually the Y value of the height map, but the z value in world coordinates.
// Check out the next height map tutorial to see texturing a height map in action,
// along with rendering the terrain using triangle strips.
//
// Good luck!
//
//
// Ben Humphrey (DigiBen)
// Game Programmer
// DigiBen@GameTutorials.com
// Co-Web Host of www.GameTutorials.com
//
//