Hi, I'm writing a program in C++/OpenGL as part of a university assignment but I am having difficulty using the function glBindTexture to bind my loaded textures onto the models that I load in and render. I can actually wrap the texture around my 3D model no problem but I can't seem to do it unless the texture has only just been loaded into memory and then I immediately bind it to my model. This means that every time I want to use a texture I have to read through all the data in the texture file every single frame; this is EXTREMELY inefficient....
Below shows the main sections of code involved (I have attached the full listing for the involved classes too though):
for(int i=0;i<nBalls;i++){
TexID[i]= myBall[i].loadBitMap(BitMapList[i]);
myBall[i].draw(TexID[i]);
}
This above code is in my 'scene' class and within a render function called each frame. The loadBitMap function that is called in the loop returns an ID that should be able to then be used to bind a texture and hence shouldn't be used in a render loop....problem is, the ID and binding (which is done in my 'ball' class) only works if the texture was loaded into memory immediately before.
int Ball::loadBitMap(char *currenttexture){
textureid =LoadBitmap(currenttexture);
return textureid;
}
This the code in 'ball' which calls the LoadBitmap function to read the text file.
#include <stdio.h>
#include <windows.h>
#include "glut.h"
#include <GL/glu.h>
#include <GL/gl.h>
#include "texture.h"
/**********************************************************
*
* VARIABLES DECLARATION
*
*********************************************************/
int num_texture=-1; //Counter to keep track of the last loaded texture
/**********************************************************
*
* FUNCTION LoadBitmap(char *)
*
* This function loads a bitmap file and return the OpenGL reference ID to use that texture
*
*********************************************************/
int LoadBitmap(char *filename)
{
int i, j=0; //Index variables
FILE *l_file; //File pointer
unsigned char *l_texture; //The pointer to the memory zone in which we will load the texture
// windows.h gives us these types to work with the Bitmap files
BITMAPFILEHEADER fileheader;
BITMAPINFOHEADER infoheader;
RGBTRIPLE rgb;
num_texture++; // The counter of the current texture is increased
if( (l_file = fopen(filename, "rb"))==NULL) return (-1); // Open the file for reading
fread(&fileheader, sizeof(fileheader), 1, l_file); // Read the fileheader
fseek(l_file, sizeof(fileheader), SEEK_SET); // Jump the fileheader
fread(&infoheader, sizeof(infoheader), 1, l_file); // and read the infoheader
// Now we need to allocate the memory for our image (width * height * color deep)
l_texture = (byte *) malloc(infoheader.biWidth * infoheader.biHeight * 4);
// And fill it with zeros
memset(l_texture, 0, infoheader.biWidth * infoheader.biHeight * 4);
// At this point we can read every pixel of the image
for (i=0; i < infoheader.biWidth*infoheader.biHeight; i++)
{
// We load an RGB value from the file
fread(&rgb, sizeof(rgb), 1, l_file);
// And store it
l_texture[j+0] = rgb.rgbtRed; // Red component
l_texture[j+1] = rgb.rgbtGreen; // Green component
l_texture[j+2] = rgb.rgbtBlue; // Blue component
l_texture[j+3] = 255; // Alpha value
j += 4; // Go to the next position
}
fclose(l_file); // Closes the file stream
glBindTexture(GL_TEXTURE_2D, num_texture); // Bind the ID texture specified by the 2nd parameter
// The next commands sets the texture parameters
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // If the u,v coordinates overflow the range 0,1 the image is repeated
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // The magnification function ("linear" produces better results)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); //The minifying function
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); // We don't combine the color with the original surface color, use only the texture map.
// Finally we define the 2d texture
glTexImage2D(GL_TEXTURE_2D, 0, 4, infoheader.biWidth, infoheader.biHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, l_texture);
// And create 2d mipmaps for the minifying function
gluBuild2DMipmaps(GL_TEXTURE_2D, 4, infoheader.biWidth, infoheader.biHeight, GL_RGBA, GL_UNSIGNED_BYTE, l_texture);
free(l_texture); // Free the memory we used to load the texture
return (num_texture); // Returns the current texture OpenGL ID
}
Above is the code that I use to load a bitmap texture. You will notice that I don't use genTextures anywhere and that is only because when I tried using genTextures it still didn't work but made my code run even slower :s
finally in my ball class the code that binds my texture before drawing the model(s):
void Ball::draw(int TexID){
int l_index;
glPushMatrix();
glColor3f(0.0f,1.0f,0.0f);
glTranslatef(x,y,z);
if (fileloaded){
glScalef(scalex,scaley,scalez);
glRotatef(theta,1.0f,0.0f,0.0f);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,TexID);
glBegin(GL_TRIANGLES); // glBegin and glEnd delimit the vertices that define a primitive (in our case triangles)
for (l_index=0;l_index<object.polygons_qty;l_index++)
{
//----------------- FIRST VERTEX -----------------
glTexCoord2f(object.mapcoord[ object.polygon[l_index].a ].u,object.mapcoord[ object.polygon[l_index].a ].v);
glVertex3f( object.vertex[ object.polygon[l_index].a ].x,
object.vertex[ object.polygon[l_index].a ].y,
object.vertex[ object.polygon[l_index].a ].z); //Vertex definition
//----------------- SECOND VERTEX -----------------
// Coordinates of the second vertex
glTexCoord2f(object.mapcoord[ object.polygon[l_index].b ].u,object.mapcoord[ object.polygon[l_index].b ].v);
glVertex3f( object.vertex[ object.polygon[l_index].b ].x,
object.vertex[ object.polygon[l_index].b ].y,
object.vertex[ object.polygon[l_index].b ].z);
//----------------- THIRD VERTEX -----------------
// Coordinates of the Third vertex
glTexCoord2f(object.mapcoord[ object.polygon[l_index].c ].u,object.mapcoord[ object.polygon[l_index].c ].v);
glVertex3f( object.vertex[ object.polygon[l_index].c ].x,
object.vertex[ object.polygon[l_index].c ].y,
object.vertex[ object.polygon[l_index].c ].z);
}
glEnd();
glDisable(GL_TEXTURE_2D);
glDeleteTextures(1,(GLuint *)&TexID);
}
else
{
glScalef(0.05f,0.05f,0.05f);
glutSolidCube(5.0);
}
glPopMatrix();
}
Please excuse the random class names etc. I have been using this code for testing purposes and have kept it seperate it from my main project which incorporates models and lighting etc. rendered through a scene graph.
Any help would be greatly appreciated.
Thanks