# A Strange Inconsistency with the Right-Hand Rule While Using glRotatef

Maybe someone can lend me a quick hand with this one. I’ve been working through the OpenGL SuperBible (3rd edition) just to get a feel for the API. In the example below from the fourth chapter three simple spheres are drawn using GLUT and they rotate around another sphere that rests in the middle. Very straightforward stuff and the program runs just fine…

Problem is that spheres that rotate around the x- and z-axes are–as best as I can reason–rotating the wrong way: they are rotating CW instead of the expected CCW. Maybe I’m just not visualizing this the correct way, but I’m pretty sure that I am.

The first sphere, which rotates around the y-axis, is issued a glRotatef() command to establish a vector which points in the positive y-direction, and it rotates CCW. The other two spheres also have positive vectors along the x- and z- axes, but they are inconsistently reversed in their rotations. I cannot figure out an explanation as to why.

The code for the program is below. The important parts are in the middle of the RenderScene() function.

``````
#include <windows.h>

#include <GL\gl.h>
#include <GL\glu.h>

#include <GL\glut.h>

// Rotation amounts
static GLfloat xRot		= 0.0f;
static GLfloat yRot		= 0.0f;

/* Called to draw scene */

void RenderScene( void )	{

// Angle of revolution around the nucleus
static GLfloat fElect1 = 0.0f;

// Clear the window with current clearing color
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

// Reset the modelview matrix
glMatrixMode( GL_MODELVIEW );

// Translate the whole scene out and into view
// This is the initial viewing transformation
glTranslatef( 0.0f, 0.0f, -100.0f );

// Yellow electron
glColor3ub( 255, 255, 0 );
// First Electron Orbit
// Save viewing transformation
glPushMatrix();
// Rotate by angle of revolution
glRotatef( fElect1, 0.0f, 1.0f, 0.0f );
// Translate out from origin to orbit distance
glTranslatef( 90.0f, 0.0f, 0.0f );
// Draw the electron
glutSolidSphere( 6.0f, 15, 15 );
// Restore the viewing transformation
glPopMatrix();

// Red Nucleus
glColor3ub( 255, 0, 0 );
glutSolidSphere( 10.0f, 15, 15 );

// White electron
glColor3ub( 255, 255, 255 );
// Second Electron Orbit
glPushMatrix();
glRotatef( fElect1, 0.0f, 0.0f, 1.0f );
glTranslatef( 80.0f, 0.0f, 0.0f );
glutSolidSphere( 6.0f, 15, 15 );
glPopMatrix();

// Purple electron
glColor3ub( 124, 75, 190 );
// Third Electron Orbit
glPushMatrix();
glRotatef( fElect1, 1.0f, 0.0f, 0.0f );
glTranslatef( 0.0f, 0.0f, -60.0f );
glutSolidSphere( 6.0f, 15, 15 );
glPopMatrix();

// Increment the angle of revolution
fElect1 += 0.5f;
if( fElect1 > 360.0f )	{ fElect1 = 0.0f; }

// Show the image
glutSwapBuffers();

}

/* This function does any needed initialization on the rendering context */

void SetupRC()	{

glEnable( GL_DEPTH_TEST );	// Hidden surface removal
//glFrontFace( GL_CCW );		// Counter clock-wise polygons face out
//glEnable( GL_CULL_FACE );	// Do not calculate inside of jet

// Black background
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );

}

/* Respond to arrow keys */

void SpecialKeys( int key, int x, int y )	{

if( key == GLUT_KEY_UP )	{ xRot-= 5.0f; }

if( key == GLUT_KEY_DOWN )	{ xRot += 5.0f; }

if( key == GLUT_KEY_LEFT )	{ yRot -= 5.0f; }

if( key == GLUT_KEY_RIGHT )	{ yRot += 5.0f; }

if( key > 356.0f )	{ xRot = 0.0f; }

if( key < -1.0f )	{ xRot = 355.0f; }

if( key > 356.0f )	{ yRot = 0.0f; }

if( key < -1.0f )	{ yRot = 355.0f; }

// Refresh the Window
glutPostRedisplay();

}

/* Timer function to refresh the screen for the given period */

void TimerFunc( int value )	{

glutPostRedisplay();
glutTimerFunc( 25, TimerFunc, 1 );

}

/* Window has changed size, recalculate projection */

void ChangeSize( int w, int h )	{

GLfloat nRange = 100.0f;

// Prevent a divide by zero
if(h == 0)	{ h = 1; }

// Set Viewport to window dimensions
glViewport( 0, 0, w, h );

// Reset coordinate system
glMatrixMode( GL_PROJECTION );

// Establish clipping volume (left, right, bottom, top, near, far)
if (w <= h)	{
glOrtho (-nRange, nRange, nRange*h/w, -nRange*h/w, -nRange*2.0f, nRange*2.0f);

} else {
glOrtho (-nRange*w/h, nRange*w/h, nRange, -nRange, -nRange*2.0f, nRange*2.0f);

}

// Reset Model View matrix stack
glMatrixMode(GL_MODELVIEW);

}

/* Main program entry point */

int main( int argc, char* argv[] )	{

glutInit( &argc, argv );
glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );
glutInitWindowSize( 800, 600 );
glutCreateWindow( "Atom2" );
glutReshapeFunc( ChangeSize );
glutSpecialFunc( SpecialKeys );
glutDisplayFunc( RenderScene );

glutTimerFunc( 500, TimerFunc, 1 );
SetupRC();
glutMainLoop();

return 0;

}

``````

This is probably due to the Y axis inversion in the projection matrix set by the glOrtho() function.

Bingo! That was exactly it. Thank you.