Previous Entry Next Entry→

July 21, 2005

Back to “Interaction and Animation,” chapter three, which I started about a week ago, before taking up more chapter 2 problems.

How about a rotating regular n-gon?

The coordinates of a regular n-gon inscribed in the unit circle are

where α is an arbitrary angle of rotation.  Continuously varying α will cause the regular n-gon to continuously rotate.

One way to animate is to increment this angle as part of the idle callback and then redisplay.  The idle callback function is glutIdleFunc(), is located in the main function, and executes whenever there are no other events to be handled. So here’s what I came up with for my first animated graphic:

/* Rotating Polygon */

#include <GL/glut.h>   // This includes gl.h and glu.h

#include <cmath>

#define TwoPI 6.283185307

GLfloat alpha = 0.0;  //rotation angle global

void drawNgon(GLfloat *center, GLfloat radius, GLfloat sides) {

GLfloat v1[2], v2[2];

double i;

v1[0] = center[0]+radius*cos(alpha); // position of first vertex

for(i = 0; i <= sides; ++i) {

glBegin(GL_LINES);

glColor3f(1.0-i/sides,i/sides,1.0);

glVertex2fv(v1);

glVertex2fv(v2);

glEnd();

v1[0] = v2[0];

v1[1] = v2[1];

} // end for

}

//Center and radius are also global and could be animated too

GLfloat c[2] = {0.0,0.0};

GLfloat radius = 1.0;  // inscribe in unit circle

void display(void) {

glClear(GL_COLOR_BUFFER_BIT);

GLfloat sides = 5.0;

glFlush();//replace with glutSwapBuffer() to eliminate flicker

}

void idle() {

alpha+=0.1;

if(alpha>TwoPI) alpha -= TwoPI;

glutPostRedisplay();

}

void init() {

//set clear color to white

glClearColor(1.0,1.0,1.0,1.0);

//set standard orthogonal (look straight at) clipping view

glMatrixMode(GL_PROJECTION);

gluOrtho2D(-1.1,1.1,-1.1,1.1);

}

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

//init mode and open window in upper-left corner

glutInit(&argc, argv);
// replace GLUT_SINGLE with GLUT_DOUBLE in the next line

glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

glutInitWindowSize(500,500);

glutInitWindowPosition(0,0);

glutCreateWindow("whimple");

glutDisplayFunc(display);

init();

glutIdleFunc(idle);

glutMainLoop();

}

 This resulted in a skittering, flickering sprite of uncertain shape.  A couple of captures grabbed images like the one shown at right. One fix for this skitterish behavior is double buffering, where two screen buffers are used, a front buffer for viewing and a back buffer for drawing. Actually, I observe that the rotation becomes much clearer if I simply slow it down by changing the alpha increment from 0.1 to 0.001, and that changing glFlush() to glutSwapBuffers() has no discernable effect…  Aha!  You need to change glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB) to glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB).  Making this change leads to a very slowly rotating very solid (not flickering) polygon.

How to do this in a way that could be communicated through the internet?  Well there’s Java, VRML (now X3D) and who knows what else?