Multiple Textures...

I posted this on the beginners board since I originally thought it was a beginners question, but I never got a reply, so it obviously went over their heads, so I’ll post here.
I am trying to load multiple textures when the level loads, but for some reason, once the bitmaps are loaded, one of the two is invisible, like the polygons with that texture aren’t even drawn! Here is the source, maybe you’ll spot something i am just over-looking…

//MAX_TEXTURES is 256 right now

//Global vars
char texlist[MAX_TEXTURES][32];
GLuint texture[MAX_TEXTURES];

//This is called when drawing the screen
unsigned long FindTexture(char *texname)
{
char texbuf[32];

sprintf(texbuf, “%s”, texname);
for(unsigned long loop = 0; loop < MAX_TEXTURES; loop++)
if(strstr(texlist[loop], texbuf) != NULL)
return (loop + 1);

return 1;
}

//This is my loading routine
BOOL LoadBMP()
{
char texbuf[256];
int texnum = 0;
BOOL status;
GLubyte fixer, image[32][32][3];
FILE *texfile;
BITMAPFILEHEADER bmfh;
BITMAPINFOHEADER bmih;

for(unsigned long loop = 0; loop < area.numObjects; loop++)
{
status = TRUE;
for(unsigned long t_loop = 0; t_loop < MAX_TEXTURES; t_loop++)
{
if(strstr(texlist[t_loop], area.object[loop].Texture) != NULL)
{
status = FALSE;
}
}
if(status)
{
sprintf(texlist[texnum], “%s”, area.object[loop].Texture);
texnum++;
}
}

glGenTextures(texnum, &texture[0]);

for(unsigned long loop = 0; loop < texnum; loop++)
{
MessageBox(glwnd, texlist[loop], “LoadBMP(unsigned long)”, MB_OK);
sprintf(texbuf, “Textures\%s”, texlist[loop]);
if((texfile = fopen(texbuf, “rb”)) == NULL)
return FALSE;

  fread(&bmfh, sizeof(BITMAPFILEHEADER), 1, texfile);
  fread(&bmih, sizeof(BITMAPINFOHEADER), 1, texfile);
  fread(&image, sizeof(image), 1, texfile);
  fclose(texfile);

  for(short int x_loop = 0; x_loop < 32; x_loop++)
  	{
  	for(short int y_loop = 0; y_loop < 32; y_loop++)
  		{
  		fixer = image[y_loop][x_loop][0];
  		image[y_loop][x_loop][0] = image[y_loop][x_loop][2];
  		image[y_loop][x_loop][2] = fixer;
  		}
  	}

  glBindTexture(GL_TEXTURE_2D, texture[loop]);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, 32, 32, GL_RGB, GL_UNSIGNED_BYTE, image);
  }

return TRUE;
}

//And here’s the drawing routine
glNormal3f(0.0f, 0.0f, 1.0f);
for(unsigned long o_loop = 0; o_loop < area.numObjects; o_loop++)
{
glBindTexture(GL_TEXTURE_2D, FindTexture(area.object[o_loop].Texture));
glBegin(GL_TRIANGLES);
for(int t_loop = 0; t_loop < area.object[o_loop].numTriangles; t_loop++)
{
glTexCoord2f(area.object[o_loop].triangle[t_loop].vertex[0].u, area.object[o_loop].triangle[t_loop].vertex[0].v);
glVertex3f(area.object[o_loop].triangle[t_loop].vertex[0].x, area.object[o_loop].triangle[t_loop].vertex[0].y, area.object[o_loop].triangle[t_loop].vertex[0].z);

  	glTexCoord2f(area.object[o_loop].triangle[t_loop].vertex[1].u, area.object[o_loop].triangle[t_loop].vertex[1].v);
  	glVertex3f(area.object[o_loop].triangle[t_loop].vertex[1].x, area.object[o_loop].triangle[t_loop].vertex[1].y, area.object[o_loop].triangle[t_loop].vertex[1].z);

  	glTexCoord2f(area.object[o_loop].triangle[t_loop].vertex[2].u, area.object[o_loop].triangle[t_loop].vertex[2].v);
  	glVertex3f(area.object[o_loop].triangle[t_loop].vertex[2].x, area.object[o_loop].triangle[t_loop].vertex[2].y, area.object[o_loop].triangle[t_loop].vertex[2].z);
  	}
  glEnd();
  }

Now my small 512w128h512l room only loads two textures, one for the walls and one for the ceiling/floor. The ceiling/floor texture works perfectly, while it acts as though my wall polygons aren’t even drawn! Any ideas?

