My Rotation is not correct, please help

Hi Everyone :slight_smile:

I am trying to get the cylinder to rotate with the floor (cube). Unfortunately I cannot get this to work correctly. Please let me know if you can see where I have gone wrong?

Thanks a lot, my code is:


#include <windows.h>							// Header File For Windows
#include <gl\gl.h>								// Header File For The OpenGL32 Library
#include <gl\glu.h>								// Header File For The GLu32 Library
#include <gl\glut.h>

GLfloat rotXAngle = 0.0;
GLfloat rotYAngle = 0.0;
GLfloat rotAngle = 0.0;
GLfloat fov = 60.0;
bool isRotating = false;
bool isReverse = false;
int width = 800;
int height = 800;

const float ar = (float)width / (float)height;

void IdleFunc()
{
	if (isRotating)
	{
		if (isReverse)
		{
			rotAngle -= 0.5f;
		}
		else
		{
			rotAngle += 0.5f;
		}
	}

	glutPostRedisplay();
}

void toggleAnimation()
{
	if (isRotating){
		isRotating = false;
	}
	else {
		isRotating = true;
	}
}

void changeRotation()
{
	if (isRotating){
		if (isReverse)
		{
			isReverse = false;
		}
		else
		{
			isReverse = true;
		}
	}
}

void KeyboardFunc(BYTE key, int x, int y)
{
	switch (key)
	{
	case 27: // Escape key
		exit(0);
		break;
	case 82: // r key
		toggleAnimation();
		break;
	case 114: // R key
		toggleAnimation();
		break;
	case 83: // s key
		changeRotation();
		break;
	case 115: // S key
		changeRotation();
		break;
	}
}

void zoomIn()
{
	if (fov > 30)
		fov -= 1.0;
}

void zoomOut()
{
	if (fov < 90)
		fov += 1.0;
}

void SpecialFunc(int key, int x, int y)
{
	switch (key)
	{
	case GLUT_KEY_UP:
		zoomIn();
		break;
	case GLUT_KEY_DOWN:
		zoomOut();
		break;
	}
}

void demo_menu(int id)
{
	switch (id)
	{
	case 1:
		exit(0);
		break;
	case 2:
		toggleAnimation();
		break;
	case 3:
		changeRotation();
		break;
	case 4:
		zoomIn();
		break;
	case 5:
		zoomOut();
		break;
	}
	glutPostRedisplay();
}

