Jump to content
  • Advertisement
Sign in to follow this  
mike_ix

Problems reading 16 bit or higher .raw file for heightmap

This topic is 4437 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

Hello all, I'm having a little bit of trouble using the .raw image file heightmap that gets exported from PnP Terrain Creator. I suppose it's mostly because I'm not 100% familiar with the .raw format. I've been making .raw files using adobe photoshop that work perfectly. However, when I export from PnP TC my terrain is rendered incorrectly. When exporting I have four options for the format of my .raw file: 1) FLOAT (4 bytes) 2) DWORD (4 bytes) 3) WORD (2 bytes) 4) BYTE (1 byte). When I export using the fourth option, I get results that are similar to what I'm used to getting from .raw files I've created in photoshop. I don't really want to use this option, however, as it stores the height values as whole integers which gives my terrain a "boxy" looking appaerance. If I use any of the other formats, my engine just scrambles the terrain. I've taken a bunch of screenshots to illustrate this problem which you can see here. the code I'm using to load my .raw file looks like this:
	std::ifstream f_DataFile;
	f_DataFile.open(mapname, std::ios::binary);
	if (f_DataFile.is_open())
	{
		for (int x=0; x<w; x++)
		{
		    for (int y=0; y<w; y++)
		    {
				g_nHeightArray[x][y] = f_DataFile.get();
                                //g_nHeightArray is initialized as a 2D array of floats
			}
		}
	}
	else {
		MessageBox(NULL, "Failed to load RAW file for terrain!", "Error!",
        MB_ICONEXCLAMATION | MB_OK);

	}


If anybody can direct me to a tutorial that will help me understand why this is happening, or perhaps just post some code to help me along my way I would be most appreciative. Thanks in advance! [Edited by - mike_ix on July 27, 2006 3:26:35 PM]

Share this post


Link to post
Share on other sites
Advertisement
You're using istream::get. It doesn't read a float, it only reads a character at a time. So you'd have to call it 4 times to read a single float, the way you're doing things. Instead, you'd better use istream::read:

for (int x=0; x<w; x++)
{
for (int y=0; y<w; y++)
{
f_DataFile.read(reinterpret_cast<char*>(&g_nHeightArray[x][y]), sizeof(float));
}
}

Share this post


Link to post
Share on other sites
hi, right I think you need to smooth out your bitmap/rawmap, the code below is just some I dragged out of my (unfinished), map/terrain thing, but hopefully it may give an idea? (theres probably some bits which don't need to be in there).

Google for box smoothing or something.

I think you will still need to smooth it even if you use floats, because theres still going to be irregular differece thingies ;D





//this should run for each heightmap pixel
void TerrainBuff::SmoothHeightMap()
{
//the bitmap data is held in this->floatchunk, so that would be your
//height map or height map array.

float checksquare[9];
float newheight = 0.0f;
int heightmultiplier = 0;
int width = this->terrsizex;
int row = this->terrsizez ;
int testcounter = 0;

//make some temp storage the same size as your rawmap
float *tempfloatchunk = new float[this->terrsizex * this->terrsizex];
memset(tempfloatchunk, 0.0f, (this->terrsizex * this->terrsizex) * sizeof(float) );

//go through entire rawmap/array data and check all the surrounding pixels or data
for(int i = 0; i <row; i++)
{
for(int j = 0; j <width; j++)
{
//offset for each surrounding pixel
if( CheckInBounds(i -1, j -1) )
{ //if the pixel isn't off an edge, include it
newheight+= floatchunk[ ((i -1)*width) + (j -1) ];
heightmultiplier++;
}
if( CheckInBounds(i -1, j) )
{
newheight+= floatchunk[ ((i -1)*width) + (j) ];
heightmultiplier++;
}
if( CheckInBounds(i -1, j +1) )
{
newheight+= floatchunk[ ((i -1)*width) + (j +1) ];
heightmultiplier++;
}

if( CheckInBounds(i, j -1) )
{
newheight+= floatchunk[ (i*width) + (j -1) ];
heightmultiplier++;
}

if( CheckInBounds(i ,j) );
{
newheight+= floatchunk[ (i*width) + (j) ];
heightmultiplier++;
}

if( CheckInBounds(i, j +1) )
{
newheight+= floatchunk[ (i*width) + (j +1) ];
heightmultiplier++;
}


if( CheckInBounds(i +1, j -1) )
{
newheight+= floatchunk[ ((i +1)*width) + (j -1) ];
heightmultiplier++;
}
if( CheckInBounds(i +1 ,j) )
{
newheight+= floatchunk[ ((i +1)*width) + (j) ];
heightmultiplier++;
}
if( CheckInBounds(i +1, j +1) );
{
newheight+= floatchunk[ ((i +1)*width) + (j +1) ];
heightmultiplier++;
}

//right just get this vertex to equal all the heights / how many
tempfloatchunk[ (i*width) + (j) ] = (newheight/heightmultiplier);

newheight = 0;
heightmultiplier = 0; //reset hieghtmultiplier count
testcounter++;
}
}

delete [] this->floatchunk;//delete the old unsmoothed data
this->floatchunk = NULL;
//reassign
this->floatchunk = tempfloatchunk;

//set to null but don't delete though as it would still be pointing
//to the new data.
tempfloatchunk = NULL;

}

//this is called in the above function
bool TerrainBuff::CheckInBounds(int locx, int locz)
{
bool InWorld;

RECT rect;
int tleft = 0;
int ttop = 0;
int tright = this->terrsizex;
int tbottom = this->terrsizez;

//set the rectangle to the same size as the terrain map.

SetRect(&this->terrainrect, tleft, ttop, tright, tbottom);

if( (locx > this->terrainrect.left && locx < this->terrainrect.right)
&&
(locz > this->terrainrect.top && locz < this->terrainrect.bottom) )
{
//the pixel/position should be on our world map.
InWorld = true;
}
else
//The position isn't on our map, return false.
InWorld = false;

return InWorld;
}










edited to make the code a bit tidier.

Share this post


Link to post
Share on other sites
Thanks, guys, for your suggestions. Indeed, my biggest problem lay with casting. I tried many different solutions (and there are many), but the one I finally stayed with is shown as below:


int w = MAP_SIZE;
FILE * pFile;
pFile = fopen (mapname, "rb");
float *m_xHeightData = new float[w*w];
if (pFile!=NULL)
{
fread( m_xHeightData, sizeof(float), ( w*w ), pFile ) ;
fclose( pFile ) ;
}
else {
MessageBox(NULL, "Failed to load RAW file for terrain!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
}
for (int x=0; x<w; x++)
{
for (int y=0; y<w; y++)
{
g_nHeightArray[x][y] = m_xHeightData[q];
q++;
}
}
SafeDeleteArray(m_xHeightData);

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!