Archived

This topic is now archived and is closed to further replies.

Height mapping questions

This topic is 5016 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I was wondering if someone could explain height mapping to me. I understand the "general" concept but the process still confuses me. Like, if I plan on plopping a texture on top of my map, how do I go about creating the appropriate height map (.raw file) to accompany the texture? I''ve converted to greyscale and saved it as a .raw file in photoshop, but this doesn''t seem to work. I get extreme peaks all over the place. [I''ve tested this by saving textures and .raw''s of the same size with the same filename and putting them in the gametutorials tutorial.] Saving a "cloud" filter in raw seems to work but this wouldn''t be repeatable if necessary. I searched the forum and there was mention of just using .bmp''s to create height maps. Has anyone done this before and how would I go about implimenting it? This seems like it would be ideal. Thanks for the help

Share this post


Link to post
Share on other sites
Yea i use a .bmp as a heightmap.
Just load one of the channels as height into one array and your set(personaly i use the red channel).
The other two channels could be used for texture look up and shadowmapping..

---------------------------------
For an overdose of l33tness, flashbang.nu

Share this post


Link to post
Share on other sites
Thanks, Could you show me some sample code as an example?

Also is the "scaleValue" way they do the zooming in lesson 34 really the way to go? I know it does the same thing, but it feels cheap. It also makes the map flip upside-down if you zoom out enough.

Thanks

Share this post


Link to post
Share on other sites
The way to go with a heightmap is, i think, to set vertices specifying the ground plane (corners) and one maximum height value. This way you can control the heightmap size really well.

Loading routine: (uses standard nehe bmp loading, i haven't included the LoadBMP function in the code)

void LoadHeightMap(char *file){
AUX_RGBImageRec *TextureImage[1]; // Create Storage Space For The Texture


memset(TextureImage,0,sizeof(void *)*1); // Set The Pointer To NULL


// Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit

if (TextureImage[0]=LoadBMP(file))
{
for(unsigned int y=0;y<HEIGHTMAP_Y;y++){
for(unsigned int x=0;x<HEIGHTMAP_X;x++){
heightmap[x][y]=TextureImage[0]->data[(y*HEIGHTMAP_X+x)*3];
g_islava[x][y]=false;
};
};
}

if (TextureImage[0]) // If Texture Exists

{
if (TextureImage[0]->data) // If Texture Image Exists

{
free(TextureImage[0]->data); // Free The Texture Image Memory

}

free(TextureImage[0]); // Free The Image Structure

}

}


[edited by - Tree Penguin on March 23, 2004 5:09:30 PM]

Share this post


Link to post
Share on other sites
that''s prettty much the way i do it(the code looks remarkibly simmilar).
Allthough i am currently trying to do it trough GLSLang shaders(it doesn''t work that well though, i can only do procedural stuff, not texture lookup as i want to have).

---------------------------------
For an overdose of l33tness, flashbang.nu

Share this post


Link to post
Share on other sites
Ok, I decided to stick with the .raw format and this is what I have.

This is the .h file


#include "GLModel.h"
#include <stdio.h>

#define MAP_SIZE 1024 // PREDEFINED MAP SIZE

#define STEP_SIZE 16 // ACCURACY OF OUR HEIGHT MAP

#define HEIGHT_RATIO 1.5f // AMOUNT Y IS SCALED IN REALTION TO X AND Z




class GLTerrain : public GLModel
{


private:

UINT HeightMapTexture[1]; // This holds the texture info by an ID


BYTE g_HeightMap[MAP_SIZE*MAP_SIZE]; // This holds the height map data


// This returns the height (0 to 255) from a heightmap given an X and Y

int Height(BYTE *pHeightMap, int X, int Y);

// This turns heightmap data into primitives and draws them to the screen

void DrawHeightMap(BYTE *pHeightMap);

// This loads a .raw file of a certain size from the file

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

void SetTextureCoord(float x, float z);

public:

// DEFAULT CONSTRUCTOR

GLTerrain();

// RENDER FUNCTION

void Render();

};



And this is the .cpp file...


#include "GLTerrain.h"
#include "GLModel.h"



int GLTerrain::Height(BYTE *pHeightMap, int X, int Y)
{
// Make sure we don't go past our array size

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


// Use the equation: index = (x + (y * arrayWidth) ) to find the current height

return pHeightMap[x + (y * MAP_SIZE)]; // Index into our height array and return the height

}





/////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////







void GLTerrain::SetTextureCoord(float x, float z)
{
// Give OpenGL the current texture coordinate for our height map

glTexCoord2f( (float)x / (float)MAP_SIZE,
- (float)z / (float)MAP_SIZE );
}






/////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////







void GLTerrain::DrawHeightMap(BYTE pHeightMap[])
{
int X = 0, Y = 0; // Create some variables to walk the array with.

int x, y, z; // Create some variables for readability

bool bSwitchSides = false;

// Make sure our height data is valid

if(!pHeightMap) return;

// Bind the terrain texture to our terrain

glBindTexture( GL_TEXTURE_2D, HeightMapTexture[0] );

// We want to render triangle strips

glBegin( GL_TRIANGLE_STRIP );

// Go through all of the rows of the height map

for ( X = 0; X <= MAP_SIZE; X += STEP_SIZE )
{
// Chechk if we need to render the opposite way for this column

if(bSwitchSides)
{
// Render a column of the terrain, for this current X.

// We start at MAP_SIZE and render down to 0.

for ( Y = MAP_SIZE; Y >= 0; 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 current texture coordinate and render the vertex

SetTextureCoord( (float)x, (float)z );
glVertex3i(x, y, z);

// 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 current texture coordinate and render the vertex

SetTextureCoord( (float)x, (float)z );
glVertex3i(x, y, z);
}
}
else
{
// Render a column of the terrain, for this current X.

// We start at 0 and render down up to MAP_SIZE.

for ( Y = 0; Y <= MAP_SIZE; Y += STEP_SIZE )
{
// 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 current texture coordinate and render the vertex

SetTextureCoord( (float)x, (float)z );
glVertex3i(x, y, z);

// Get the (X, Y, Z) value for the bottom left vertex

x = X;
y = Height(pHeightMap, X, Y );
z = Y;

// Set the current texture coordinate and render the vertex

SetTextureCoord( (float)x, (float)z );
glVertex3i(x, y, z);
}
}

// Switch the direction the column renders to allow the fluid tri strips

bSwitchSides = !bSwitchSides;
}

// Stop rendering triangle strips

glEnd();
}





/////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////







void GLTerrain::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);
}





