Revised Code. I have revised this code so many times that, I don't know what else to do. I posted this code a few days ago and a number of people gave me pointers which I included in my code. But it's still not working. Based on examples I saw on the Web, I tried the following:
1. I copied and put the whole texture mapping operations in the void init( ) function and that did not work.
2. I took out the code that SOIL uses to upload the image and that did not work (I did that because one person said it was unnecessary)
3. I changed the height and width of my image to 256
4. I made sure the image was in the same folder as my project file
5. I included glBindTexture(GL_TEXTURE_2D, texture); in each function that I wrote:
eg: void draw Triagle (), void drawCircle ()
6. Initially, static GLuint texture; was inside the GLint LoadGLTexture(const char *filename, int width, int height) function. I took it out.
I have run out of ideas. Maybe you might be able to see something I am missing. Please help. This project was due a while back. Thanks.

static GLuint texture;    

GLint LoadGLTexture(const char *filename, int width, int height)
{ 

     

     unsigned char *data;
     FILE *file;
 
     // open texture data
     file = fopen(filename, "r");
     
     if (file == NULL) return 0;
  
     
     // allocate buffer
     data = (unsigned char*) malloc(width * height * 4);
 
     //read texture data
     fread(data, width * height * 4, 1, file);
     fclose(file); 
     
     texture = SOIL_load_OGL_texture // load an image file directly as a new OpenGL  texture 
	(
		"face.png",
		SOIL_LOAD_AUTO,
		SOIL_CREATE_NEW_ID,
		SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT
	);
    
    
    // check for an error during the load process 
    if(texture == 0)
    {
	    cout << "SOIL loading error: \n" << endl;
    } 
    
     glGenTextures(1, &texture);            //get a name for the texture
    glBindTexture(GL_TEXTURE_2D, texture); // Bind the texture object to its name
    
    //Specify the parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);  // texture should tile
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);  
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
    
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_DECAL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_DECAL);
     
    // Specify the application mode
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);  

    // build our texture mipmaps
   // gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width, height,
      //                 GL_RGB, GL_UNSIGNED_BYTE, data );                               
    glTexImage2D(GL_TEXTURE_2D,
                0,                 // One resolution (i.e. level 0)
                3,                 // 3 components (i.e., RGB)
                256,               // Width
                256,               // Height
                0,                 // Border width
                GL_RGB,            // Format
                GL_UNSIGNED_BYTE,  // Data type of the texels
                data);
   // Enable textures
   glEnable(GL_TEXTURE_2D); 


   // free buffer
   free(data);  
 
   return texture;
}






void init(void)
{

    glClearColor (0.0, 0.0, 1.0, 0.0);

    glMatrixMode (GL_PROJECTION);
    gluOrtho2D (0.0, winWidth, 0.0, winHeight);
    glShadeModel (GL_SMOOTH);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
	
    glClearDepth(1.0f);                             // Depth Buffer Setup

  //glEnable(GL_DEPTH_TEST);                        // Enables Depth Testing
  //glDepthFunc(GL_LEQUAL);                         // The Type Of Depth Testing To Do

    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);  

}



void display(void)
{
    
    
    //clear the screen
   glClear(GL_COLOR_BUFFER_BIT);
   glEnable(GL_TEXTURE_2D);
   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
   glBindTexture(GL_TEXTURE_2D, texture);
  
  
   LoadGLTexture("face.png", 256, 256);


  //  LoadGLTexture("face.png", 594, 738);
    
   	glPushMatrix();
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glRotatef(Angle, 0.0, 0.0, 0.0);

     
	//Nose
   drawTriangle();

   //Face
   circle (250, 250, 400);
   
   
   //Inner Eyes
   glLoadIdentity();
   circle(200, 280, 10);
   drawCircle1(-30, 280, 10);
   
   //Eye lids
   glLoadIdentity();
   glScalef(0.6,0.2,0);
   circle(530, 2400, 60);
   circle(-150, 2150, 60);
   
   //Arc for eyebrows
   drawArc(500, 500, -70, -140, 100);
   drawArc(270, 500, -70, -140, 100);
   
   //Mouth
   drawArc(380, 250, 110, -180, 180);
  // drawArc(380, 100, -100, -180, 180);
   drawLine();
   
   
   
   // Force the rendering (off-screen)
   glFlush();

   // Handle the double buffering
   glutSwapBuffers();
}

Recommended Answers

All 9 Replies

