How to draw 3D rotating Cylinder

Hi,

i am new to openGL, i am not getting how to draw 3d Cylinder and that should be rotate in x-direction.

Please guide me, Your answer is valuable for me…

waiting for reply.

Please be more specific – what books or online articles have you looked at? What tools are you using C/C++? Posting your code always is a good start. It is quite difficult to answer such a broad question – maybe looking at how to do an animation itself may help so see Post# 267635

That post shows a rotating cube, to get a rotating cylinder the code is modifed to use GLUquadricObj as follows;


#include <GL/gl.h>
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>

GLfloat gAngle = 0.0;
GLUquadricObj *IDquadric;

void timer(int value)
{
  const int desiredFPS=120;
  glutTimerFunc(1000/desiredFPS, timer, ++value);
  GLfloat dt = 1./desiredFPS;

  //put your specific idle code here
  //... this code will run at desiredFPS
  gAngle += dt*360./8.; //rotate 360 degrees every 8 seconds
  //end your specific idle code here

  glutPostRedisplay(); // initiate display() call at desiredFPS rate
}

void display() {
  // Will be called at FPS rate, ok to use global values now to rener scene
  glClear(GL_COLOR_BUFFER_BIT);

  glPushMatrix();
    glTranslatef(0,0,-100);
    glRotatef(gAngle,1.,1.,1.);
    //glutWireCube(20.); //cube of size 20x20x20
    gluCylinder(IDquadric,10.0f,10.0f,10.0f,32,32);
  glPopMatrix();

  glutSwapBuffers();
}

void cleanupQuadric(void)          // Properly Kill The Window
{
  gluDeleteQuadric(IDquadric);
  printf( "cleanupQuadric completed
" );
}

void init() {
  glClearColor(0.0, 0.0, 0.0, 0.0);

  IDquadric=gluNewQuadric();      // Create A Pointer To The Quadric Object ( NEW )
  gluQuadricNormals(IDquadric, GLU_SMOOTH);  // Create Smooth Normals ( NEW )
  gluQuadricTexture(IDquadric, GL_TRUE);    // Create Texture Coords ( NEW )
  atexit(cleanupQuadric);

  GLdouble Vol = 10*1.8;
  GLdouble Left=-Vol;
  GLdouble Right=Vol;
  GLdouble Bottom=-Vol;
  GLdouble Top=Vol;
  GLdouble Near=0; 
  GLdouble Far=2*Vol;

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(Left, Right, Bottom, Top,  Near, Far);

  GLdouble eyeX=0;
  GLdouble eyeY=0;
  GLdouble eyeZ=-100+Vol;
  GLdouble centerX=0;
  GLdouble centerY=0;
  GLdouble centerZ=-100;
  GLdouble upX=0;
  GLdouble upY=1;
  GLdouble upZ=0;

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  gluLookAt(eyeX,eyeY,eyeZ,
            centerX,centerY,centerZ,
            upX,upY,upZ);
}

void keyboard(unsigned char key, int x, int y)
{
   switch (key) {
      case 27:  // escape key
         exit(0);
         break;
      default:
         break;
   }
}

int main(int argc, char** argv) {
   glutInit(&argc, argv);
   glutInitDisplayMode(GLUT_DOUBLE);
   glutCreateWindow("FPS test /w glutTimerFunc");

   glutTimerFunc(0,timer,0);
   glutDisplayFunc(display);
   glutKeyboardFunc(keyboard);

   init();

   glutMainLoop();
   return 0;
}

Hi,

Thank you so much.

i checked your code, it’s displaying perfect cylinder. i made other code to Display cylinder and rotation of that is mouse control. if you want to check the code means i will send it.

my assignment is to place bmp format images on the side surfaces of the Cylinder. i am using C in Ubuntu.
if i rotate the cylinder around the x-axis, it should highlight the current image from my point of view.
Please guide me, any valuable answer is appreciated.

i am thankful for any kind of help.

There is a nice image loading library called DevIL that is cross platform. Since you are on ubuntu it is a simple “sudo apt-get install libdevil-dev” command installation.

To use it see a previous post from earlier today at Post267979.

After you load the image like the post, you simply need to add two lines of code in the Display function before you start drawing the gluCylinder …


struct TextureHandle {
... identical from post267979, cut-n-paste
};

TextureHandle logo;

ILuint LoadImageDevIL (const char *szFileName, struct TextureHandle *T)
{
 ... identical to post267979, cut-n-paste
}

void init() {
... add following two lines
   ilInit(); //initialize DevIL library required
   LoadImageDevIL ("your.bmp", &logo);
}

void display() {
 ...
  //add two line to bind texture
  glEnable (GL_TEXTURE_2D);
  glBindTexture ( GL_TEXTURE_2D, logo.genID);

  // your previous drawing of quadric cylinder
  glPushMatrix();
    glTranslatef(0,0,-100);
    glRotatef(gAngle,1.,1.,1.);
    gluCylinder(IDquadric,10.0f,10.0f,10.0f,32,32);
  glPopMatrix();
...
}


someone forgot that’s about it:

Texture coordinate generation can be turned on and o with
gluQuadricTexture:

void gluQuadricTexture( GLUquadricObj *quadobj,GLboolean textureCoords );

GLU spec 6.3 page 21

Hi,

Thank You for your initiation.

I made the changes,what you sent above, but it’s giving the error as “logo” is undefined, but it’s already declared. i am not getting that… placing the entire code below and there is two init() functions so i commented the below init()function :

Code :

#include <GL/gl.h>
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>

#include <IL/ilut.h>

GLfloat gAngle = 0.0;
GLUquadricObj *IDquadric;

struct TextureHandle {

ILubyte *p;
ILuint id;
ILint w;
ILint h;
ILenum DestFormat;
ILenum DestType;
GLuint genID;

};
TextureHandle wmap, logo, frac;

ILuint LoadImageDevIL (const char *szFileName, struct TextureHandle *T)
{

ilEnable(IL_ORIGIN_SET);

ilOriginFunc(IL_ORIGIN_LOWER_LEFT);


ILuint ImageNameID;
ilGenImages(1, &ImageNameID);
ilBindImage(ImageNameID);
if (!ilLoadImage(szFileName)) return 0;
ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE);

T-&gt;id = ImageNameID;
T-&gt;p = ilGetData();
T-&gt;w = ilGetInteger(IL_IMAGE_WIDTH);
T-&gt;h = ilGetInteger(IL_IMAGE_HEIGHT);

  T-&gt;DestFormat = ilGetInteger(IL_IMAGE_FORMAT);
T-&gt;DestType = ilGetInteger(IL_IMAGE_TYPE);


glGenTextures(1, &T-&gt;genID);
glBindTexture(GL_TEXTURE_2D, T-&gt;genID);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D (GL_TEXTURE_2D, 0, T-&gt;DestFormat, T-&gt;w, T-&gt;h, 0, T-&gt;DestFormat, T-&gt;DestType, T-&gt;p);

printf("%s %d %d %d

",szFileName,T->id,T->w,T->h);
return 1;
}

void init() {

ilInit();
LoadImageDevIL ("/localhome/user/Temp/sample/bird.bmp", &logo);
}

void timer(int value)
{
const int desiredFPS=120;
glutTimerFunc(1000/desiredFPS, timer, ++value);
GLfloat dt = 1./desiredFPS;

gAngle += dt*360./8.;

glutPostRedisplay();
}

void display() {

 glEnable (GL_TEXTURE_2D);
  glBindTexture ( GL_TEXTURE_2D, logo.genID);

glClear(GL_COLOR_BUFFER_BIT);

glPushMatrix();
glTranslatef(0,0,-100);
glRotatef(gAngle,1.,1.,1.);

gluCylinder(IDquadric,10.0f,10.0f,10.0f,32,32);

glPopMatrix();

glutSwapBuffers();
}

void cleanupQuadric(void)
{
gluDeleteQuadric(IDquadric);
printf( "cleanupQuadric completed
" );
}
/*
void init() {
glClearColor(0.0, 0.0, 0.0, 0.0);

IDquadric=gluNewQuadric();
gluQuadricNormals(IDquadric, GLU_SMOOTH);
gluQuadricTexture(IDquadric, GL_TRUE);
atexit(cleanupQuadric);

GLdouble Vol = 101.8;
GLdouble Left=-Vol;
GLdouble Right=Vol;
GLdouble Bottom=-Vol;
GLdouble Top=Vol;
GLdouble Near=0;
GLdouble Far=2
Vol;

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(Left, Right, Bottom, Top, Near, Far);

GLdouble eyeX=0;
GLdouble eyeY=0;
GLdouble eyeZ=-100+Vol;
GLdouble centerX=0;
GLdouble centerY=0;
GLdouble centerZ=-100;
GLdouble upX=0;
GLdouble upY=1;
GLdouble upZ=0;

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(eyeX,eyeY,eyeZ,
centerX,centerY,centerZ,
upX,upY,upZ);
}
*/
void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 27:
exit(0);
break;
default:
break;
}
}

