PDA

View Full Version : Heightfields based on targa.


LongJumper
2003.10.07, 01:24 AM
I can't seem to control how large in width my heightfields are. Mostly because I'm having trouble grasping the way they are constructed. They are way too huge, but I want the greyscale image to be larger so that I can edit it a little better. So a 5x5 pixel image wouldn't be very easy to work on.

worldSize is whatever you want to set it to, although I notice huge problems with making it smaller than the dimensions of the greyscale image.

I'm also seeing a few stray strips occassionaly. What are some reasons why those would appear?

int mapZ = worldSize;
int mapX = worldSize;
for(int z = 0;z<mapZ;z++)
{
for(int x = 0;x<mapX;x++)
{
terrain[x][z][0] = float(x)*worldSize;

terrain[x][z][1] = (float)imageData[(z*mapZ+x)*3];
terrain[x][z][2] = -float(z)*worldSize;
}
}
terrainList = glGenLists(1);
glNewList(terrainList,GL_COMPILE);
glPushMatrix();
glBindTexture(GL_TEXTURE_2D,texture);
glFrontFace(GL_CW);
glBegin(GL_TRIANGLE_STRIP);
for(int z = 0;z<mapZ-1;z++)
{
for(int x = 0;x<mapX-1;x++)
{
glTexCoord2f(0,0);
glVertex3f(terrain[x][z][0],terrain[x][z][1],terrain[x][z][2]);

glTexCoord2f(10,0);
glVertex3f(terrain[x+1][z][0],terrain[x+1][z][1],terrain[x+1][z][2]);

glTexCoord2f(10,10);
glVertex3f(terrain[x][z+1][0],terrain[x][z+1][1],terrain[x][z+1][2]);

glTexCoord2f(0,10);
glVertex3f(terrain[x+1][z+1][0],terrain[x+1][z+1][1],terrain[x+1][z+1][2]);
}
}
glEnd();
glFrontFace(GL_CCW);
glPopMatrix();
glEndList();

Bachus
2003.10.07, 01:38 PM
I'm also seeing a few stray strips occassionaly. What are some reasons why those would appear?

Any number of things. Try posting a screenshot in wireframe mode so that we can get a better idea. However, also try going with regular ole triangles instead of strips. I bet you get the same speed without any rendering errors that way.

This is how I handle my terrain sizes:


#define MAP_SIZE 1024 // Size of our .raw height map
#define STEP_SIZE 16 // distance between vertices
#define WIDTH (MAP_SIZE / STEP_SIZE) // number of vertices in a row/column
#define HEIGHT_RATIO .45f // Ratio that the Y is scaled according to X and Z

@interface Terrain : NSObject
{
Texture *texture;

int numVertices;
VertexRec *vertices;
int numIndices;
unsigned short *indices;

GLubyte heightMap[ MAP_SIZE * MAP_SIZE ]; // Holds the height map data
float scaleValue; // Scale value for the terrain
}

- (id) init
{
[super init];

scaleValue = 0.5f;

numVertices = (WIDTH + 1) * (WIDTH + 1);
vertices = (VertexRec *)malloc(sizeof(VertexRec) * numVertices);
numIndices = (WIDTH) * (WIDTH) * 6;
indices = (unsigned short *)malloc(sizeof(unsigned short) * numIndices);

[self loadRawFile:[ NSString stringWithFormat:@"%@/%s",
[[NSBundle mainBundle] resourcePath], "Terrain.raw" ]
size:MAP_SIZE * MAP_SIZE map:heightMap];
[self renderHeightMap:heightMap]; // Render The Height Map
[self normalize];

texture = [[Texture alloc] init];
[texture loadTGA:[NSString stringWithFormat:@"%@/%s",
[[NSBundle mainBundle] resourcePath], "Terrain.tga"] useMipMaps:NO];

// Before GL_APPLE_vertex_array_range: FPS = 70, after: FPS = 125
#if GL_APPLE_vertex_array_range
glVertexArrayRangeAPPLE((sizeof(VertexRec) * numVertices), (GLvoid *)vertices);
glEnableClientState( GL_VERTEX_ARRAY_RANGE_APPLE );
glFlushVertexArrayRangeAPPLE((sizeof(VertexRec) * numVertices), (GLvoid *)vertices);
#endif

return self;
}


Should be fairly obvious what's going on. I use a .raw file (instead of tga) of 1024x1024 pixels to store the greyscale height data. [self renderHeightMap] goes through the heightmap setting the vertices every sixteen pixels/points. It starts at 0 and goes to 1024, which is why numVertices is (width + 1) * (width + 1). Then it sets the indices/triangles. [self normalize] computes the normals and I'm all ready for rendering.

EDIT: Forgot to mention how to change the size. If you want to use a different size heightmap you just change MAP_SIZE to 512 or 256 or whatever. To change the density of the triangles you change STEP_SIZE. Smaller numbers are denser meshes, but also slower. Then, if you just want to change how big it displays on screen you change the scaleValue setting. I use 0.5f so my terrain renders only 512x512 instead of 1024x1024.