First of all, the loading of the texture and the registering of it to OpenGL only has to occur once. So, you should move the call to LoadGLTextures() to the init function. All that you need to do before you render the polygons on which the texture is applied is to call the glBindTexture() function with the correct parameters.

Second, I would guess that calling glBindTexture() at line 111 with the variable "texture" which is not initialized could possibly cause problems as well, if anything, you need to move that line at least beyond the LoadGLTextures() call if you decide to leave it there (which you shouldn't).

Line 109 and 110 can also be moved to the init function.

Line 119 is misplaced and useless. The purpose of push-pop matrix calls is to preserve the previous matrix (modelview or projection, or other) in order to be able to retrieve it later. Usually it is used for drawing an object (or mesh) by first pushing the current modelview matrix, then applying some local transformation (translation, rotation, scaling) to render the model, and finally popping the modelview matrix to come back to the previous one (the "global" frame transformation). So, having a single push call, before you actually set the matrix is pretty much useless, push and pop always should come in pair and they are useless before you actually gave a value to the matrix (e.g. with glLoadIdentity() for instance).

Then, I think you should enable Depth-test (uncomment the lines you have already for that), but then, you need to clear the depth buffer bits along with the color bits. Thus, you need this line at line 108:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

Finally, needless to say, but on the remote chance that you didn't do it (since that code is missing), you need to make sure that your polygons that you are drawing (circles and stuff) all have correctly given texture coordinates (glTexCoord2f()) associated to each vertex.

Can you please describe the symptoms of "how" it doesn't work? Don't just say "well it still doesn't work", that doesn't tell me if anything renders, if the textures don't show up or if they show up weird, or if the polygons themselves don't show up, or if the program crashes, etc. It is very important, in order to be able to help, to know in what manner it's not working.

First of all, the loading of the texture and the registering of it to OpenGL only has to occur once. So, you should move the call to LoadGLTextures() to the init function. All that you need to do before you render the polygons on which the texture is applied is to call the glBindTexture() function with the correct parameters.

Second, I would guess that calling glBindTexture() at line 111 with the variable "texture" which is not initialized could possibly cause problems as well, if anything, you need to move that line at least beyond the LoadGLTextures() call if you decide to leave it there (which you shouldn't).

Line 109 and 110 can also be moved to the init function.

Line 119 is misplaced and useless. The purpose of push-pop matrix calls is to preserve the previous matrix (modelview or projection, or other) in order to be able to retrieve it later. Usually it is used for drawing an object (or mesh) by first pushing the current modelview matrix, then applying some local transformation (translation, rotation, scaling) to render the model, and finally popping the modelview matrix to come back to the previous one (the "global" frame transformation). So, having a single push call, before you actually set the matrix is pretty much useless, push and pop always should come in pair and they are useless before you actually gave a value to the matrix (e.g. with glLoadIdentity() for instance).

Then, I think you should enable Depth-test (uncomment the lines you have already for that), but then, you need to clear the depth buffer bits along with the color bits. Thus, you need this line at line 108:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

Finally, needless to say, but on the remote chance that you didn't do it (since that code is missing), you need to make sure that your polygons that you are drawing (circles and stuff) all have correctly given texture coordinates (glTexCoord2f()) associated to each vertex.

Can you please describe the symptoms of "how" it doesn't work? Don't just say "well it still doesn't work", that doesn't tell me if anything renders, if the textures don't show up or if they show up weird, or if the polygons themselves don't show up, or if the program crashes, etc. It is very important, in order to be able to help, to know in what manner it's not working.

Thank you mike_2000_17. I will try your suggestions right away. This is what I found out after playing with the program for a while. I realized that my image was not 256 X 256. I thought it was because that was what I cropped it to be but it did not work. When I realized that, I decided to try an image with 180 X 180 dimensions. The system crashed. At least that told me I was getting close. It gave the following error:

>

017632a9()	
 	nvoglv32.dll!69ad4904() 	
 	[Frames below may be incorrect and/or missing, no symbols loaded for nvoglv32.dll]	
 	nvoglv32.dll!69ad80df() 	
 	nvoglv32.dll!69addd16() 	
 	nvoglv32.dll!695271df() 	
 	nvoglv32.dll!69b55d95() 	
 	ntdll.dll!774556f4() 	
 	ntdll.dll!77455c34() 	
 	KernelBase.dll!756fdee2() 	
 	nvoglv32.dll!69c1a38d() 	
 	nvoglv32.dll!69af91d5() 	
 	nvoglv32.dll!69c966bb() 	
 	nvoglv32.dll!69c91b6a() 	
 	nvoglv32.dll!6963440b() 	
 	Neutral.exe!00401f81() 	
 	Neutral.exe!004011e7() 	
 	Neutral.exe!00401258() 	
 	kernel32.dll!75dced6c() 	
 	ntdll.dll!774737f5() 	
 	ntdll.dll!774737c8()

I tried to reinstall nvoglv32.dll but my computer could not recognize it.
At this point, the problem could be the dimensions of the images or something else. I will try your suggestions. That might make a big difference.

Keep the image a the 256x256 dimension, and make sure that is the dimension you get when your program loads it. Otherwise, it means your loading method is corrupt.

BTW, if you think that this line:

fread(data, width * height * 4, 1, file);

correctly reads the pixels of the image in the file, you are greatly mistaken. An image file is not just a dump of pixel values, it contains a header (information at the beginning of the file) with information about the format of the pixels, the size of the image, compression method, palettes, etc.. Just reading in the raw bytes into an array of unsigned char is very wrong. This is not to mention that you load the image with a pixel-width of 4 bytes and then you send it to OpenGL with a pixel-width of 3 bytes (RGB, not RGBA). Get your image-loading code straight. For example, you should maybe use an image-loading library like FreeImage or SOIL, don't rely or try to load the image with your own hand-crafted code, and make sure that the image loading works before you move on to trying to apply it to an OpenGL object (I didn't mention this earlier because I assumed that you had done due diligence on making sure the image got loaded correctly, but now I see that you didn't).

Keep the image a the 256x256 dimension, and make sure that is the dimension you get when your program loads it. Otherwise, it means your loading method is corrupt.

BTW, if you think that this line:

fread(data, width * height * 4, 1, file);

correctly reads the pixels of the image in the file, you are greatly mistaken. An image file is not just a dump of pixel values, it contains a header (information at the beginning of the file) with information about the format of the pixels, the size of the image, compression method, palettes, etc.. Just reading in the raw bytes into an array of unsigned char is very wrong. This is not to mention that you load the image with a pixel-width of 4 bytes and then you send it to OpenGL with a pixel-width of 3 bytes (RGB, not RGBA). Get your image-loading code straight. For example, you should maybe use an image-loading library like FreeImage or SOIL, don't rely or try to load the image with your own hand-crafted code, and make sure that the image loading works before you move on to trying to apply it to an OpenGL object (I didn't mention this earlier because I assumed that you had done due diligence on making sure the image got loaded correctly, but now I see that you didn't).

I've been working on my code and I came up with this, but I still can't get the image to upload.

static GLuint texture[1];    

//GLint LoadGLTexture(const char *filename, int width, int height)
GLuint LoadGLTexture()
{ 
    /* unsigned char *data;
     FILE *file;
 
     // open texture data
     file = fopen(filename, "r");
     
     if (file == NULL) return 0;

     
     // allocate buffer
     data = (unsigned char*) malloc(width * height * 4);
 
     //read texture data
     fread(data, width * height * 3, 1, file);
     fclose(file); */
     
     texture[0] = SOIL_load_OGL_texture // load an image file directly as a new OpenGL texture 
	(
		"face3.png",
		SOIL_LOAD_AUTO,
		SOIL_CREATE_NEW_ID,
		SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT
	);
    
    
    // check for an error during the load process 
    if(texture[0] == 0)
    return false;
    /*{
	    cout << "SOIL loading error: \n" << endl;
    } */
    
    // enable textures
    glEnable(GL_TEXTURE_2D);


    //glGenTextures(1, &texture);            //get a name for the texture
    glBindTexture(GL_TEXTURE_2D, texture[0]); // Bind the texture object to its name
    
    //Specify the parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);  // texture should tile
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);  
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
    
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_DECAL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_DECAL);
     
    // Specify the application mode
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);  

    // build our texture mipmaps
   // gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width, height,
      //                 GL_RGB, GL_UNSIGNED_BYTE, data );                               
   /* glTexImage2D(GL_TEXTURE_2D,
                0,                 // One resolution (i.e. level 0)
                3,                 // 3 components (i.e., RGB)
                256,               // Width
                256,               // Height
                0,                 // Border width
                GL_RGB,            // Format
                GL_UNSIGNED_BYTE,  // Data type of the texels
                data);
   // Enable textures */
   glEnable(GL_TEXTURE_2D);         

   // free buffer
   //free(data);  
 
   //return texture;
}
int init(void)
{
     LoadGLTexture();		   // Jump To Texture Loading Routine ( NEW )
	
     glEnable(GL_TEXTURE_2D);      // Enable Texture Mapping ( NEW )
     glClearColor (0.0, 0.0, 1.0, 0.0);
     glMatrixMode (GL_PROJECTION);
     gluOrtho2D (0.0, winWidth, 0.0, winHeight);
     glShadeModel (GL_SMOOTH);
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();
	
     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
     glBindTexture(GL_TEXTURE_2D, texture[0]);
	
      glClearDepth(1.0f);                 // Depth Buffer Setup

  //  glEnable(GL_DEPTH_TEST);            // Enables Depth Testing
  //  glDepthFunc(GL_LEQUAL);             // The Type Of Depth Testing To Do

      glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);  
    

}
void display(void)
{

    //clear the screen
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   glEnable(GL_TEXTURE_2D);
  
   //LoadGLTexture("face3.png", 180, 180);
   
   LoadGLTexture();
   
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
   glRotatef(Angle, 0.0, 0.0, 0.0);

     
   //Nose
   drawTriangle();

   //Face
   circle (250, 250, 400);
   
   
   //Inner Eyes
   glLoadIdentity();
   circle(200, 280, 10);
   drawCircle1(-30, 280, 10);
   
   //Eye lids
   glLoadIdentity();
   glScalef(0.6,0.2,0);
   circle(530, 2400, 60);
   circle(-150, 2150, 60);
   
   //Arc for eyebrows
   drawArc(500, 500, -70, -140, 100);
   drawArc(270, 500, -70, -140, 100);
   
   //Mouth
   drawArc(380, 250, 110, -180, 180);
  // drawArc(380, 100, -100, -180, 180);
   drawLine();
   
   
   
   // Force the rendering (off-screen)
   glFlush();

   // Handle the double buffering
   glutSwapBuffers();
}