int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE);
glutCreateWindow(“FPS test /w glutTimerFunc”);

glutTimerFunc(0,timer,0);
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);

init();

glutMainLoop();
return 0;
}

and one more is it necessary to place this line
void gluQuadricTexture( GLUquadricObj *quadobj,GLboolean textureCoords );
if means, where i should i place ?
Compile: gcc cc1.c -o cc1 -I/usr/x11R6/include/ -L/usr/lib -lX11 -lXmu -lglut -lGL -lGLU

Is there any changes needed in above command, Guide me please.

i am thankful for any kind of help.

You need to place gluQuadricTexture(IDquadric, GL_TRUE); after you called your gluNewQuadric. This is what gives you texture coordinates.

The compile command I use is for C++ (filename.cpp)


g++ main.cpp  -lGL -lglut -lIL
but you can also use
gcc main.cpp  -lGL -lglut -lIL

Now if you have a .c extension instead of .cpp, then the gcc command will assume Ansi-C. In which case you have to declare with a “struct” explicitly.


for .cpp: TextureHandle logo;
          gcc main.cpp  -lGL -lglut -lIL
for   .c: struct TextureHandle logo;
          gcc main.c  -lGL -lglut -lIL

so your gcc compile command looks fine as is as long as you change to make the “logo” declaration ANSI-C instead of my ANSI-C++ as done in following code …

Here’s the code with the “struct” added for filename.c (ie c version)


// on linux with gcc: g++ main.c  -lGL -lglut -lIL
#include <GL/gl.h>
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>

#include <IL/ilut.h>

GLfloat gAngle = 0.0;
GLUquadricObj *IDquadric;

struct TextureHandle
{

  ILubyte *p;
  ILuint id;
  ILint w;
  ILint h;
  ILenum DestFormat;
  ILenum DestType;
  GLuint genID;

};

struct TextureHandle logo;

ILuint LoadImageDevIL (const char *szFileName, struct TextureHandle *T)
{

  ilEnable(IL_ORIGIN_SET);

  ilOriginFunc(IL_ORIGIN_LOWER_LEFT);

  ILuint ImageNameID;
  ilGenImages(1, &ImageNameID);
  ilBindImage(ImageNameID);
  if (!ilLoadImage(szFileName)) return 0;
  ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE);

  T->id = ImageNameID;
  T->p = ilGetData();
  T->w = ilGetInteger(IL_IMAGE_WIDTH);
  T->h = ilGetInteger(IL_IMAGE_HEIGHT);

  T->DestFormat = ilGetInteger(IL_IMAGE_FORMAT);
  T->DestType = ilGetInteger(IL_IMAGE_TYPE);

  glGenTextures(1, &T->genID);
  glBindTexture(GL_TEXTURE_2D, T->genID);
  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexImage2D (GL_TEXTURE_2D, 0, T->DestFormat, T->w, T->h, 0, T->DestFormat, T->DestType, T->p);

  printf("%s %d %d %d
",szFileName,T->id,T->w,T->h);
  return 1;
}


void timer(int value)
{
  const int desiredFPS=120;
  glutTimerFunc(1000/desiredFPS, timer, ++value);
  GLfloat dt = 1./desiredFPS;

  gAngle += dt*360./8.;

  glutPostRedisplay();
}


void display()
{

  glEnable (GL_TEXTURE_2D);
  glBindTexture ( GL_TEXTURE_2D, logo.genID);

  glClear(GL_COLOR_BUFFER_BIT);

  glPushMatrix();
  glTranslatef(0,0,-100);
  glRotatef(gAngle,1.,1.,1.);

  gluCylinder(IDquadric,10.0f,10.0f,10.0f,32,32);
  glPopMatrix();

  glutSwapBuffers();
}