/////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////







GLTerrain::GLTerrain()
{
LoadRawFile("Data/Terrain.raw", (MAP_SIZE * MAP_SIZE) , g_HeightMap);
CreateTexture(HeightMapTexture, "Data/Terrain.bmp", 0);

}





/////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////







void GLTerrain::Render()
{
DrawHeightMap( g_HeightMap );
}


I get no errors at all when compiling, not even linking errors, but when I declare a variable of type GLTerrain and try to execute I get this error...

"The exception unknown software exception (0xc00000fd) occurred in the application location 0x00407927"

I get this error only when I try to declare a variable of this class.

Any suggestions?

*edit* According to the debugger this is a stack overflow error... If that helps.


thanks








[edited by - Ransom on March 24, 2004 10:03:59 PM]

Share this post


Link to post
Share on other sites
Tree Penguin is correct, you are trying to allocate too much on your stack. I believe the problem is the 1024x1024 array that you are allocating. Using dynamic memory allocation (the heap) will solve the problem.

Share this post


Link to post
Share on other sites
How do i go about doing that?

Also, why am "I" having problems? I based my code on both NeHe and GameTutorials and they do not appear to use dynamic memory allocation.

Share this post


Link to post
Share on other sites
malloc and new[] both allocate memory in the heap so look them up somewhere (try google). The fact that you are having trouble is that you probably allocate too much memory and nehe or gamutut projects are under the limit but if you want to allocate 1 MB and probably a whole lot of other arrays and variables like you are doing might give a stack overflow. With you this is the case.

Share this post


Link to post
Share on other sites