Tom Kelliher, CS 320
Mar. 29, 2000
Project 1 due in one week. Written final?
Read paint.c.
Projections.
Dealing with window resizing: viewports, aspect ratios.
Continuing interactive graphics.
The aspect ratio's of the clipping rectangle and viewing window should match. Otherwise, distortion results.
void glViewport(GLint x, GLint y, GLsizei w, GLsizei h);where , is the lower-left corner of the viewport, and w and h are its width and height, respectively.
Example. Assume you have a viewing window:
glViewport(100, 100, 50, 50)This sets the viewport to the upper righthand quarter of the viewing window.
glutInitWindowSize(gww, gwh);But, the user can resize the window at will.
#define WINDOW_WIDTH 200 #define WINDOW_HEIGHT 200 void reshape(int, int); int maintainAspectRatio = 1; int gww = WINDOW_WIDTH; int gwh = WINDOW_HEIGHT; int main() { /* ... */ glutInitWindowSize(gww, gwh); glutReshapeFunc(reshape); /* ... */ } void reshape(int w, int h) { if (maintainAspectRatio) gww = gwh = (w < h) ? w : h; /* aspect ratio = 1 */ else { gww = w; gwh = h; } }
Points to note:
Note the overlap and observe the result.
The user could easily write a small function to position and render strings.
int main() { // ... c_menu = glutCreateMenu(color_menu); glutAddMenuEntry("Red",1); glutAddMenuEntry("Green",2); glutAddMenuEntry("Blue",3); glutAddMenuEntry("Cyan",4); glutAddMenuEntry("Magenta",5); glutAddMenuEntry("Yellow",6); glutAddMenuEntry("White",7); glutAddMenuEntry("Black",8); p_menu = glutCreateMenu(pixel_menu); glutAddMenuEntry("increase pixel size", 1); glutAddMenuEntry("decrease pixel size", 2); f_menu = glutCreateMenu(fill_menu); glutAddMenuEntry("fill on", 1); glutAddMenuEntry("fill off", 2); glutCreateMenu(right_menu); glutAddSubMenu("Colors", c_menu); glutAddSubMenu("Pixel Size", p_menu); glutAddSubMenu("Fill", f_menu); glutAddMenuEntry("clear",2); glutAddMenuEntry("quit",1); glutAttachMenu(GLUT_RIGHT_BUTTON); // ... } void color_menu(int id) { glutIdleFunc(NULL); if(id == 1) {r = 1.0; g = 0.0; b = 0.0;} else if(id == 2) {r = 0.0; g = 1.0; b = 0.0;} else if(id == 3) {r = 0.0; g = 0.0; b = 1.0;} else if(id == 4) {r = 0.0; g = 1.0; b = 1.0;} else if(id == 5) {r = 1.0; g = 0.0; b = 1.0;} else if(id == 6) {r = 1.0; g = 1.0; b = 0.0;} else if(id == 7) {r = 1.0; g = 1.0; b = 1.0;} else if(id == 8) {r = 0.0; g = 0.0; b = 0.0;} glutIdleFunc(idle); }
int pick(int x, int y) { y = wh - y; if(y < wh-ww/10) return 0; else if(x < ww/10) return 1; else if(x < ww/5) return 2; else if(x < 3*ww/10) return 3; else if(x < 2*ww/5) return 4; else return 0; } void mouse(int btn, int state, int x, int y) { static int draw_mode = 0; /* drawing mode */ static int count; int where; static int xp[2],yp[2]; if(btn==GLUT_LEFT_BUTTON && state==GLUT_DOWN) { glPushAttrib(GL_ALL_ATTRIB_BITS); glutIdleFunc(NULL); where = pick(x,y); glColor3f(r, g, b); if(where != 0) { count = 0; draw_mode = where; } else if(draw_mode == 1 && count == 0) { count = 1; xp[0] = x; yp[0] = y; } else if(draw_mode == 1 && count != 0) { glBegin(GL_LINES); glVertex2i(x,wh-y); glVertex2i(xp[0],wh-yp[0]); glEnd(); draw_mode=0; count=0; } else if(draw_mode == 2 && count == 0) { count = 1; xp[0] = x; yp[0] = y; } else if(draw_mode == 2 && count != 0) { if(fill) glBegin(GL_POLYGON); else glBegin(GL_LINE_LOOP); glVertex2i(x,wh-y); glVertex2i(x,wh-yp[0]); glVertex2i(xp[0],wh-yp[0]); glVertex2i(xp[0],wh-y); glEnd(); draw_mode=0; count=0; } else if(draw_mode == 3 && count == 0) { count = 1; xp[0] = x; yp[0] = y; } else if(draw_mode == 3 && count == 1) { count = 2; xp[1] = x; yp[1] = y; } else if(draw_mode == 3 && count == 2) { if(fill) glBegin(GL_POLYGON); else glBegin(GL_LINE_LOOP); glVertex2i(xp[0],wh-yp[0]); glVertex2i(xp[1],wh-yp[1]); glVertex2i(x,wh-y); glEnd(); draw_mode=0; count=0; } else if(draw_mode == 4 ) { drawSquare(x,y); count++; } glutIdleFunc(idle); glPopAttrib(); glFlush(); } }
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.
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); glColor3f(0.0,0.0,0.0); glBegin(GL_QUADS); 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);