Need help on BackGround!!!!!

Started by
4 comments, last by Like OpenGL 21 years, 9 months ago
i''m new to opengl..just started few weeks ago. my final year project is abt doing a 3D skyboard game! i''m in charge of the background..like the terrain.. and i need lots of help on this area.. any recommendations for me..like tutorials..
Advertisement
search gamedev.articles! There are some neat ones!
The simplest terrain would be a heightmap. There are plenty of tutorials out there. Two consistently informative sources are NeHe and GameTutorials.com (an excellent site). GameTutorials also deals with cameras, checking for collisions, and so on.

There''s the problem of generating the terrain. You can either read in a picture representing each height (a 256 colour image is fine for this) and assign each array element directly from the picture or you can use a clever algorithm to slowly generate your terrain over several iterations. As well as the two above, have a look at Delphi3D (for example, a relatively recent demo program that textures terrain). Also, there''s Lighthouse3d covers several algorithms and provides relevant links. One good algorithm is called "midpoint displacement".

Once you get into more complicated techniques you''ll have to consider level-of-detail. Gametutorials covers octrees, and you can also investigate BSP trees (for indoors), the Rottger algo, ROAM (which is getting a bit long in the tooth now), etc. This covers some of the alternatives with example code. Finally, remember to have a look through Gamedev''s resource section for more articles than you need.

One more link: VTerrain.org.
Thanks to Alimonster and Pipo DeClown for yr replies!!

but i have a problem now...i dun understand the following codes..

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)
// % remainder...!!
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.
//ESP THIS PART ALTHOUGH THEY PROVIDE EXPLAINATIONS
return pHeightMap[x + (y * MAP_SIZE)]; // Index into our height array and return the height
}


i can this code from http://www.gametutorials.com/Tutorials/OpenGL/OpenGL_Pg4.htm

Height map!!
can anyone pls help me?? thanks!!!!!!!!!

[edited by - Like OpenGL on July 20, 2002 6:04:38 AM]
quote:int Height(BYTE *pHeightMap, int X, int Y)
{

The very first part is passing an array to the function. Arrays are simply pointers to their first element. This means that you can have arrays for function parameters (as pHeightMap is here) as pointers instead of using the [] notation.

quote:// 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)
// % remainder...!!
int x = X % MAP_SIZE; // Error check our x value
int y = Y % MAP_SIZE; // Error check our y value


% is the modulus operator in C++. This means that it returns the remainder of a division. For example with mod 3:

0 % 3 = 0 remainder 0
1 % 3 = 0 remainder 1
2 % 3 = 0 remainder 2
3 % 3 = 1 remainder 0
4 % 3 = 1 remainder 1
5 % 3 = 1 remainder 2
6 % 3 = 2 remainder 0

...and so on. The % operator gives you the remainder of a division. This is useful for keeping a value in a wanted range. If you look at the remainders then you''ll see that they will always be between 0 and the number - 1, inclusive.

In this case, the array should not be accessed with too large a value. Using mod here lets the value wrap around. Think about the above example using % 256, for example (assuming that''s the map size - I''ve not got the code to hand - but you can hopefully get the gist regardless). Say we passed in too large a value...

254 % 256 = 0 remainder 254
255 % 256 = 0 remainder 255
256 % 256 = 1 remainder 0
257 % 256 = 1 remainder 1
258 % 256 = 1 remainder 2

Notice the behaviour here. It''s impossible for mod to return a value outside the range [0, mod_number-1]. Therefore, by using mod for accessing the array it''s guaranteed to be within the wanted bounds.

quote:if(!pHeightMap) return 0; // Make sure our data is valid

This one''s relatively obvious: make sure the pointer is not null (i.e. that there is actually an array to access!). This is simply a safety check - it''s usual practice to check pointers before dereferencing them so you don''t get an access violation. Assert() is also a pretty good idea for catching those sorts of errors.

quote:// 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.
//ESP THIS PART ALTHOUGH THEY PROVIDE EXPLAINATIONS
return pHeightMap[x + (y * MAP_SIZE)]; // Index into our height array and return the height
}

This one requires a little more explanation. Your instinct would probably be to declare a 2d array:

BYTE map[y][x]

...for example. In this case, he''s flattened that array down to a one-d array:

BYTE map[y * x];

Why would you want to do that? Well, there are two main reasons:
1) it makes allocating the array easier using new
2) accessing two-d arrays can be slower than one-d arrays if the boundaries are not powers-of-two (probably not the reason here, but useful to keep in mind)

You can get any element from the array by changing from this:

map[some_y][some_x]

to this:

map[(somey * x) + some_x]

(x being the width of the array.)

This works because memory for arrays is contiguous. Let''s look at the layout of the memory. This diagram represents how you might initially think of a 2D array (before you wise up ):

00-- **********
10-- **********
20-- **********
30-- **********
...

(Where * denotes an element in the array.)

The above represents how you might imagine a 2-d array. However, what it actually looks like is

******************************...

It''s not separated into rows at all in the computer . Therefore, (y * map_size) can be thought of as "move down y rows" from the first diagram. Notice the numbers I''ve added. These represent the element number in the associated one-d array. Therefore, the two-d version would look like "map[1 /*y*/][3]" for element 13, but the one-d array would be "map[y * array_width + x]" (with array_width = 10 here, of course). You can see that (y * array_width + x) = (1 * 10 + 3) = 13 = the correct element.
Thank u very much for yr help!!!!!!!!!!!!!

This topic is closed to new replies.

Advertisement