Height mapping questions

Started by
9 comments, last by Ransom 20 years ago
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
Advertisement
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
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
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]
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
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 Zclass 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]
Anyone have any suggestions?

I''m really stumped
Stack overflow means that the stack is full, try allocating the memory for the variable using malloc or new.
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.
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.

This topic is closed to new replies.

Advertisement