Back to July Calendar  Previous Entry Next Entry→

July 7

 

Damn, well, the kids are still up and fussing with the laundry long after they should have gone sleepy-bye.

 

July 8, 2005

 

The following code uses the glRect*() function instead of glBegin/End() to draw a rectangle with the given corner coordinates.  It draws the interior of the rectangle red and the perimeter yellow, but, in fact, it doesn’t quite work.  I can see the figure if I resize the window, but only intermittently.  I wonder what’s going on?  Note the use of glPolygonOffset() which has to be enabled.  This is so the border is more clearly articulated—which it is, when you can see anything at all.

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

 

void square() {

      glRectf(-1.0,-1.0,1.0,1.0);

}

 

void display() {

      //clear window

      glClear(GL_COLOR_BUFFER_BIT);

      glPolygonOffset(1.0,1.0);

      glEnable(GL_POLYGON_OFFSET_LINE);

      glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

      glColor3f(1.0,0.0,0.0);

      square();

      glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

      glColor3f(1.0,1.0,0.0);

      square();

 

}

 

void init() {

      //set clear color to white

      glClearColor(1.0,1.0,1.0,1.0);

 

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

      //with cube of edge 3 centered at origin (default-could be omitted)

 

      glMatrixMode(GL_PROJECTION);

      glLoadIdentity();

      gluOrtho2D(-1.5,1.5,-1.5,1.5);

}

 

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

 

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

      glutInit(&argc, argv);

      glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

      glutInitWindowSize(500,500);

      glutInitWindowPosition(0,0);

      glutCreateWindow("thimple");

      glutDisplayFunc(display);

      init();

      glutMainLoop();

}

 

Interpolating Colors

 

As we’ve seen, (at least me and my eyeballs) when geometric primitives are formed by vertices of different colors, the colors in between these vertices are kind of rainbow which is the result of the default interpolation called smooth shading. 

 

You can change from this default to either GL_SMOOTH mode (the default) or GL_FLAT mode, which colors everything according to the color of the last vertex used in defining the primitive.  Trouble is, the program is still drawing intermittently.  I tried eliminating the glClear(GL_COLOR_BUFFER_BIT) command, but this just means it grabs whatever back ground was there and draws intermittently over that each time the window is resized, without clearing, leading to a, well, solid blue overlay of triangles from the following display function.

void display() {

      //clear window is deleted

      glColor3f(1.0,0.0,0.0);

      glShadeModel(GL_FLAT);

      glBegin(GL_TRIANGLES);

        glColor3f(0.5,0.5,1.0); 

        glVertex2f(1.0,0.0);    //left mid

        glColor3f(1.0,0.0,0.0);  //red

        glVertex2f(1.29,-0.71);  //upper left corner

        glColor3f(0.0,0.0,1.0);  //blue

        glVertex2f(-1.0,1.0);

      glEnd();

}

 

Aha!  Somehow I had deleted glFlush() after the last glEnd() and thus the intermittency.

 

One solution to the problem of non-convex and/or non-planar polygons is to dissect or tessellate the polygon into triangular pieces, each of which is necessarily convex and planar.  There is a bit of a hang when it comes to displaying the edges of such a polygon, especially if you want to see only the outer edges.  To specify which edges to show, you use the function glEdgeFlag*().  If the flag is set to GL_TRUE, each vertex is considered to be the beginning of a segment to be displayed, or not, if the flag is set to GL_FALSE.  There is also something called the tessellator, which involves a number of other functions, so we’ll look at it later.

 

Ok, here’s a nifty little function Angel outlines for using recursion to produce something like sequence of nested triangles. 

 

Note

  • use of the vector forms glVertexfv, etc.
  • recursion has base case as an “else.”
  •  Each of the 4 subtriangles is divided recursively, including the middle one.
  • As is usual with recursion, it’s a slick way to construct the program, but it leaves a lot of dangling function calls, potentially hogging a lot of memory. Here n = 4, and we’re getting 120 triangles.  Geese, why so many?
  • Why are half the triangles solid?

 

/* source1 - From Angel's OpenGL Primer */

 

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

 

void triangle(GLfloat *a, GLfloat *b, GLfloat *c) {

      glBegin(GL_TRIANGLES);

        glVertex2fv(a);

        glVertex2fv(b);

        glVertex2fv(c);

      glEnd();

}

 

void divide_triangle(GLfloat *a, GLfloat *b, GLfloat *c, int m) {

      //Start with a triangle and recursively subdivide it m times

      GLfloat v[3][2];  //starting triangle

      int j;

      if(m>0) {

            for(j=0;j<2;j++) v[0][j] = (a[j] + b[j])/2;

            for(j=0;j<2;j++) v[1][j] = (a[j] + c[j])/2;

            for(j=0;j<2;j++) v[2][j] = (c[j] + b[j])/2;

            divide_triangle(a, v[0], v[1], m-1);                 

            divide_triangle(v[0], b, v[2], m-1);

            divide_triangle(v[1], v[2], c, m-1);

            divide_triangle(v[0], v[1], v[2], m-1);

      }

      else triangle(a,b,c);

}

 

void init() {

      glClearColor(1.0,1.0,1.0,1.0);

      glMatrixMode(GL_PROJECTION);

      glLoadIdentity();

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

}

 

//We generate 4n triangles with this callback

GLfloat v[3][2] = {{-1,-1},{1,-1},{0,0.866}};

void display(void) {

      glClear(GL_COLOR_BUFFER_BIT);

      glPolygonMode(GL_FRONT, GL_LINE);

      int n = 4;

      glColor3f(1.0, 0.0, 0.0);

      divide_triangle(v[0], v[1], v[2], n);    

      glFlush(); // don't forget to flush!

}

 

 

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

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

      glutInit(&argc, argv);

      glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

      glutInitWindowSize(500,500);

      glutInitWindowPosition(0,0);

      glutCreateWindow("whimple");

      glutDisplayFunc(display);

      init();

      glutMainLoop();

}

 

This is great!  There’re a lot of variations on this that come to mind, but let’s plod on.

 

Angel now goes into detail on the possible edge flag situations and how to set this up so that we only show the outer perimeter of the whole collection.  There are 23 = 8 ways for each of the 3 sides of a triangle to be either GL_TRUE or GL_FALSE.  Angel proposes simply (the old plough approach) writing cases for each of these