void cleanupQuadric(void)
{
  gluDeleteQuadric(IDquadric);
  printf( "cleanupQuadric completed
" );
}


void init()
{
  glClearColor(0.0, 0.0, 0.0, 0.0);

  IDquadric=gluNewQuadric();
  gluQuadricNormals(IDquadric, GLU_SMOOTH);
  gluQuadricTexture(IDquadric, GL_TRUE);
  atexit(cleanupQuadric);

  GLdouble Vol = 10*1.8;
  GLdouble Left=-Vol;
  GLdouble Right=Vol;
  GLdouble Bottom=-Vol;
  GLdouble Top=Vol;
  GLdouble Near=0;
  GLdouble Far=2*Vol;

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(Left, Right, Bottom, Top, Near, Far);

  GLdouble eyeX=0;
  GLdouble eyeY=0;
  GLdouble eyeZ=-100+Vol;
  GLdouble centerX=0;
  GLdouble centerY=0;
  GLdouble centerZ=-100;
  GLdouble upX=0;
  GLdouble upY=1;
  GLdouble upZ=0;

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  gluLookAt(eyeX,eyeY,eyeZ,
    centerX,centerY,centerZ,
    upX,upY,upZ);

  ilInit();
  LoadImageDevIL ("/localhome/user/Temp/sample/bird.bmp", &logo);
  //LoadImageDevIL ("Logo.bmp", &logo);
}


void keyboard(unsigned char key, int x, int y)
{
  switch (key)
  {
    case 27:
      exit(0);
      break;
    default:
      break;
  }
}


int main(int argc, char** argv)
{
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_DOUBLE);
  glutCreateWindow("FPS test /w glutTimerFunc");

  glutTimerFunc(0,timer,0);
  glutDisplayFunc(display);
  glutKeyboardFunc(keyboard);

  init();

  glutMainLoop();
  return 0;
}

Hi,
Thank You very much for your reply marshats,

The above code is working fine without any error messages.
i just changed width and height to get good clarity.
i dint get what exactly below line indicates, why cant we use directly value for IDquadric :

GLUquadricObj *IDquadric;

and i changed the line as
gluCylinder (30, 5.0f, 5.0f, 10.0f, 24, 8);

This shows segmentation fault. This means memory related are what.

one more thing requesting you is how to place many different images on the same cylinder ?

Please guide me.

i am thankful for any kind of help.

This is a C question, whenever you see an argument of the form “type * X” then it expects an address, not the value, to be passed into the function … see glCylinder definition. Notice how the first argument it expects is a pointer to a GLUquadric. And reading further this pointer is defined by a very specific function, gluNewQuadric(). So you can’t use the value of “30” for the first argument of your gluCylinder (30, 5.0f, 5.0f, 10.0f, 24, 8) – the function is looking for the address not the value 30, this explains why you saw a segmentation fault.

The question about multiple textures on a single cylinder is more involved question. Do you have to do multiple textures or simply make a single texture in some drawing program that has the effect of multiple decals? The second approach easily maps to the code you already have. But if you have to do the first approach – A quick google search lead to multitexturing tutorial that may help you get started. Also see Post90211.

I believe with this you will have to start using the openGL extensions – you can get setup to use them with the GLEW library. On Ubuntu you can get it installed with a simple “sudo apt-get install libglew1.5-dev”. To use it read Glew basic usage.
Here’s code to simply add glew functionality (NOT multitexturing) – a single include is added with a call to glewInit(). And note the compile command is


gcc main.c  -lGL -lglut -lIL -lGLEW


// on linux with gcc: gcc main.c  -lGL -lglut -lIL -lGLEW
#include <GL/glew.h>
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>

#include <IL/ilut.h>

GLfloat gAngle = 0.0;
GLUquadricObj *IDquadric;

struct TextureHandle
{

  ILubyte *p;
  ILuint id;
  ILint w;
  ILint h;
  ILenum DestFormat;
  ILenum DestType;
  GLuint genID;

};

struct TextureHandle logo;

ILuint LoadImageDevIL (const char *szFileName, struct TextureHandle *T)
{

  ilEnable(IL_ORIGIN_SET);

  ilOriginFunc(IL_ORIGIN_LOWER_LEFT);

  ILuint ImageNameID;
  ilGenImages(1, &ImageNameID);
  ilBindImage(ImageNameID);
  if (!ilLoadImage(szFileName)) return 0;
  ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE);

  T->id = ImageNameID;
  T->p = ilGetData();
  T->w = ilGetInteger(IL_IMAGE_WIDTH);
  T->h = ilGetInteger(IL_IMAGE_HEIGHT);

  T->DestFormat = ilGetInteger(IL_IMAGE_FORMAT);
  T->DestType = ilGetInteger(IL_IMAGE_TYPE);

  glGenTextures(1, &T->genID);
  glBindTexture(GL_TEXTURE_2D, T->genID);
  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexImage2D (GL_TEXTURE_2D, 0, T->DestFormat, T->w, T->h, 0, T->DestFormat, T->DestType, T->p);

  printf("%s %d %d %d
",szFileName,T->id,T->w,T->h);
  return 1;
}


void timer(int value)
{
  const int desiredFPS=120;
  glutTimerFunc(1000/desiredFPS, timer, ++value);
  GLfloat dt = 1./desiredFPS;

  gAngle += dt*360./8.;

  glutPostRedisplay();
}


void display()
{

  glEnable (GL_TEXTURE_2D);
  glBindTexture ( GL_TEXTURE_2D, logo.genID);

  glClear(GL_COLOR_BUFFER_BIT);

  glMatrixMode(GL_MODELVIEW);
  glPushMatrix();
  glTranslatef(0,0,-100);
  glRotatef(gAngle,1.,1.,1.);

  gluCylinder(IDquadric,10.0f,10.0f,10.0f,32,32);
  glPopMatrix();

  glutSwapBuffers();
}


