Well, this is my 2nd attempt at writing this post because an error happened the 1st time, so grrr...makes me mad...oh well...Here goes...

Many of you know I am working on a Battletech game, very similar to that of Mechwarrior.

Lately, however, I have come upon a severe bottleneck in my game, and having tried everything I know of, am unable to fix it. Hence I have conducted a series of tests in order to gather data and then present it before you to see if you can give me any help with my problem I have here.

Here is the basics of the problem: I have my terrain engine. It ran run in two modes: textured and non-textured. When I run it with no textures, I get a frame rate of about 30 fps. When I run it with textures applied, my frame rate drops to about 7 fps.

Now, to explain the problem further in depth, I will give you some background about my engine:

I have a "map" which is composed of the terrain that all the units move on, obviously.

The map is composed of a unit which I call a "hex" (short for hexagon...each piece of the map is a hexagon). The plural is "hexes." So when you see me say hex in this post, I mean a spot on the map, NOT hexidecimal.

The map is a matrix of hexes. The size is specified by the programmer and the data for the map is loaded in from a file. Right now I am running a map of 30x20 hexes.

I have 3 textures loaded into memory right now. One is called GRASS, one is called HILL, and one is called WATER. When I load in the height map, textures are automatically applied to each hex.

All hexes with a height less than or equal to 0 receive a water texture. All hexes with a height between 0 and 2 (non-inclusive) receive a grass texture, and all hexes with a height of 2 or greater receive a hill texture.

The programmer can choose whether to actually use the textures or not, but nevertheless, each hex is assigned its texture, and the textures are loaded into memory.

Each texture is a 64x64 pixel 24-bit bitmap.

That is basically all the info on how I store my map in memory. Now I will show you some code...

Before you jump to any conclusions, do not tell me to use display lists to boosts my frame rate. I have already tried them.

The following code is my function to initialize OpenGL. Remember that this function is only called once, so it has no factor whatsoever in my frame rate, but it might give some useful information for all of you:

Code:
void setup_opengl( int width, int height )
{
    float ratio = (float) width / (float) height;

	//Texture Mapping Initialization	
	InitTextureNames ( );
	LoadGLTextures();		// Texture Loading Routine
	BuildFont();
	glEnable(GL_TEXTURE_2D);// Enable Texture Mapping
	

    /* Our shading model--Gouraud (smooth). */
    glShadeModel( GL_SMOOTH );

    /* Set the clear color. */
    glClearColor( 0, 0, 0, 0 );

    /* Setup our viewport. */
    glViewport( 0, 0, width, height );

    /*
     * Change to the projection matrix and set
     * our viewing volume.
     */
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity( );

    gluPerspective( 60.0, ratio, 1.0, 1024.0 );


//Create a map of 20x30 hexes of 1 radius each.
//Set the base elavation of the map to -1.0 on the y-axis.
//Load and apply the height map.
//Apply the default terrain colors for when textures are not used.
//Enable texture mapping, and create a display lists for the map.
	myMap = new HEXMAP_DTP( 20, 30, 1.0f );
	myMap->SetBase ( 0.0f, -1.0f, 0.0f );
	myMap->LoadHeightMap ( "heightmap.dat" );
	myMap->HeightMap( );
	myMap->ApplyDefaultTerrainColors();
	myMap->EnableTextureMapping ( true );
	myMap->CreateHexDisplayLists ( );

	glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
}
I hope that function is pretty clear and straight forward. If there is any confusion about my code, ask me and I will explain a part of it.

Here is the next function. This function is my draw function and gets called on every frame:

Code:
static void draw_screen( void )
{    

	GLfloat xtrans = -xpos;
	GLfloat ztrans = -zpos;		
	movy -= ypos;
	GLfloat sceneroty = 360.0f - yrot;

    /* Clear the color and depth buffers. */
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    /* We don't want to modify the projection matrix. */
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity( );

	glRotatef(sceneroty,0,1.0f,0);
	glTranslatef(xtrans, movy, ztrans);

//Draw the map...obviously.  
	myMap->DrawMap();	


//This function is for printing text onto the screen.
	CyclePrintBuffer ( );

    /*
     * Swap the buffers. This this tells the driver to
     * render the next frame from the contents of the
     * back-buffer, and to set all rendering operations
     * to occur on what was the front-buffer.
     *
     * Double buffering prevents nasty visual tearing
     * from the application drawing on areas of the
     * screen that are being updated at the same time.
     */


    SDL_GL_SwapBuffers( );

	movy += ypos;
	
}
There are some variables in that function that are global variables and declared elsewhere in my code. Just have confidence that they HAVE been decalared. ;-)