Any suggestions?

Are you sure SOIL_load_OGL_texture() is returning successfully?

Also, have you specified the correct texture coordinates while drawing the shapes?

] but I still can't get the image to upload.[/I]

Could you take a screenshot of the output and post it here?

Are you sure SOIL_load_OGL_texture() is returning successfully?

Also, have you specified the correct texture coordinates while drawing the shapes?


Could you take a screenshot of the output and post it here?

I have attached the screen shot. I want want the image I'm uploading to appear behind this drawing.

Where do you actually drawn the background? All I see in your rendering code is the drawing of the face components (which are lines). Where do you draw a large rectangle with the texture object binded and mapped to it?

For example, you should have something like this in your render code (just after the glRotatef call):

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
     glBindTexture(GL_TEXTURE_2D, texture[0]);

     glBegin(GL_QUADS);
       glVertex3f(0,0,0.99);                 glTexCoord2f(0,0);
       glVertex3f(winWidth,0,0.99);          glTexCoord2f(1.0,0);
       glVertex3f(winWidth,winHeight,0.99);  glTexCoord2f(1.0,1.0);
       glVertex3f(0,winHeight,0.99);         glTexCoord2f(0,1.0);
     glEnd(GL_QUADS);

Where do you actually drawn the background? All I see in your rendering code is the drawing of the face components (which are lines). Where do you draw a large rectangle with the texture object binded and mapped to it?

For example, you should have something like this in your render code (just after the glRotatef call):

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
     glBindTexture(GL_TEXTURE_2D, texture[0]);

     glBegin(GL_QUADS);
       glVertex3f(0,0,0.99);                 glTexCoord2f(0,0);
       glVertex3f(winWidth,0,0.99);          glTexCoord2f(1.0,0);
       glVertex3f(winWidth,winHeight,0.99);  glTexCoord2f(1.0,1.0);
       glVertex3f(0,winHeight,0.99);         glTexCoord2f(0,1.0);
     glEnd(GL_QUADS);

You are right. I should include a code similar to your and I did but it's still not working. I don't think the problem is with you code. I think there's something else that I'm over-looking or not doing right. But you are right. I definitely needed to include your code. I researched a little bit on texture mapping.

The coordinates and vertexes in your code were floats but the vertexes in my code are integers so I converted the floats in your code to integers but that did not work either.

You are right. I should include a code similar to your and I did but it's still not working. I don't think the problem is with you code. I think there's something else that I'm over-looking or not doing right. But you are right. I definitely needed to include your code. I researched a little bit on texture mapping.

The coordinates and vertexes in your code were floats but the vertexes in my code are integers so I converted the floats in your code to integers but that did not work either.

I just found out that, my image which is in .png must be converted to raw RBG image data before I can successfully upload my image. I will try this also.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.