void cleanupQuadric(void)
{
  gluDeleteQuadric(IDquadric);
  printf( "cleanupQuadric completed
" );
}


void init()
{
  glClearColor(0.0, 0.0, 0.0, 0.0);

  IDquadric=gluNewQuadric();
  gluQuadricNormals(IDquadric, GLU_SMOOTH);
  gluQuadricTexture(IDquadric, GL_TRUE);
  atexit(cleanupQuadric);

  GLdouble Vol = 10*1.8;
  GLdouble Left=-Vol;
  GLdouble Right=Vol;
  GLdouble Bottom=-Vol;
  GLdouble Top=Vol;
  GLdouble Near=0;
  GLdouble Far=2*Vol;

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(Left, Right, Bottom, Top, Near, Far);

  GLdouble eyeX=0;
  GLdouble eyeY=0;
  GLdouble eyeZ=-100+Vol;
  GLdouble centerX=0;
  GLdouble centerY=0;
  GLdouble centerZ=-100;
  GLdouble upX=0;
  GLdouble upY=1;
  GLdouble upZ=0;

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  gluLookAt(eyeX,eyeY,eyeZ,
    centerX,centerY,centerZ,
    upX,upY,upZ);

  ilInit();
  LoadImageDevIL ("/localhome/user/Temp/sample/bird.bmp", &logo);
  //LoadImageDevIL ("Logo.bmp", &logo);
}


void keyboard(unsigned char key, int x, int y)
{
  switch (key)
  {
    case 27:
      exit(0);
      break;
    default:
      break;
  }
}


int main(int argc, char** argv)
{
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_DOUBLE);
  glutCreateWindow("FPS test /w glutTimerFunc");
  glewInit();

  glutTimerFunc(0,timer,0);
  glutDisplayFunc(display);
  glutKeyboardFunc(keyboard);

  init();

  glutMainLoop();
  return 0;
}

The changes of adding GLEW are just to help you have access to the commands like “glActiveTexture and glMultiTexCoord2f” that you will need for multi-texturing.

Hi,

i got the idea about segmentation fault. Thank you very much.

Regarding multitexturing, the code which is in above link is in shading language is it same for C. Sorry for asking simple question.

Guide me please.

Here’s a modified code example from a book well worth getting “OpenGL Programming Guide Fifth Edition, by Dave Shreiner, Mason Woo, Jackie Neider, Tom Davis” – Chapter 9 has multitex.c. It shows how to do multitexturing in c (but on a QUAD instead of a cylinder). The images themselves are quite indistinct so the example isn’t the best but it does show two images – look at the fullscreen window when running. That will improve when you use your own images that aren’t so dark.


/*  multitex.c
 from http://www.cosc.brocku.ca/Offerings/3P98/course/OpenGL/RedBookExamples/multitex.c
 slightly modified to use GLEW for extensions

// on linux with gcc: gcc main.c  -lGL -lglut -lIL -lGLEW
 */
#include <GL/glew.h>
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>

static GLubyte texels0[32][32][4];
static GLubyte texels1[16][16][4];

void makeCheckImages(void)
{
   int i, j;
    
   for (i = 0; i < 32; i++) {
      for (j = 0; j < 32; j++) {
         texels0[i][j][0] = (GLubyte) i;
         texels0[i][j][1] = (GLubyte) j;
         texels0[i][j][2] = (GLubyte) (i*j)/255;
         texels0[i][j][3] = (GLubyte) 255;
      }
   }

   for (i = 0; i < 16; i++) {
      for (j = 0; j < 16; j++) {
         texels1[i][j][0] = (GLubyte) 255;
         texels1[i][j][1] = (GLubyte) i;
         texels1[i][j][2] = (GLubyte) j;
         texels1[i][j][3] = (GLubyte) 255;
      }
   }
}

void init(void)
{    
   GLuint texNames[2];

   glClearColor (0.0, 0.0, 0.5, 0.0);
   glShadeModel(GL_FLAT);
   glEnable(GL_DEPTH_TEST);

   makeCheckImages();
   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

   glGenTextures(2, texNames);
   glBindTexture(GL_TEXTURE_2D, texNames[0]);
   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, 
		GL_UNSIGNED_BYTE, texels0);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 
                   GL_NEAREST);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 
                   GL_NEAREST);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

   glBindTexture(GL_TEXTURE_2D, texNames[1]);
   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, 
		GL_UNSIGNED_BYTE, texels1);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
   /*  Use the two texture objects to define two texture units
    *  for use in multitexturing  */
   glActiveTexture (GL_TEXTURE0);
   glEnable(GL_TEXTURE_2D);
   glBindTexture(GL_TEXTURE_2D, texNames[0]);
   glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
   glMatrixMode (GL_TEXTURE);
      glLoadIdentity();
      glTranslatef(0.5f, 0.5f, 0.0f);
      glRotatef(45.0f, 0.0f, 0.0f, 1.0f);
      glTranslatef(-0.5f, -0.5f, 0.0f);
   glMatrixMode (GL_MODELVIEW);
   glActiveTexture (GL_TEXTURE1);
   glEnable(GL_TEXTURE_2D);
   glBindTexture(GL_TEXTURE_2D, texNames[1]);
   glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}

void display(void)
{
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   glBegin(GL_TRIANGLES);
   glMultiTexCoord2f (GL_TEXTURE0, 0.0, 0.0);
   glMultiTexCoord2f (GL_TEXTURE1, 1.0, 0.0);
   glVertex2f(0.0, 0.0);
   glMultiTexCoord2f (GL_TEXTURE0, 0.5, 1.0);
   glMultiTexCoord2f (GL_TEXTURE1, 0.5, 0.0);
   glVertex2f(50.0, 100.0);
   glMultiTexCoord2f (GL_TEXTURE0, 1.0, 0.0);
   glMultiTexCoord2f (GL_TEXTURE1, 1.0, 1.0);
   glVertex2f(100.0, 0.0);
   glEnd();
   glutSwapBuffers();
}

void reshape(int w, int h)
{
   glViewport(0, 0, (GLsizei) w, (GLsizei) h);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   if (w <= h)
      gluOrtho2D(0.0, 100.0, 0.0, 100.0 * (GLdouble)h/(GLdouble)w);
   else
      gluOrtho2D(0.0, 100.0 * (GLdouble)w/(GLdouble)h, 0.0, 100.0);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
}

void keyboard(unsigned char key, int x, int y)
{
   switch (key) {
      case 27:
         exit(0);
         break;
   }
}