Anyways, I will show you one more function. This is the function where an individual hex is actually drawn onto the screen. Keep in mind that although I am using display lists for the drawing, I have omitted them in this post for the sake that you can see all of the code. This function is called DrawHexTextured(), and is called by the DrawMap() function as the map class draws every hex in the map. The code is identical to the code that draws the map with no-textures, except that this code contains code for textures :-) :

Code:
void HEX_DTP::DrawHexTextured ( )
{
	//Find out which texture to use
	if ( level <= 0 )
		glBindTexture ( GL_TEXTURE_2D, texture[WATER] );
	else if ( level >= 2 )
		glBindTexture ( GL_TEXTURE_2D, texture[HILL] );
	else 
		glBindTexture ( GL_TEXTURE_2D, texture[GRASS] );

	//account for elevation change at center of hex
	v[1] += level;

	//radius, x1, z1, and other variables are declared in the class declaration
	//they are also defined by other functions and by the class constructor
	//create outer vertexes of hexagon
	float vertex[6][3] = 
	{ 
		{ v[0] - radius,	v[1] - ElevationMod[0],		v[2] },
		{ v[0] - x1,		v[1] - ElevationMod[1],		v[2] - z1 },
		{ v[0] + x1,		v[1] - ElevationMod[2],		v[2] - z1 },
		{ v[0] + radius,	v[1] - ElevationMod[3],		v[2] },
		{ v[0] + x1,		v[1] - ElevationMod[4],		v[2] + z1 },
		{ v[0] - x1,		v[1] - ElevationMod[5],		v[2] + z1 }
	};


	glBegin ( GL_TRIANGLES );		
	
		glTexCoord2f(0.0f, 0.0f); 
			glVertex3f ( v[0], v[1], v[2] );	
		glTexCoord2f(1.0f, 0.0f); 
			glVertex3f ( vertex[0][0], vertex[0][1], vertex[0][2] );
		glTexCoord2f(1.0f, 1.0f); 
			glVertex3f ( vertex[1][0], vertex[1][1], vertex[1][2] );
	
		glTexCoord2f(0.0f, 0.0f);
			glVertex3f ( v[0], v[1], v[2] );	
		glTexCoord2f(1.0f, 0.0f); 
			glVertex3f ( vertex[1][0], vertex[1][1], vertex[1][2] );
		glTexCoord2f(1.0f, 1.0f);
			glVertex3f ( vertex[2][0], vertex[2][1], vertex[2][2] );
	
		glTexCoord2f(0.0f, 0.0f);
			glVertex3f ( v[0], v[1], v[2] );	
		glTexCoord2f(1.0f, 0.0f); 
			glVertex3f ( vertex[2][0], vertex[2][1], vertex[2][2] );
		glTexCoord2f(1.0f, 1.0f);
			glVertex3f ( vertex[3][0], vertex[3][1], vertex[3][2] );
	
		glTexCoord2f(0.0f, 0.0f);
			glVertex3f ( v[0], v[1], v[2] );	
		glTexCoord2f(1.0f, 0.0f); 
			glVertex3f ( vertex[3][0], vertex[3][1], vertex[3][2] );
		glTexCoord2f(1.0f, 1.0f);
			glVertex3f ( vertex[4][0], vertex[4][1], vertex[4][2] );
	
		glTexCoord2f(0.0f, 0.0f);
			glVertex3f ( v[0], v[1], v[2] );	
		glTexCoord2f(1.0f, 0.0f); 
			glVertex3f ( vertex[4][0], vertex[4][1], vertex[4][2] );
		glTexCoord2f(1.0f, 1.0f);
			glVertex3f ( vertex[5][0], vertex[5][1], vertex[5][2] );		
	
		glTexCoord2f(0.0f, 0.0f);
			glVertex3f ( v[0], v[1], v[2] );	
		glTexCoord2f(1.0f, 0.0f); 
			glVertex3f ( vertex[5][0], vertex[5][1], vertex[5][2] );
		glTexCoord2f(1.0f, 1.0f);
			glVertex3f ( vertex[0][0], vertex[0][1], vertex[0][2] );

	glEnd ( );

	v[1] -= level;
}
Okay, that should be all code relevant to the problem. If you would like to see any other code, just tell me and I will post it, however I think this should suffice.

If you see anything that could be causing my extreme bottleneck, please tell me. I have tried quite a bit to get this thing to go faster, but nothing seems to work.

I just don't understand why 3 small textures alone could be dropping my frame rate from 30 fps to 7 fps.

So any help is appreciated.

If I have left any information out of this post I apologize. Ask and ye shall receive.

I will post you a picture of the UNTEXTURED version of the terrain engine so you can get a feel for what it looks like. Notice the clear distinction between each hexagon on the map. It is supposed to be like that: