Problem rendering heightmap with screenshots

Started by
16 comments, last by jake_Ghost 18 years, 9 months ago
I have been working on this for a while and I can't seem to fix it. I have to images to show you guys: 1 - the rendered heightmap, 2 - the data loaded draw as an image where black is 0 height and bright red is max height. Also, when you look at the 2D and 3D heightmap, that back wall shouldn't be there, I don't know why thats happening. It seems that the data saved in a byte array is not working so good. I don't know what is causing this so I hope you guys can find it out. Here's the terrain loading/rendering code...

BOOL cTerrain :: LoadRawFile(std::string strName, int nSize, int ID, std::string TexBase, std::string TexDetail, int MapX, int MapY)
{
	FILE *pFile = NULL;

	// Let's open the file in Read/Binary mode.
	pFile = fopen( strName.c_str(), "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(HWND_DESKTOP, "Can't find the height map!", "Map Error", MB_OK);
		Write("Can't find height map " + strName);
		return FALSE;
	}

	TERRAIN tmpTerrain;

	terrain.push_back(tmpTerrain);
	TerrainCount += 1;

	terrain[TerrainCount - 1].HeightMap = new BYTE[MAP_SIZE * MAP_SIZE];
	terrain[TerrainCount - 1].MAPSIZE = nSize;
	terrain[TerrainCount - 1].ID = ID;
	terrain[TerrainCount - 1].TexBase = TexBase;
	terrain[TerrainCount - 1].TexDetail = TexDetail;
	terrain[TerrainCount - 1].x = MapX;
	terrain[TerrainCount - 1].y = MapY;

	// 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( terrain[TerrainCount - 1].HeightMap, 1, (MAP_SIZE * MAP_SIZE), 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)
	{
		Write("Error loading terrain " + strName);
		MessageBox(NULL, "Can't get data!", "Map Error", MB_OK);
	}

	Write("Loaded terrain " + strName);

	if(!bmp.FindTexture(TexBase))
	{
		bmp.LoadGLTextures(TexBase,3);
	}

	if(!bmp.FindTexture(TexDetail))
	{
		bmp.LoadGLTextures(TexDetail,3);
	}

	terrain[TerrainCount - 1].MapList = glGenLists(1);

	glNewList(terrain[TerrainCount - 1].MapList,GL_COMPILE);

		glEnable(GL_FOG);

		int X = terrain[TerrainCount - 1].x, Y = terrain[TerrainCount - 1].y;						// Create some variables to walk the array with.
		int x, y, z;							// Create some variables for readability
		bool bSwitchSides = false;
		BYTE *pHeightMap;

		pHeightMap = terrain[TerrainCount - 1].HeightMap;

		// Activate the first texture ID and bind the tree background to it
		glActiveTextureARB(GL_TEXTURE0_ARB);
		glEnable(GL_TEXTURE_2D);

		if(bmp.FindTexture(terrain[TerrainCount - 1].TexBase))
		{
			glBindTexture(GL_TEXTURE_2D, bmp.Texture(terrain[TerrainCount - 1].TexBase));
		}

			// Activate the second texture ID and bind the fog texture to it
			glActiveTextureARB(GL_TEXTURE1_ARB);
			glEnable(GL_TEXTURE_2D);
				
			// Here we turn on the COMBINE properties and increase our RGB
			// gamma for the detail texture.  2 seems to work just right.
			glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
			glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 2);
					
			// Bind the detail texture
			if(bmp.FindTexture(terrain[TerrainCount - 1].TexDetail))
			{
				glBindTexture(GL_TEXTURE_2D, bmp.Texture(terrain[TerrainCount - 1].TexDetail));
			}
				
			// Now we want to enter the texture matrix.  This will allow us
			// to change the tiling of the detail texture.
			glMatrixMode(GL_TEXTURE);

				// Reset the current matrix and apply our chosen scale value
				glLoadIdentity();
				glScalef((float)4, (float)4, 1);

			// Leave the texture matrix and set us back in the model view matrix
			glMatrixMode(GL_MODELVIEW);

			glBegin(GL_TRIANGLE_STRIP);
				for (int x = terrain[TerrainCount - 1].x; x < MAP_SIZE + terrain[TerrainCount - 1].x; x += STEP_SIZE)
				{
					for (int y = terrain[TerrainCount - 1].y; y < MAP_SIZE + terrain[TerrainCount - 1].y; y += STEP_SIZE)
					{
						SetTextureCoord( (float)x, (float)y, TerrainCount - 1 );
						glVertex3f(x,Height(pHeightMap, x, y, TerrainCount - 1 ),y);

						SetTextureCoord( (float)x + STEP_SIZE, (float)y, TerrainCount - 1 );
						glVertex3f(x + STEP_SIZE,Height(pHeightMap, x+ STEP_SIZE, y, TerrainCount - 1 ),y);

						SetTextureCoord( (float)x, (float)y + STEP_SIZE, TerrainCount - 1 );
						glVertex3f(x,Height(pHeightMap, x, y+ STEP_SIZE, TerrainCount - 1 ),y + STEP_SIZE);

						SetTextureCoord( (float)x + STEP_SIZE, (float)y, TerrainCount - 1 );
						glVertex3f(x + STEP_SIZE,Height(pHeightMap, x+ STEP_SIZE, y, TerrainCount - 1 ),y);

						SetTextureCoord( (float)x + STEP_SIZE, (float)y + STEP_SIZE, TerrainCount - 1 );
						glVertex3f(x + STEP_SIZE,Height(pHeightMap, x+ STEP_SIZE, y+ STEP_SIZE, TerrainCount - 1 ),y + STEP_SIZE);

						SetTextureCoord( (float)x, (float)y + STEP_SIZE, TerrainCount - 1 );
						glVertex3f(x,Height(pHeightMap, x, y+ STEP_SIZE, TerrainCount - 1 ),y + STEP_SIZE);
					}
				}
			glEnd();

			// Turn the second multitexture pass off
			glActiveTextureARB(GL_TEXTURE1_ARB);
			glDisable(GL_TEXTURE_2D);

		// Turn the first multitexture pass off
		glActiveTextureARB(GL_TEXTURE0_ARB);		
		glDisable(GL_TEXTURE_2D);
		glDisable(GL_FOG);
	glEndList();
	
	pHeightMap = NULL;

	// Close the file.
	fclose(pFile);

	return TRUE;
}





Here is my map, which draws a 2d version of the heightmap...

MapList = glGenLists(1);

	glNewList(MapList, GL_COMPILE);
		BYTE *pHeightMap;

		pHeightMap = cTer.terrain.HeightMap;

		glDisable(GL_TEXTURE_2D);

		glBegin(GL_QUADS);
			for (int x = 0; x < MAP_SIZE; x += 16)
			{
				for (int y = 0; y < MAP_SIZE; y += 16)
				{
					glColor3ub(cTer.Height(pHeightMap, x, y, i ),0,0);
					glVertex2f(x,y);

					glColor3ub(cTer.Height(pHeightMap, x, y + 16, i ),0,0);
					glVertex2f(x, y + 16);

					glColor3ub(cTer.Height(pHeightMap, x + 16, y + 16, i ),0,0);
					glVertex2f(x + 16, y + 16);

					glColor3ub(cTer.Height(pHeightMap, x + 16, y, i ),0,0);
					glVertex2f(x + 16, y);
				}
			}
		glEnd();

		glEnable(GL_TEXTURE_2D);
	glEndList();





Anyone know why this might be happening? Jake [Edited by - jake_Ghost on June 28, 2005 11:35:03 AM]
Advertisement
From my experience with heightmaps, I'd say doing one small thing should fix it.

Move the line:
glBegin(GL_QUADS);

So that it comes after:
for (int x = 0; x < MAP_SIZE; x += 16)

And also move the appropriate glEnd();

It worked for me in the past :) (I use the triangle strip method at the moment).
All try that thanks, but my 3D heightmap doesn't work either, as you can see from that screenshot.

Jake
I added that line of code to my terrain as well and those strips on top of the terrain disappeared, but that back wall didn't. The wall shouldn't bee there.
Ok, you need to change these lines:

for (int x = 0; x < MAP_SIZE; x += 16)

and

for (int y = 0; y < MAP_SIZE; y += 16)

After MAP_SIZE put -1

That should remove the wall.
I added the - 1 but it didn't do anything. I put - 16 and now the wall is gone but I have all these spaces in between my terrain now. So now all the terrain is 1008 x 1008 instead of 1024 x 1024.

Jake
Can you post how the code looks now? You have some weirdass thing with all your 16's. I'll see what I can do when you've posted that code.
Here's my entire Terrain.cpp file...

#include <windows.h>#include <stdio.h>#include <stdlib.h>#include <gl\gl.h>										// Header File For The OpenGL32 Library#include <gl\glu.h>										// Header File For The GLu32 Library#include <gl\glaux.h>									// Header File For The GLaux Library#include <math.h>#include "main.h"#include "terrain.h"#include "bmp.h"// This stores the desired depth that we want to fogextern float g_FogDepth;// This is our fog extension function pointer to set a vertice's depthextern PFNGLFOGCOORDFEXTPROC glFogCoordfEXT;int cTerrain :: Height(BYTE *pHeightMap, int X, int Y,int ID){	// 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(!terrain[ID].HeightMap) 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}int cTerrain :: Height(int X, int Y,int ID){	// 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(!terrain[ID].HeightMap) return 0;				// Make sure our data is valid	//for (int i = 0; i < TerrainCount; i++)	//{	//	if (terrain.ID = i)	//	{			// Use the equation: index = (x + (y * arrayWidth) ) to find the current height			return (terrain[ID].HeightMap[x + (y * MAP_SIZE)]);	// Index into our height array and return the height	//	}	//}}int cTerrain :: GetID(int ID){	for (int i = 0; i < TerrainCount; i++)	{		if (terrain.ID == i)		{			return i;		}	}	return -1;}void cTerrain :: SetTextureCoord(float x, float z, int ID){	// Find the (u, v) coordinate for the current vertex	float u =  (float)x / (float)MAP_SIZE;	float v = -(float)z / (float)MAP_SIZE;		// Give OpenGL the current terrain texture coordinate for our height map	glMultiTexCoord2fARB(GL_TEXTURE0_ARB, u, v);	// Give OpenGL the current detail texture coordinate for our height map	glMultiTexCoord2fARB(GL_TEXTURE1_ARB, u, v);}void SetFogCoord(float depth, float height){	float fogY = 0;	// Check if the height of this vertex is greater than the depth (needs no fog)	if(height > depth)		fogY = 0;	// Otherwise, calculate the fog depth for the current vertex	else		fogY = -(height - depth);	// Assign the fog coordinate for this vertex using our extension function pointer	glFogCoordfEXT(fogY);}void cTerrain :: RenderHeightMap(int ID){	for (int i = 0; i < TerrainCount; i++)	{		if (terrain.ID == ID)		{			if(!terrain.HeightMap) return;			glCallList(terrain.MapList);		}	}}BOOL cTerrain :: LoadRawFile(std::string strName, int nSize, int ID, std::string TexBase, std::string TexDetail, int MapX, int MapY){	FILE *pFile = NULL;	// Let's open the file in Read/Binary mode.	pFile = fopen( strName.c_str(), "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(HWND_DESKTOP, "Can't find the height map!", "Map Error", MB_OK);		Write("Can't find height map " + strName);		return FALSE;	}	TERRAIN tmpTerrain;	terrain.push_back(tmpTerrain);	TerrainCount += 1;	terrain[TerrainCount - 1].HeightMap = new BYTE[MAP_SIZE * MAP_SIZE];	terrain[TerrainCount - 1].MAPSIZE = nSize;	terrain[TerrainCount - 1].ID = ID;	terrain[TerrainCount - 1].TexBase = TexBase;	terrain[TerrainCount - 1].TexDetail = TexDetail;	terrain[TerrainCount - 1].x = MapX;	terrain[TerrainCount - 1].y = MapY;	// 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( terrain[TerrainCount - 1].HeightMap, 1, (MAP_SIZE * MAP_SIZE), 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)	{		Write("Error loading terrain " + strName);		MessageBox(NULL, "Can't get data!", "Map Error", MB_OK);	}	Write("Loaded terrain " + strName);	if(!bmp.FindTexture(TexBase))	{		bmp.LoadGLTextures(TexBase,3);	}	if(!bmp.FindTexture(TexDetail))	{		bmp.LoadGLTextures(TexDetail,3);	}	terrain[TerrainCount - 1].MapList = glGenLists(1);	glNewList(terrain[TerrainCount - 1].MapList,GL_COMPILE);		glEnable(GL_FOG);		int X = terrain[TerrainCount - 1].x, Y = terrain[TerrainCount - 1].y;						// Create some variables to walk the array with.		int x, y, z;							// Create some variables for readability		bool bSwitchSides = false;		BYTE *pHeightMap;		pHeightMap = terrain[TerrainCount - 1].HeightMap;		// Activate the first texture ID and bind the tree background to it		glActiveTextureARB(GL_TEXTURE0_ARB);		glEnable(GL_TEXTURE_2D);		if(bmp.FindTexture(terrain[TerrainCount - 1].TexBase))		{			glBindTexture(GL_TEXTURE_2D, bmp.Texture(terrain[TerrainCount - 1].TexBase));		}			// Activate the second texture ID and bind the fog texture to it			glActiveTextureARB(GL_TEXTURE1_ARB);			glEnable(GL_TEXTURE_2D);							// Here we turn on the COMBINE properties and increase our RGB			// gamma for the detail texture.  2 seems to work just right.			glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);			glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 2);								// Bind the detail texture			if(bmp.FindTexture(terrain[TerrainCount - 1].TexDetail))			{				glBindTexture(GL_TEXTURE_2D, bmp.Texture(terrain[TerrainCount - 1].TexDetail));			}							// Now we want to enter the texture matrix.  This will allow us			// to change the tiling of the detail texture.			glMatrixMode(GL_TEXTURE);				// Reset the current matrix and apply our chosen scale value				glLoadIdentity();				glScalef((float)4, (float)4, 1);			// Leave the texture matrix and set us back in the model view matrix			glMatrixMode(GL_MODELVIEW);			for (int x = terrain[TerrainCount - 1].x; x < MAP_SIZE + terrain[TerrainCount - 1].x - 16; x += STEP_SIZE)			{				for (int y = terrain[TerrainCount - 1].y; y < MAP_SIZE + terrain[TerrainCount - 1].y - 16; y += STEP_SIZE)				{					glBegin(GL_TRIANGLE_STRIP);						SetTextureCoord( (float)x, (float)y, TerrainCount - 1 );						glVertex3f(x,Height(pHeightMap, x, y, TerrainCount - 1 ),y);						SetTextureCoord( (float)x + STEP_SIZE, (float)y, TerrainCount - 1 );						glVertex3f(x + STEP_SIZE,Height(pHeightMap, x+ STEP_SIZE, y, TerrainCount - 1 ),y);						SetTextureCoord( (float)x, (float)y + STEP_SIZE, TerrainCount - 1 );						glVertex3f(x,Height(pHeightMap, x, y+ STEP_SIZE, TerrainCount - 1 ),y + STEP_SIZE);						SetTextureCoord( (float)x + STEP_SIZE, (float)y, TerrainCount - 1 );						glVertex3f(x + STEP_SIZE,Height(pHeightMap, x+ STEP_SIZE, y, TerrainCount - 1 ),y);						SetTextureCoord( (float)x + STEP_SIZE, (float)y + STEP_SIZE, TerrainCount - 1 );						glVertex3f(x + STEP_SIZE,Height(pHeightMap, x+ STEP_SIZE, y+ STEP_SIZE, TerrainCount - 1 ),y + STEP_SIZE);						SetTextureCoord( (float)x, (float)y + STEP_SIZE, TerrainCount - 1 );						glVertex3f(x,Height(pHeightMap, x, y+ STEP_SIZE, TerrainCount - 1 ),y + STEP_SIZE);					glEnd();				}			}			// Turn the second multitexture pass off			glActiveTextureARB(GL_TEXTURE1_ARB);			glDisable(GL_TEXTURE_2D);		// Turn the first multitexture pass off		glActiveTextureARB(GL_TEXTURE0_ARB);				glDisable(GL_TEXTURE_2D);		glDisable(GL_FOG);	glEndList();		pHeightMap = NULL;	// Close the file.	fclose(pFile);	return TRUE;}cTerrain :: cTerrain(){}cTerrain :: ~cTerrain(){	for (int i = 0; i < TerrainCount; i++)	{		delete [] terrain.HeightMap;	}	terrain.clear();}
Here's what it looks like now...

Did you change either of these lines based on what I said?

for (int x = terrain[TerrainCount - 1].x; x < MAP_SIZE + terrain[TerrainCount - 1].x - 16; x += STEP_SIZE)

for (int y = terrain[TerrainCount - 1].y; y < MAP_SIZE + terrain[TerrainCount - 1].y - 16; y += STEP_SIZE)

What I meant by the -1 was like this:

for (int x = terrain[TerrainCount - 1].x; x < MAP_SIZE-1 + terrain[TerrainCount - 1].x - 16; x += STEP_SIZE)

for (int y = terrain[TerrainCount - 1].y; y < MAP_SIZE-1 + terrain[TerrainCount - 1].y - 16; y += STEP_SIZE)

This topic is closed to new replies.

Advertisement