static void resize(int width, int height)
{
	glViewport(0, 0, width, height);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	//glFrustum(-ar, ar, -1.0, 1.0, 2.0, 100.0);
	gluPerspective(fov, ar, 1.0, 100.0);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

void DrawCylinder(void)
{
	GLUquadricObj *quadratic;
	quadratic = gluNewQuadric();

	glPushMatrix();
	glLoadIdentity();
	glTranslatef(0.0f, 1.0f, -15.0f);
	glRotatef(100.0f, 1.0f, 0.0f, 0.0f);
	glRotatef(rotAngle, 0.0f, 1.0f, 0.0f);
	glColor4f(0.5f, 0.0f, 0.0f, 1.0f);
	gluCylinder(quadratic, 1.0f, 1.0f, 1.0, 32, 32);
	glPopMatrix();
}

void DrawFloor(void)
{
	glPushMatrix();
	glLoadIdentity(); //resets drawing position
	glTranslatef(0.0f, 0.0f, -15.0f);
	glRotatef(10.0f, 1.0f, 0.0f, 0.0f);
	glRotatef(rotAngle, 0.0f, 1.0f, 0.0f);
	glColor4f(0.5f, 0.5f, 0.5f, 1.0f);

	glBegin(GL_QUADS);

	glVertex3f(5.0f, 0.1f, -5.0f);			// Top Right Of The Quad (Top)
	glVertex3f(-5.0f, 0.1f, -5.0f);			// Top Left Of The Quad (Top)
	glVertex3f(-5.0f, 0.1f, 5.0f);			// Bottom Left Of The Quad (Top)
	glVertex3f(5.0f, 0.1f, 5.0f);			// Bottom Right Of The Quad (Top)

	glColor4f(0.1f, 0.1f, 0.1f, 1.0f);
	glVertex3f(5.0f, -0.1f, 5.0f);			// Top Right Of The Quad (Bottom)
	glVertex3f(-5.0f, -0.1f, 5.0f);			// Top Left Of The Quad (Bottom)
	glVertex3f(-5.0f, -0.1f, -5.0f);			// Bottom Left Of The Quad (Bottom)
	glVertex3f(5.0f, -0.1f, -5.0f);			// Bottom Right Of The Quad (Bottom)

	glColor4f(0.3f, 0.3f, 0.3f, 1.0f);
	glVertex3f(5.0f, 0.1f, 5.0f);			// Top Right Of The Quad (Front)
	glVertex3f(-5.0f, 0.1f, 5.0f);			// Top Left Of The Quad (Front)
	glVertex3f(-5.0f, -0.1f, 5.0f);			// Bottom Left Of The Quad (Front)
	glVertex3f(5.0f, -0.1f, 5.0f);			// Bottom Right Of The Quad (Front)

	glColor4f(0.3f, 0.3f, 0.3f, 1.0f);
	glVertex3f(5.0f, -0.1f, -5.0f);			// Bottom Left Of The Quad (Back)
	glVertex3f(-5.0f, -0.1f, -5.0f);			// Bottom Right Of The Quad (Back)
	glVertex3f(-5.0f, 0.1f, -5.0f);			// Top Right Of The Quad (Back)
	glVertex3f(5.0f, 0.1f, -5.0f);			// Top Left Of The Quad (Back)

	glColor4f(0.3f, 0.3f, 0.3f, 1.0f);
	glVertex3f(-5.0f, 0.1f, 5.0f);			// Top Right Of The Quad (Left)
	glVertex3f(-5.0f, 0.1f, -5.0f);			// Top Left Of The Quad (Left)
	glVertex3f(-5.0f, -0.1f, -5.0f);			// Bottom Left Of The Quad (Left)
	glVertex3f(-5.0f, -0.1f, 5.0f);			// Bottom Right Of The Quad (Left)


	glVertex3f(5.0f, 0.1f, -5.0f);			// Top Right Of The Quad (Right)
	glVertex3f(5.0f, 0.1f, 5.0f);			// Top Left Of The Quad (Right)
	glVertex3f(5.0f, -0.1f, 5.0f);			// Bottom Left Of The Quad (Right)
	glVertex3f(5.0f, -0.1f, -5.0f);			// Bottom Right Of The Quad (Right)

	glEnd();			// Done Drawing The Quad
	glPopMatrix();
}

//--------------------------------------------------------------------------------------------
// DrawGLScene()
//--------------------------------------------------------------------------------------------
void DrawGLScene(void)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glEnable(GL_DEPTH_TEST);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(fov, ar, 1.0, 100.0);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();	
	
	// Now draw and rotate objects..
	DrawFloor();
	DrawCylinder();

	glutSwapBuffers();
}

/* Program entry point */
int main(int argc, char *argv[])
{
	glutInit(&argc, argv);
	glutInitWindowSize(width, height);
	glutInitWindowPosition(100, 100);
	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);

	glutCreateWindow("My Animation");

	glutSpecialFunc(SpecialFunc);
	glutKeyboardFunc(KeyboardFunc);
	glutReshapeFunc(resize);
	glutDisplayFunc(DrawGLScene);
	glutIdleFunc(IdleFunc);

	glutCreateMenu(demo_menu);
	glutAddMenuEntry("toggle animation", 2);
	glutAddMenuEntry("change rotation", 3);
	glutAddMenuEntry("zoom in", 4);
	glutAddMenuEntry("zoom out", 5);
	glutAddMenuEntry("quit", 1);
	glutAttachMenu(GLUT_RIGHT_BUTTON);

	glutMainLoop(); //transfer program to glut

	return EXIT_SUCCESS;
}

The floor is rotating about an axis which is 10 degrees from vertical, while the cylinder is rotating about an axis which is 100 degrees from vertical.

If you wanted the cylinder to be oriented so that it’s axis is vertical, you need to put a 90-degree rotation after the animated rotation, e.g.


	glRotatef(10.0f, 1.0f, 0.0f, 0.0f);
	glRotatef(rotAngle, 0.0f, 1.0f, 0.0f);
	glRotatef(90.0f, 1.0f, 0.0f, 0.0f);

More generally, you’d normally have related objects share the common parts of their transformation rather than constructing each object’s transformation from scratch. E.g.


void DrawGLScene(void)
{
    ...
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();	
	glTranslatef(0.0f, 0.0f, -15.0f);
	glRotatef(10.0f, 1.0f, 0.0f, 0.0f);
	glRotatef(rotAngle, 0.0f, 1.0f, 0.0f);
	DrawFloor();
	DrawCylinder();

This way, the position and rotation apply to both the floor and the cylinder. DrawFloor() wouldn’t need any additional transformations while DrawCylinder() would just need the 90-degree rotation.

Transformation hierarchies should be covered in any decent introduction to 3D graphics, e.g.the Red Book.

Wow, thank you so much for the info. I never for a moment thought about splitting up the rotations. Thank you very very much for the help and the very insightful reply. I really do appreciate it.

I have since implemented your suggestions. Also, thanks a lot for the link to the red book.

What I would like to now do is have the cylinder rotate with the flattened cube around the y axis. Is this possible? That is why I have split up the transformations.


#include <windows.h>							// Header File For Windows
#include <gl\gl.h>								// Header File For The OpenGL32 Library
#include <gl\glu.h>								// Header File For The GLu32 Library
#include <gl\glut.h>

GLfloat rotXAngle = 0.0;
GLfloat rotYAngle = 0.0;
GLfloat rotAngle = 0.0;
GLfloat fov = 60.0;
bool isRotating = false;
bool isReverse = false;
int width = 800;
int height = 800;

const float ar = (float)width / (float)height;

void IdleFunc()
{
	if (isRotating)
	{
		if (isReverse)
		{
			rotAngle -= 0.5f;
		}
		else
		{
			rotAngle += 0.5f;
		}
	}

	glutPostRedisplay();
}

void toggleAnimation()
{
	if (isRotating){
		isRotating = false;
	}
	else {
		isRotating = true;
	}
}

void changeRotation()
{
	if (isRotating){
		if (isReverse)
		{
			isReverse = false;
		}
		else
		{
			isReverse = true;
		}
	}
}

void KeyboardFunc(BYTE key, int x, int y)
{
	switch (key)
	{
	case 27: // Escape key
		exit(0);
		break;
	case 82: // r key
		toggleAnimation();
		break;
	case 114: // R key
		toggleAnimation();
		break;
	case 83: // s key
		changeRotation();
		break;
	case 115: // S key
		changeRotation();
		break;
	}
}

void zoomIn()
{
	if (fov > 30)
		fov -= 1.0;
}

void zoomOut()
{
	if (fov < 90)
		fov += 1.0;
}

void SpecialFunc(int key, int x, int y)
{
	switch (key)
	{
	case GLUT_KEY_UP:
		zoomIn();
		break;
	case GLUT_KEY_DOWN:
		zoomOut();
		break;
	}
}

void demo_menu(int id)
{
	switch (id)
	{
	case 1:
		exit(0);
		break;
	case 2:
		toggleAnimation();
		break;
	case 3:
		changeRotation();
		break;
	case 4:
		zoomIn();
		break;
	case 5:
		zoomOut();
		break;
	}
	glutPostRedisplay();
}

static void resize(int width, int height)
{
	glViewport(0, 0, width, height);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	//glFrustum(-ar, ar, -1.0, 1.0, 2.0, 100.0);
	gluPerspective(fov, ar, 1.0, 100.0);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

void DrawCylinder(void)
{
	GLUquadricObj *quadratic;
	quadratic = gluNewQuadric();

	glPushMatrix();
	glLoadIdentity();
	glTranslatef(-3.0f, 1.2f, -15.0f);
	glRotatef(10.0f, 1.0f, 0.0f, 0.0f);
	glRotatef(rotAngle, 0.0f, 1.0f, 0.0f);
	glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
	glColor4f(0.5f, 0.0f, 0.0f, 1.0f);
	gluCylinder(quadratic, 1.0f, 1.0f, 1.0, 32, 32);
	glPopMatrix();
}

void DrawFloor(void)
{
	glPushMatrix();
	glLoadIdentity(); //resets drawing position
	glTranslatef(0.0f, 0.0f, -15.0f);
	glRotatef(10.0f, 1.0f, 0.0f, 0.0f);
	glRotatef(rotAngle, 0.0f, 1.0f, 0.0f);
	glColor4f(0.5f, 0.5f, 0.5f, 1.0f);

	glBegin(GL_QUADS);

	glVertex3f(5.0f, 0.1f, -5.0f);			// Top Right Of The Quad (Top)
	glVertex3f(-5.0f, 0.1f, -5.0f);			// Top Left Of The Quad (Top)
	glVertex3f(-5.0f, 0.1f, 5.0f);			// Bottom Left Of The Quad (Top)
	glVertex3f(5.0f, 0.1f, 5.0f);			// Bottom Right Of The Quad (Top)

	glColor4f(0.1f, 0.1f, 0.1f, 1.0f);
	glVertex3f(5.0f, -0.1f, 5.0f);			// Top Right Of The Quad (Bottom)
	glVertex3f(-5.0f, -0.1f, 5.0f);			// Top Left Of The Quad (Bottom)
	glVertex3f(-5.0f, -0.1f, -5.0f);			// Bottom Left Of The Quad (Bottom)
	glVertex3f(5.0f, -0.1f, -5.0f);			// Bottom Right Of The Quad (Bottom)

	glColor4f(0.3f, 0.3f, 0.3f, 1.0f);
	glVertex3f(5.0f, 0.1f, 5.0f);			// Top Right Of The Quad (Front)
	glVertex3f(-5.0f, 0.1f, 5.0f);			// Top Left Of The Quad (Front)
	glVertex3f(-5.0f, -0.1f, 5.0f);			// Bottom Left Of The Quad (Front)
	glVertex3f(5.0f, -0.1f, 5.0f);			// Bottom Right Of The Quad (Front)

	glColor4f(0.3f, 0.3f, 0.3f, 1.0f);
	glVertex3f(5.0f, -0.1f, -5.0f);			// Bottom Left Of The Quad (Back)
	glVertex3f(-5.0f, -0.1f, -5.0f);			// Bottom Right Of The Quad (Back)
	glVertex3f(-5.0f, 0.1f, -5.0f);			// Top Right Of The Quad (Back)
	glVertex3f(5.0f, 0.1f, -5.0f);			// Top Left Of The Quad (Back)

	glColor4f(0.3f, 0.3f, 0.3f, 1.0f);
	glVertex3f(-5.0f, 0.1f, 5.0f);			// Top Right Of The Quad (Left)
	glVertex3f(-5.0f, 0.1f, -5.0f);			// Top Left Of The Quad (Left)
	glVertex3f(-5.0f, -0.1f, -5.0f);			// Bottom Left Of The Quad (Left)
	glVertex3f(-5.0f, -0.1f, 5.0f);			// Bottom Right Of The Quad (Left)


	glVertex3f(5.0f, 0.1f, -5.0f);			// Top Right Of The Quad (Right)
	glVertex3f(5.0f, 0.1f, 5.0f);			// Top Left Of The Quad (Right)
	glVertex3f(5.0f, -0.1f, 5.0f);			// Bottom Left Of The Quad (Right)
	glVertex3f(5.0f, -0.1f, -5.0f);			// Bottom Right Of The Quad (Right)

	glEnd();			// Done Drawing The Quad
	glPopMatrix();

	
}

//--------------------------------------------------------------------------------------------
// DrawGLScene()
//--------------------------------------------------------------------------------------------
void DrawGLScene(void)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glEnable(GL_DEPTH_TEST);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(fov, ar, 1.0, 100.0);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();	

	
	// Now draw and rotate objects..
	DrawFloor();
	DrawCylinder();

	glutSwapBuffers();
}

/* Program entry point */
int main(int argc, char *argv[])
{
	glutInit(&argc, argv);
	glutInitWindowSize(width, height);
	glutInitWindowPosition(100, 100);
	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);

	glutCreateWindow("Assignment 01: Student 33816115");

	glutSpecialFunc(SpecialFunc);
	glutKeyboardFunc(KeyboardFunc);
	glutReshapeFunc(resize);
	glutDisplayFunc(DrawGLScene);
	glutIdleFunc(IdleFunc);

	glutCreateMenu(demo_menu);
	glutAddMenuEntry("toggle animation", 2);
	glutAddMenuEntry("change rotation", 3);
	glutAddMenuEntry("zoom in", 4);
	glutAddMenuEntry("zoom out", 5);
	glutAddMenuEntry("quit", 1);
	glutAttachMenu(GLUT_RIGHT_BUTTON);

	glutMainLoop(); //transfer program to glut

	return EXIT_SUCCESS;
}

Thanks again for the help :slight_smile:

Yes.

However, the cylinder is still rotating about a different axis to the cube; it’s at the correct angle, but the offset is different:

Again, the key point is that the transformations should form a hierarchy, with the initial components (up to and including the animated rotation) applying to both parts, rather than each component trying to construct its transformation from scratch (starting from an identity matrix).

Thanks a lot. For the project I am working on, they only ever explained working with one object. Now it is asking for an environment drawn up with multiple objects. Unfortunately the book never touched on transformations and hierarchies.

Seeing that time is a bit of a problem for me, is there perhaps an example that you know of that I can go through? Thanks a lot

[QUOTE=Syzygy187;1279176]Thanks a lot. For the project I am working on, they only ever explained working with one object. Now it is asking for an environment drawn up with multiple objects. Unfortunately the book never touched on transformations and hierarchies.

Seeing that time is a bit of a problem for me, is there perhaps an example that you know of that I can go through? Thanks a lot[/QUOTE]

Chapter 3 of the red book covers transformations. Examples 3-6 and 3-7 cover composing transformations.

thanks a lot :slight_smile: