Tom Kelliher, CS 320
Feb. 23, 2011
Read polygon.c, Section 3.9.
Input devices and interaction introduction.
polygon.c
Display lists and distributed computing.
Idea:
Example:
void renderString(GLdouble x, GLdouble y, void *font, char *text)
{
glRasterPos2d(x, y);
while (text)
{
glutBitmapCharacter(font, *text);
++text;
}
}
See man page for glutBitmapCharacter for list of available bitmap
fonts. Example:
renderString(0.0, 0.0, GLUT_BITMAP_9_BY_15, "OpenGL rocks!");
Idea similar to font cache: display lists. Program example:
base = glGenLists(128);
for(i=0;i<128;i++)
{
glNewList(base+i, GL_COMPILE);
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, i);
glEndList();
}
glListBase(base);
Use:
// Dump time string into out. glRasterPos2i(ww-80, wh-15); // Window units = world units. glColor3f(0.0,0.0,0.0); glBegin(GL_QUADS); // Erase current time. glVertex2i(ww-80, wh-15); glVertex2i(ww, wh-15); glVertex2i(ww, wh); glVertex2i(ww-80, wh); glEnd(); glColor3f(1.0,1.0,1.0); glCallLists(strlen(out), GL_BYTE, out);Another example:
list = glGenLists(1)
glNewList(list, GL_COMPILE);
glBegin(GL_POLYGON);
glVertex2f(...);
...
glEnd();
glEndList();
...
glCallList(list);
Why do we use menus? -- What's the alternative?
int main(int argc, char** argv)
{
int c_menu;
/* ... */
c_menu = glutCreateMenu(color_menu);
glutAddMenuEntry("Black",0);
glutAddMenuEntry("Red",1);
glutAddMenuEntry("Green",2);
glutAddMenuEntry("Blue",3);
glutAddMenuEntry("Cyan",4);
glutAddMenuEntry("Magenta",5);
glutAddMenuEntry("Yellow",6);
glutAddMenuEntry("White",7);
glutCreateMenu(main_menu);
glutAddMenuEntry("new polygon", 1);
glutAddMenuEntry("end polygon", 2);
glutAddMenuEntry("delete polygon", 3);
glutAddMenuEntry("move polygon", 4);
glutAddMenuEntry("quit",5);
glutAddSubMenu("Colors", c_menu);
glutAttachMenu(GLUT_MIDDLE_BUTTON);
/* ... */
}
Polygon representation:
typedef struct polygon
{
int color; /* color index */
bool used; /* TRUE if polygon exists */
int xmin, xmax, ymin, ymax; /* bounding box */
float xc, yc; /* center of polygon */
int nvertices; /* number of vertices */
int x[MAX_VERTICES]; /* vertices */
int y[MAX_VERTICES];
} polygon;
Setting a polygon's color:
GLfloat colors[8][3]={{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0},
{0.0, 0.0, 1.0}, {0.0, 1.0, 1.0}, {1.0, 0.0, 1.0},
{1.0, 1.0, 0.0}, {1.0, 1.0, 1.0}};
void color_menu(int index)
{
present_color = index;
if(in_polygon>=0) polygons[in_polygon].color = index;
}
Rendering polygons:
void myDisplay()
{
/* display all active polygons */
int i, j;
glClear(GL_COLOR_BUFFER_BIT);
for(i=0; i<MAX_POLYGONS; i++)
{
if(polygons[i].used)
{
glColor3fv(colors[polygons[i].color]);
glBegin(GL_POLYGON);
for(j=0; j<polygons[i].nvertices; j++)
glVertex2i(polygons[i].x[j], polygons[i].y[j]);
glEnd();
}
}
glFlush();
}
Recall:
What's the problem here?
int pick_polygon(int x, int y)
{
/* find first polygon in which we are in bounding box */
int i;
for(i=0; i<MAX_POLYGONS; i++)
{
if(polygons[i].used)
if((x>=polygons[i].xmin) && (x<=polygons[i].xmax) &&
(y>=polygons[i].ymin)&&(y<polygons[i].ymax))
{
in_polygon = i;
moving = TRUE;
return(i);
}
printf("not in a polygon\n");
return(-1);
}
}
void main_menu(int index)
{
int i;
switch(index)
{
case(1): /* create a new polygon */
{
moving = FALSE;
for(i=0; i<MAX_POLYGONS; i++) if(polygons[i].used == FALSE) break;
if(i == MAX_POLYGONS)
{
printf("exceeeded maximum number of polygons\n");
exit(0);
}
polygons[i].color = present_color;
polygons[i].used = TRUE;
polygons[i].nvertices = 0;
in_polygon = i;
picking = FALSE;
break;
}
case(2): /* end polygon and find bounding box and center */
{
moving = FALSE;
if(in_polygon>=0)
{
polygons[in_polygon].xmax =
polygons[in_polygon].xmin =
polygons[in_polygon].x[0];
polygons[in_polygon].ymax =
polygons[in_polygon].ymin =
polygons[in_polygon].y[0];
polygons[in_polygon].xc = polygons[in_polygon].x[0];
polygons[in_polygon].yc = polygons[in_polygon].y[0];
for(i=1;i<polygons[in_polygon].nvertices;i++)
{
if(polygons[in_polygon].x[i]<polygons[in_polygon].xmin)
polygons[in_polygon].xmin =
polygons[in_polygon].x[i];
else if(polygons[in_polygon].x[i] >
polygons[in_polygon].xmax)
polygons[in_polygon].xmax =
polygons[in_polygon].x[i];
if(polygons[in_polygon].y[i]<polygons[in_polygon].ymin)
polygons[in_polygon].ymin =
polygons[in_polygon].y[i];
else if(polygons[in_polygon].y[i] >
polygons[in_polygon].ymax)
polygons[in_polygon].ymax =
polygons[in_polygon].y[i];
polygons[in_polygon].xc += polygons[in_polygon].x[i];
polygons[in_polygon].yc += polygons[in_polygon].y[i];
}
polygons[in_polygon].xc =
polygons[in_polygon].xc/polygons[in_polygon].nvertices;
polygons[in_polygon].yc =
polygons[in_polygon].yc/polygons[in_polygon].nvertices;
}
in_polygon = -1;
glutPostRedisplay();
break;
}
case(3): /* set picking mode */
{
picking = TRUE;
moving = FALSE;
break;
}
case(4): /* set moving mode */
{
moving = TRUE;
break;
}
case(5): /* exit */
{
exit(0);
break;
}
}
}