int main(int argc, char** argv)
{
   glutInit(&argc, argv);
   glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
   glutInitWindowSize(640, 480);
   glutInitWindowPosition(100, 100);
   glutCreateWindow(argv[0]);
   glewInit();
   init();
   glutReshapeFunc(reshape);
   glutDisplayFunc(display);
   glutKeyboardFunc (keyboard);
   glutMainLoop();
   return 0; 
}

I realized my previous post could use the older blending capabilities instead … see chapter06 in Redbook.

Heres some alternative code that reads two textures (Logo.bmp and Logo2.bmp) and combines them in two passes. The changes mostly occure in the Display() function.


// on linux with gcc: gcc main.c  -lGL -lglut -lIL -lGLEW
#include <GL/glew.h>
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>

#include <IL/ilut.h>

GLfloat gAngle = 0.0;
GLUquadricObj *IDquadric;

struct TextureHandle
{
  ILubyte *p;
  ILuint id;
  ILint w;
  ILint h;
  ILenum DestFormat;
  ILenum DestType;
  GLuint genID;

};

struct TextureHandle logo;
struct TextureHandle logo2;

ILuint LoadImageDevIL (const char *szFileName, struct TextureHandle *T)
{
  ilEnable(IL_ORIGIN_SET);

  ilOriginFunc(IL_ORIGIN_LOWER_LEFT);

  ILuint ImageNameID;
  ilGenImages(1, &ImageNameID);
  ilBindImage(ImageNameID);
  if (!ilLoadImage(szFileName)) return 0;
  ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE);

  T->id = ImageNameID;
  T->p = ilGetData();
  T->w = ilGetInteger(IL_IMAGE_WIDTH);
  T->h = ilGetInteger(IL_IMAGE_HEIGHT);

  T->DestFormat = ilGetInteger(IL_IMAGE_FORMAT);
  T->DestType = ilGetInteger(IL_IMAGE_TYPE);

  glGenTextures(1, &T->genID);
  glBindTexture(GL_TEXTURE_2D, T->genID);
  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexImage2D (GL_TEXTURE_2D, 0, T->DestFormat, T->w, T->h, 0, T->DestFormat, T->DestType, T->p);

  printf("%s %d %d %d
",szFileName,T->id,T->w,T->h);
  return 1;
}


void timer(int value)
{
  const int desiredFPS=120;
  glutTimerFunc(1000/desiredFPS, timer, ++value);
  GLfloat dt = 1./desiredFPS;

  gAngle += dt*360./8.;

  glutPostRedisplay();
}


void draw_cylinder() 
{
  glPushMatrix();
    glTranslatef(-5.,0,-100);
    glRotatef(gAngle,1.,0.,0.);
    glRotatef(90,0.,1.,0.);
    gluCylinder(IDquadric,10.0f,10.0f,10.0f,32,32);
  glPopMatrix();
}

void display()
{
  glClear(GL_COLOR_BUFFER_BIT);

  glMatrixMode(GL_MODELVIEW);

  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_COLOR,GL_DST_COLOR);

  glBindTexture ( GL_TEXTURE_2D, logo.genID);
  draw_cylinder();

  glBindTexture ( GL_TEXTURE_2D, logo2.genID);
  draw_cylinder();

  glutSwapBuffers();
}


void cleanupQuadric(void)
{
  gluDeleteQuadric(IDquadric);
  printf( "cleanupQuadric completed
" );
}


void init()
{
  glClearColor(0.0, 0.0, 0.0, 0.0);
  glEnable(GL_CULL_FACE);

  IDquadric=gluNewQuadric();
  gluQuadricNormals(IDquadric, GLU_SMOOTH);
  gluQuadricTexture(IDquadric, GL_TRUE);
  atexit(cleanupQuadric);

  GLdouble Vol = 10*1.8;
  GLdouble Left=-Vol;
  GLdouble Right=Vol;
  GLdouble Bottom=-Vol;
  GLdouble Top=Vol;
  GLdouble Near=0;
  GLdouble Far=2*Vol;

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(Left, Right, Bottom, Top, Near, Far);

  GLdouble eyeX=0;
  GLdouble eyeY=0;
  GLdouble eyeZ=-100+Vol;
  GLdouble centerX=0;
  GLdouble centerY=0;
  GLdouble centerZ=-100;
  GLdouble upX=0;
  GLdouble upY=1;
  GLdouble upZ=0;

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  gluLookAt(eyeX,eyeY,eyeZ,
    centerX,centerY,centerZ,
    upX,upY,upZ);

  ilInit();
  //LoadImageDevIL ("/localhome/user/Temp/sample/bird.bmp", &logo);
  LoadImageDevIL ("Logo.bmp", &logo);
  LoadImageDevIL ("Logo2.gif", &logo2);

  glEnable (GL_TEXTURE_2D);
}


void keyboard(unsigned char key, int x, int y)
{
  switch (key)
  {
    case 27:
      exit(0);
      break;
    default:
      break;
  }
}


int main(int argc, char** argv)
{
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_DOUBLE);
  glutCreateWindow("Multipass texturing Demo");
  glewInit();

  glutTimerFunc(0,timer,0);
  glutDisplayFunc(display);
  glutKeyboardFunc(keyboard);

  init();

  glutMainLoop();
  return 0;
}

Hi Thank you very much.

How to do multitexturing ?

i am using the code below :

AUX_RGBImageRec *LoadBMP(char *Filename)
{
FILE *File=NULL;

if (!Filename)							
{
	return NULL;						
}

File=fopen(Filename,"r");				

if (File)								
{
	fclose(File);						
	return auxDIBImageLoad(Filename);	
}

return NULL;							

}

int LoadGLTextures()
{
int Status=FALSE;

AUX_RGBImageRec *TextureImage[2];			

memset(TextureImage,0,sizeof(void *)*2);	

if ((TextureImage[0]=LoadBMP("Data/BG.bmp")) &&				
	(TextureImage[1]=LoadBMP("Data/Reflect.bmp")))			
{
	Status=TRUE;							

	glGenTextures(6, &texture[0]);			

	for (int loop=0; loop&lt;=1; loop++)
	{
		
		glBindTexture(GL_TEXTURE_2D, texture[loop]);		
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
		glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[loop]-&gt;sizeX, TextureImage[loop]-&gt;sizeY,
			0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[loop]-&gt;data);

		
		glBindTexture(GL_TEXTURE_2D, texture[loop+2]);		
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[loop]-&gt;sizeX, TextureImage[loop]-&gt;sizeY,
			0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[loop]-&gt;data);

		
		glBindTexture(GL_TEXTURE_2D, texture[loop+4]);		
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
		gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage[loop]-&gt;sizeX, TextureImage[loop]-&gt;sizeY,
			GL_RGB, GL_UNSIGNED_BYTE, TextureImage[loop]-&gt;data);
	}
	for (loop=0; loop&lt;=1; loop++)
	{
        if (TextureImage[loop])							
	    {
		        if (TextureImage[loop]-&gt;data)			
			    {
				        free(TextureImage[loop]-&gt;data);	
				}
				free(TextureImage[loop]);				
		}
	}
}

return Status;											

}

bool load_rgb_image(const char* file_name, int w, int h, RGBIMG* refimg)
{
GLuint sz;
FILE* file;
long fsize;
GLubyte* p;

refimg-&gt;w = (GLuint) w;
refimg-&gt;h = (GLuint) h;
sz = (((3*refimg-&gt;w+3)&gt;&gt;2)&lt;&lt;2)*refimg-&gt;h;
refimg-&gt;data = new GLubyte [sz];
if (refimg-&gt;data == NULL) return false;


file = fopen(file_name , "rb");
if (!file) return false;
fseek(file, 0L, SEEK_END);
fsize = ftell(file);
if (fsize != (long)sz) {
	fclose(file);
	return false;
}
fseek(file, 0L, SEEK_SET);
p = refimg-&gt;data;
while (fsize &gt; 0) {
	fread(p, 1, 1, file);
	p++;
	fsize--;
}
fclose(file); 
return true;

}

bool setup_textures()
{
RGBIMG img;

glGenTextures(TEXTURES_NUM, g_texid);          

if (!load_rgb_image("wall_64x64.raw", 64, 64, &img)) return false;

glBindTexture(GL_TEXTURE_2D, g_texid[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, 3, img.w, img.h, 0, GL_RGB, GL_UNSIGNED_BYTE, img.data);

glBindTexture(GL_TEXTURE_2D, g_texid[1]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, 3, img.w, img.h, 0, GL_RGB, GL_UNSIGNED_BYTE, img.data);

glBindTexture(GL_TEXTURE_2D, g_texid[2]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, img.w, img.h, GL_RGB, GL_UNSIGNED_BYTE, img.data);

delete img.data;
return true;

}

bool init(void)
{
if (!LoadGLTextures())
{
return FALSE;
}

glEnable(GL_TEXTURE_2D);							
glShadeModel(GL_SMOOTH);							
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);				
glClearDepth(1.0f);									
glEnable(GL_DEPTH_TEST);							
glDepthFunc(GL_LEQUAL);								

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);			
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

glLightfv(GL_LIGHT1, GL_AMBIENT, g_lightAmbient);   
glLightfv(GL_LIGHT1, GL_DIFFUSE, g_lightDiffuse);  
glLightfv(GL_LIGHT1, GL_POSITION,g_lightPosition);  
glEnable(GL_LIGHT1);                               

g_quadratic = gluNewQuadric();                     
if (g_quadratic == 0) return false;
gluQuadricNormals(g_quadratic, GLU_SMOOTH);         
gluQuadricTexture(g_quadratic, GL_TRUE);            

glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);	
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);	
return true;

}

int DrawGLScene(GLvoid) // Here’s Where We Do All The Drawing
{
return TRUE; // Keep Going
}

void render(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

glTranslatef(0.0f,0.0f,g_z);

glEnable(GL_TEXTURE_GEN_S);						
glEnable(GL_TEXTURE_GEN_T);						

glBindTexture(GL_TEXTURE_2D, texture[g_filter+(g_filter+1)]);		
glPushMatrix();
glRotatef(g_xrot,1.0f,0.0f,0.0f);
glRotatef(g_yrot,0.0f,1.0f,0.0f);
switch(g_object)
{
case 0:
	glDrawCube();
	break;
case 1:
	glTranslatef(0.0f,0.0f,-1.5f);					
	gluCylinder(g_quadratic,1.0f,1.0f,3.0f,32,32);			
	break;
case 2:
	gluSphere(g_quadratic,1.3f,32,32);				
	break;
case 3:
	glTranslatef(0.0f,0.0f,-1.5f);					
	gluCylinder(g_quadratic,1.0f,0.0f,3.0f,32,32);			
	break;
};

glPopMatrix();
glDisable(GL_TEXTURE_GEN_S);						
glDisable(GL_TEXTURE_GEN_T);						

glBindTexture(GL_TEXTURE_2D, texture[g_filter*2]);			
glPushMatrix();
	glTranslatef(0.0f, 0.0f, -24.0f);
	glBegin(GL_QUADS);
		glNormal3f( 0.0f, 0.0f, 1.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-13.3f, -10.0f,  10.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 13.3f, -10.0f,  10.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 13.3f,  10.0f,  10.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-13.3f,  10.0f,  10.0f);
	glEnd();

glPopMatrix();

g_xrot+=g_xspeed;
g_yrot+=g_yspeed;



glutSwapBuffers ( );

}

The above part of code i used for multitexturing, but it's not working.

please i am new to openGL, help me out from this.

i am thankful for any kind of help.

Hi,

Yes as you told, it’s displaying rectangle like object not a perfect Cylinder and two images on that are not so clear, they are compressed and shuffled…

Please help me from this.

i am thankful for Help.

What code are you referring exactly? I have lost track. Also did you see the Post268130 and compile and run it – that I think is a better example of multitexturing.

I have made a point to not use GLaux since it is over 15 years old, buggy, leaks memory, and deprecated – see the section on “External Links:Image Loader”
Getting Started. I really can’t help you debug that code with GLaux. I would suggest going back to using IL/il.h.

The GLaux code you posted is not a multitexturing example ie it does not apply two or more textures to the same geometric object. Instead it has one texture for each object and there are three objects which is not multitexturing. – Maybe we have a semantics misunderstanding – Do you want to apply two or more textures to the same object or simply have many objects each with their own texure decal?

As for why the image is compressed and distorted, understanding the Redbook Chapter 9 would be a better help there. But in essence it has to do with the specific numbers defined for S and T texture coordinates. Take a look at “Figure 9-6 : Texture-Map Distortion.” This is one of the more difficult things to get straight when first learning texturing – how the S and T coordinates and the original texture image correspond to one another visually.

Hi,
Thank you very much.

sorry for late reply. i am out.

I referred code which i placed above is from NeHe’s production example, which uses GLaux library. ok leave, if it’s old one.

I tried the code in Post268130 it’s working without errors,This code generates a rectangle object not a cylinder and images placed on that are shuffled, no clear separation between those images. you are right i need to place more images on the single object.

please what to do Now ?

I am thankful for any kind of help.

Here is a slightly modified code from post268130 – to show it is a cylinder by changing axis of rotation and adding a global gState that toggles between 0 and 1 as you press a key.


// on linux with gcc: gcc main.c  -lGL -lglut -lIL -lGLEW
#include <GL/glew.h>
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>

#include <IL/ilut.h>

GLfloat gAngle = 0.0;
GLUquadricObj *IDquadric;

GLuint gState = 0;

struct TextureHandle
{
  ILubyte *p;
  ILuint id;
  ILint w;
  ILint h;
  ILenum DestFormat;
  ILenum DestType;
  GLuint genID;

};

struct TextureHandle logo;
struct TextureHandle logo2;

ILuint LoadImageDevIL (const char *szFileName, struct TextureHandle *T)
{
  ilEnable(IL_ORIGIN_SET);

  ilOriginFunc(IL_ORIGIN_LOWER_LEFT);

  ILuint ImageNameID;
  ilGenImages(1, &ImageNameID);
  ilBindImage(ImageNameID);
  if (!ilLoadImage(szFileName)) return 0;
  ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE);

  T->id = ImageNameID;
  T->p = ilGetData();
  T->w = ilGetInteger(IL_IMAGE_WIDTH);
  T->h = ilGetInteger(IL_IMAGE_HEIGHT);

  T->DestFormat = ilGetInteger(IL_IMAGE_FORMAT);
  T->DestType = ilGetInteger(IL_IMAGE_TYPE);

  glGenTextures(1, &T->genID);
  glBindTexture(GL_TEXTURE_2D, T->genID);
  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexImage2D (GL_TEXTURE_2D, 0, T->DestFormat, T->w, T->h, 0, T->DestFormat, T->DestType, T->p);

  printf("%s %d %d %d
",szFileName,T->id,T->w,T->h);
  return 1;
}


void timer(int value)
{
  const int desiredFPS=120;
  glutTimerFunc(1000/desiredFPS, timer, ++value);
  GLfloat dt = 1./desiredFPS;

  gAngle += dt*360./8.;

  glutPostRedisplay();
}


void draw_cylinder() 
{
  glPushMatrix();
    glTranslatef(-5.,0,-100);
    glRotatef(gAngle,1.,0.,0.);
    glRotatef(90,1.,1.,0.);
    gluCylinder(IDquadric,10.0f,10.0f,10.0f,32,32);
  glPopMatrix();
}

void display()
{
  glClear(GL_COLOR_BUFFER_BIT);

  glMatrixMode(GL_MODELVIEW);

  if (gState) {
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_COLOR,GL_DST_COLOR);

    glBindTexture ( GL_TEXTURE_2D, logo.genID);
    draw_cylinder();

    glBindTexture ( GL_TEXTURE_2D, logo2.genID);
    draw_cylinder();

    glDisable(GL_BLEND);
  } else {
    glBindTexture ( GL_TEXTURE_2D, logo.genID);
    draw_cylinder();
  }

  glutSwapBuffers();
}