First off, I just wanna say that I love this data structure:

area.object[o_loop].triangle[t_loop].vertex[0].x

That’s gotta be cache-friendly

Now, about that problem. Start by making sure that your walls are actually not being drawn. What I mean is check to be sure that you’re not just drawing white walls on a white background, for example. Also make sure that you glEnable(GL_TEXTURE_2D).

If the walls truly aren’t being drawn, make sure that face culling, alpha testing, and blending are all off.

I’m guessing it’s one of the latter problems.

– Zeno

Already tested all of them. See when I started the engine, I only loaded two textures, so I’d load them and easily reference them with loops since the ceiling and floor are drawn last. Culling works because when I would go outside the map (no collision-detection yet), the wall I was looking at from the outside wouldn’t be drawn at all and I could see into the level, to the opposing wall. I have GL_TEXTURE_2D on, and I’ve disabled culling to rule it out. Any other ideas?
Oh and that mega-structure isn’t static. It is dynamically allocated using new and freed up between levels using delete. It also frees everything before exiting, just to be safe :P.

“unsigned long FindTexture(char *texname)
{ char texbuf[32]; sprintf(texbuf, “%s”, texname); for(unsigned long loop = 0; loop < MAX_TEXTURES; loop++) if(strstr(texlist[loop], texbuf) != NULL) return (loop + 1); return 1; }”

shouldn’t your return be:-
return texture[loop];

???

BTW, what Zeno was hinting at about cache friendliness was that your way of drawing your triangles may be really nice and object orientated, but will run extremely slowly…no matter what machine you’re running on.
Aside from the fact that you should be using VAR, or any kind of vertex array, if you were going to do your drawing loop using immediate mode (glVertex3f, and you’re not even using glVertex3fv(&area.object[o_loop].triangle[t_loop].vertex[0].x)) you should at least keep all your vertices in a linear array, and just increment a pointer to step through that array.

Wandering OT, but that FindTexture code given above is rather horrendous in itself. Much better to use a binary search on a sorted array. That is, as long as the array only has to be sorted one time, or can be kept sorted any time a texture is added or removed from the array. Personally I’ve come to depend rather heavily on the STL map container for this kind of thing.

Originally posted by DFrey:
Much better to use a binary search on a sorted array.

Hehe, much better to just store the texture object number instead of the string inside the area: :object::Texture member.

– Zeno

[This message has been edited by Zeno (edited 01-22-2002).]

Poor sod. He’s in for a rough ride.

much better to just store the texture object number instead of the string inside the area::object::Texture member

True, unless you are trying to render a scenegraph as described by a human readable script that can change at any time. :stuck_out_tongue:

[This message has been edited by DFrey (edited 01-22-2002).]

Thanks, bt I already got it working, and on my P2/233 (the programming machine), with dynamic lighting and fog on, I get around 50-84fps all the time. I fixed the texture problem like this:
No more funding textures
The map no longer has a string for a texture name on each object, it now has a short int identifying the texture id.
The map stores each texture used in the level, but only once! It does this in a char TexList[number of tex in level][32] format.
When the level loads it reads this, no deciding what is already loaded!
Finally, the drawing loop simply uses the ID to choose what texture to bind to. IE: TexList[0] is ID 1, TexList[1] is 2, etc. Only limit is 32,766 textures per map, but MAN you’d take time just putting 32k textures into a level!
On a side note, the AMD K6-2 300 with a 32mb AGP card (the P2/233 has a 16mb pci voodoo) only gets 23-62 fps. Uh, wow AMD, way to kill my frames…

How many polys are you rendering to get 50-84fps? Surely not just for the walls, floor and ceiling!?
Use vertex arrays - you will not be getting anywhere near the performance you should expect, I’m 100% sure of that.

I am using vertex arrays. I just wrote my own myself. They are all pointers and they are allocated with new and delete [], though originally I used malloc and free. I am rendering Nali Castle from Unreal. If you haven’t seen that level I suggest buying a copy of Unreal (or Unreal Gold for the full storyline). That map is MASSIVE, including an entire castle with dynamic lighting, indoors and outdoors areas, a moat, an underground cavern/torture chamber, and other highly detailed objects that add to the realism. Oh and let me tell you, figuring out Unreal map format is a pain in the butt!!! My next step is to get text on the screen in OpenGL for menus and messages. Hey, you wanna’ know what that blob was that just devoured your sword, right?