←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
v1[1] = center[1]+radius*sin(alpha);
for(i = 0; i <= sides; ++i) {
v2[0] = center[0]+radius*cos(alpha+i*TwoPI/sides);
v2[1] = center[1]+radius*sin(alpha+i*TwoPI/sides);
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;
drawNgon(c, radius, sides);
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);
glLoadIdentity();
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 lineglutInitDisplayMode(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?