void cleanupQuadric(void)
{
  gluDeleteQuadric(IDquadric);
  printf( "cleanupQuadric completed
" );
}


void init()
{
  glClearColor(0.0, 0.0, 0.0, 0.0);
  glEnable(GL_CULL_FACE);

  IDquadric=gluNewQuadric();
  gluQuadricNormals(IDquadric, GLU_SMOOTH);
  gluQuadricTexture(IDquadric, GL_TRUE);
  atexit(cleanupQuadric);

  GLdouble Vol = 10*1.8;
  GLdouble Left=-Vol;
  GLdouble Right=Vol;
  GLdouble Bottom=-Vol;
  GLdouble Top=Vol;
  GLdouble Near=0;
  GLdouble Far=2*Vol;

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(Left, Right, Bottom, Top, Near, Far);

  GLdouble eyeX=0;
  GLdouble eyeY=0;
  GLdouble eyeZ=-100+Vol;
  GLdouble centerX=0;
  GLdouble centerY=0;
  GLdouble centerZ=-100;
  GLdouble upX=0;
  GLdouble upY=1;
  GLdouble upZ=0;

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  gluLookAt(eyeX,eyeY,eyeZ,
    centerX,centerY,centerZ,
    upX,upY,upZ);

  ilInit();
  //LoadImageDevIL ("/localhome/user/Temp/sample/bird.bmp", &logo);
  LoadImageDevIL ("Logo.bmp", &logo);
  LoadImageDevIL ("Logo2.gif", &logo2);

  glEnable (GL_TEXTURE_2D);
}


void keyboard(unsigned char key, int x, int y)
{
  switch (key)
  {
    case 27:
      exit(0);
      break;
    default:
      gState++;
      gState %= 2;
      printf("%d
",gState);
      break;
  }
}


int main(int argc, char** argv)
{
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_DOUBLE);
  glutCreateWindow("Multipass texturing Demo");
  glewInit();

  glutTimerFunc(0,timer,0);
  glutDisplayFunc(display);
  glutKeyboardFunc(keyboard);

  init();

  glutMainLoop();
  return 0;
}

Supply any two textures that will be applied multi-textured onto a single cylinder (lines 155 and 156), compile and run this code.

Notice what happens when you press the spacebar key – this will toggle between single texture and multi-texturing. Then look at the code that is relevant (see if-gState in Display). That’s all there is to multi-texturing using blending. To understand this read the chapters in the Redbook that I referred you to in the previous posts.

Hi,

Thank You so much for your valuable answer.

The above code result’s into cylinder,But while rotating, the back part of the cylinder is invisible.

i mean it shows semi-cylinder rotation. i gave two-textures on line 155 & 156. i changed the rotation parameters,but not displaying complete cylinder.

one more is i saw changes from single texture to multiple-texture
by pressing any key.

please help me out from above problem…

i am thankful for your help.

Actually the code is showing a complete cylinder but culling the back faces – to “fix” this I have added code to explicitly draw the top and bottom of the cylinder (see draw_cylinder() and the newly added gluDisk calls). Have you read Chapters 6 and 9 in the Redbook?


// on linux with gcc: gcc main.c  -lGL -lglut -lIL -lGLEW
// on win+mingw: gcc main8.c -lglut32 -lglu32 -lopengl32 -lwinmm -lgdi32  -lglew32 -lIL -L/usr/local/lib -I/usr/local/include
// 
#include <GL/glew.h>
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>

#include <IL/il.h>

GLfloat gAngle = 0.0;
GLUquadricObj *IDquadric;

GLuint gState = 0;

struct TextureHandle
{
  ILubyte *p;
  ILuint id;
  ILint w;
  ILint h;
  ILenum DestFormat;
  ILenum DestType;
  GLuint genID;
};

struct TextureHandle logo;
struct TextureHandle logo2;

ILuint LoadImageDevIL (const char *szFileName, struct TextureHandle *T)
{
  ilEnable(IL_ORIGIN_SET);

  ilOriginFunc(IL_ORIGIN_LOWER_LEFT);

  ILuint ImageNameID;
  ilGenImages(1, &ImageNameID);
  ilBindImage(ImageNameID);
  if (!ilLoadImage(szFileName)) return 0;
  ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE);

  T->id = ImageNameID;
  T->p = ilGetData();
  T->w = ilGetInteger(IL_IMAGE_WIDTH);
  T->h = ilGetInteger(IL_IMAGE_HEIGHT);

  T->DestFormat = ilGetInteger(IL_IMAGE_FORMAT);
  T->DestType = ilGetInteger(IL_IMAGE_TYPE);

  glGenTextures(1, &T->genID);
  glBindTexture(GL_TEXTURE_2D, T->genID);
  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexImage2D (GL_TEXTURE_2D, 0, T->DestFormat, T->w, T->h, 0, T->DestFormat, T->DestType, T->p);

  printf("%s %d %d %d
",szFileName,T->id,T->w,T->h);
  return 1;
}


void timer(int value)
{
  const int desiredFPS=120;
  glutTimerFunc(1000/desiredFPS, timer, ++value);
  GLfloat dt = 1./desiredFPS;

  gAngle += dt*360./8.;

  glutPostRedisplay();
}


void draw_cylinder() 
{
  glPushMatrix();
    glTranslatef(-5.,0,-100);
    glRotatef(gAngle,1.,1.,0.);

    gluCylinder(IDquadric,10.0f,10.0f,10.0f,32,32);

    glPushMatrix(); // top of cylinder
      glTranslatef(0.,0.,10.);
      gluDisk(IDquadric,0,10,32,32);
    glPopMatrix();

    glPushMatrix(); // bottom of cylinder
		  glFrontFace(GL_CW);
      gluDisk(IDquadric,0,10,32,32);
		  glFrontFace(GL_CCW);
    glPopMatrix();

  glPopMatrix();
}

void display()
{
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  glMatrixMode(GL_MODELVIEW);

  if (gState) {
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_COLOR,GL_DST_COLOR);

    glBindTexture ( GL_TEXTURE_2D, logo.genID);
    draw_cylinder();

    glBindTexture ( GL_TEXTURE_2D, logo2.genID);
    draw_cylinder();

    glDisable(GL_BLEND);
  } else {
    glBindTexture ( GL_TEXTURE_2D, logo.genID);
    draw_cylinder();
  }

  glutSwapBuffers();
}


void cleanupQuadric(void)
{
  gluDeleteQuadric(IDquadric);
  printf( "cleanupQuadric completed
" );
}


void init()
{
  glClearColor(0.0, 0.0, 0.0, 0.0);

  glEnable(GL_CULL_FACE);
  glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);

  IDquadric=gluNewQuadric();
  gluQuadricNormals(IDquadric, GLU_SMOOTH);
  gluQuadricTexture(IDquadric, GL_TRUE);
  atexit(cleanupQuadric);

  GLdouble Vol = 10*1.8;
  GLdouble Left=-Vol;
  GLdouble Right=Vol;
  GLdouble Bottom=-Vol;
  GLdouble Top=Vol;
  GLdouble Near=0;
  GLdouble Far=2*Vol;

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(Left, Right, Bottom, Top, Near, Far);

  GLdouble eyeX=0;
  GLdouble eyeY=0;
  GLdouble eyeZ=-100+Vol;
  GLdouble centerX=0;
  GLdouble centerY=0;
  GLdouble centerZ=-100;
  GLdouble upX=0;
  GLdouble upY=1;
  GLdouble upZ=0;

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  gluLookAt(eyeX,eyeY,eyeZ,
    centerX,centerY,centerZ,
    upX,upY,upZ);

  ilInit();
  //LoadImageDevIL ("/localhome/user/Temp/sample/bird.bmp", &logo);
  LoadImageDevIL ("Logo.bmp", &logo);
  LoadImageDevIL ("Logo2.bmp", &logo2);

  glEnable (GL_TEXTURE_2D);
}


void keyboard(unsigned char key, int x, int y)
{
  switch (key)
  {
    case 27:
      exit(0);
      break;
    default:
      gState++;
      gState %= 2;
      printf("%d
",gState);
      break;
  }
}


int main(int argc, char** argv)
{
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_DOUBLE|GLUT_DEPTH);
  glutCreateWindow("Multipass texturing Demo");
  glewInit();

  glutTimerFunc(0,timer,0);
  glutDisplayFunc(display);
  glutKeyboardFunc(keyboard);

  init();

  glutMainLoop();
  return 0;
}

Hi,

thank You So much for replying.

The above code is generating complete cylinder with top face.
Is there any function to display complete cylinder without top face. if i comment gluDisk()function it is not showing complete cylinder.

Yes as you specified in the previous post #268169, i studied Chapter-9. one more is as a fresher it is getting quite difficult for understanding. i will pickup shortly…

Please help me…

i am thankful for your help