Back to July Calendar 

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 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?