rotate a teapot clockwise on a mouse click

Hello…
I have already made a flat floor with 3 teapots, fog effect and key movements to move the front teapot up, down, left and right.
I wanted to have mouse movements to the front teapot so that clicking on the left mouse button rotate the front teapot by some angle and right button click rotates it anticlockwise.

In my code, the entire scene is rotated along with the floor and all the teapots.I just need the front teapot to rotate without changing the entire scene.

Please help me out with this problem?
Here is my code !!

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

#define checkImageWidth 128
#define checkImageHeight 128

static GLint fogMode;
static GLubyte checkImage[checkImageHeight][checkImageWidth][4];
static int flag = GL_TRUE;
GLfloat translation[2];
GLfloat spin;
float FogCol[3]={0.8f,0.8f,0.8f};

void drawCheckImage(void)
{
int i, j, c;

for (i = 0; i < checkImageHeight; i++) {
for (j = 0; j < checkImageWidth; j++) {
c = ((((i&0x8)==0)^((j&0x8))==0))*255;
checkImage[i][j][0] = (GLubyte) c;
checkImage[i][j][1] = (GLubyte) c;
checkImage[i][j][2] = (GLubyte) c;
checkImage[i][j][3] = (GLubyte) 255;
}
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

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_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, checkImageWidth, checkImageHeight,
0, GL_RGBA, GL_UNSIGNED_BYTE, checkImage);

glFrontFace (GL_CW);
}

static void init(void)
{
translation[0]=0.0;
translation[1]=0.0;
spin=0.0;

glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);

drawCheckImage();

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,0);
glEnable(GL_COLOR_MATERIAL);

float black[4]={0,0,0,0};
glMaterialfv(GL_FRONT,GL_AMBIENT,black);
glMaterialfv(GL_FRONT,GL_SPECULAR,black);
}

static void renderTeapot (GLfloat x, GLfloat y, GLfloat z)
{
glPushMatrix();
glTranslatef (x, y, z);
glutSolidTeapot(1.8);
glPopMatrix();
}

void reshape(int w, int h)
{
glViewport(0, 0,(GLsizei) w,(GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (float) w/(float) h, 1.0, 200.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -40.0f);
glRotatef(30, 1, 0, 0);
}

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

glDisable(GL_TEXTURE_2D);
glColor3f(0.4,0.0,0.8);
renderTeapot ((-5.0+translation[0]), (0.8+translation[1]), 5.0);
glRotatef (spin, 1.0, 0.0, 0.0);

glColor3f(0.1,0.5,0.3);
renderTeapot (0, 0.8, -5.0);
glColor3f(0.6,0.0,0.0);
renderTeapot (5, 0.8, -15.0);

glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

glColor3f(0.1, 0.1, 0.1);
glBegin(GL_QUADS);

glNormal3f(0, 1, 0);
glTexCoord2f(0, 0);
glVertex3f(-17.0, 0, 22.0);
glTexCoord2f(0, 1);
glVertex3f(-17.0, 0, -22.0);
glTexCoord2f(1, 1);
glVertex3f(17.0, 0, -22.0);
glTexCoord2f(1, 0);
glVertex3f(17.0,0, 22.0);

glEnd();

if (flag) {
glEnable(GL_FOG);
{
GLfloat fogColor[4] = {0.8, 0.8, 0.8, 1.0};
fogMode = GL_EXP;
glFogi (GL_FOG_MODE, fogMode);
glFogfv (GL_FOG_COLOR, fogColor);
glFogf (GL_FOG_DENSITY, 0.03);
glHint (GL_FOG_HINT, GL_DONT_CARE);
glClearColor (0.7, 0.7, 0.7, 1.0);
}
}
else
{
glDisable(GL_FOG);
glClearColor(0.0, 0.0, 0.0, 0.0);
}
glutSwapBuffers();
}

void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case ‘f’:
case ‘F’:
flag = !flag;
glutPostRedisplay();
break;

  case 27:  
     exit(0);
     break;
  default:
     break;

}
}

void special(int key, int x, int y)
{
switch (key) {

case GLUT_KEY_LEFT:
translation[0]= translation[0]+(-1.0);
glutPostRedisplay();
break;

case GLUT_KEY_RIGHT:
translation[0]= translation[0]+(1.0);
glutPostRedisplay();
break;

case GLUT_KEY_UP:
translation[1]= translation[1]+(1.0);
glutPostRedisplay();
break;

case GLUT_KEY_DOWN:
translation[1]= translation[1]+(-1.0);
glutPostRedisplay();
break;
}
}

void mouse(int button, int state, int x, int y)
{
switch (button) {
case GLUT_LEFT_BUTTON:
spin = (spin + 20.0);
glutPostRedisplay();
break;

  case GLUT_RIGHT_BUTTON:
     spin = (spin - 20.0);
 glutPostRedisplay();
     break;
  }

}

int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(750, 750);
glutInitWindowPosition(100,100);
glutCreateWindow(argv[0]);
init();
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutSpecialFunc(special);
glutKeyboardFunc (keyboard);
glutMouseFunc(mouse);
glEnable(GL_DEPTH_TEST);
glutMainLoop();
return 0;
}

Rotation is just another transformation, like the translation.
Since you only want to rotate a single teapot, you need to enclose the rotation and renderTeapot functions in a push/pop matrix() -
glPushMatrix()
rotate teapot
render teapot
glPopMatrix()

The hard part is deciding which order the rotation and translation go in. When you apply any transformation to the current matrix, OpenGL pre/left multiplies by that matrix, meaning it does transformation * modelview matrix = modelview matrix. glRotatef rotates things about the origin of the coordinate system; if the center of the coordinate system is the center of the object, then it simply rotates the object. You want the rotation to rotate only the teapot, so that transformation, conceptually, comes first. Looking at the matrix multiplication, the function call to rotate the teapot should come last, but before you call glutSolidTeapot.

Here’s what I would do:
I would modify renderTeapot to take two arguments. The first points to the location of the teapot as a 3-element array, and the second stores the rotation in a way you see fit (rotation only about the x-axis, as you have here, or all the arguments to glRotatef, or some other system). RenderTeapot then becomes:
glPushMatrix();
glTranslatef(stuff);
glRotatef(other stuff);
glutSolidTeapot(1.8);
glPopMatrix();

Hey…
Thanks a lot…I tried to modify the code as per your suggestions and it is working fine :slight_smile:

I have one more question to ask :

Any special keys(up, left…)defined in my function or left or right mouse click activates the fog effect.Even when i resize the window to fit the screen size, the fog effect gets activated.I don’t know why?

I am unable to get the problem fixed.Please let me know if i am doing an unaware mistake??..

Here’s what tipped me of to the solution:
In the display function, you clear the color buffer, then decide whether you have fog and what color the clear color should be. I think you should decide what the clear color is before you clear the buffer.
Following that same logic, you should have fog enabled before you draw things subject to fog, so that should also go before the rendering. I copied the entire if(fog) block up before your glClear and it seems to work fine.

Thanks for your help again…
I solved this problem as well :slight_smile: