/* * draw a polygon; in this case something like a fan */ #include #include #include #include #ifdef __APPLE__ #include #else #include #endif /* globals are evil */ int nfins = 16; GLfloat maj = 0.8; GLfloat min = 0.4; /* colors for the vertices */ GLfloat cols[2][4][3] = {{{0.0, 0.0, 0.5}, {0.5, 1.0, 0.9}, {0.5, 0.5, 1.0}, {0.9 ,0.6, 0.9}}, {{0.0, 0.0, 0.5}, {0.9, 1.0, 1.0}, {1.0, 1.0, 0.0}, {1.0, 0.5, 0.5}}}; int colset=0; GLubyte stipple_mask[32*32/8]; #define NUMTEX 6 /* exact number of textures */ char *texFiles[] = {"gray-swirls.ppm", "b002.ppm", "b009.ppm", "b001.ppm", "blue-texture.ppm", "blue-green-hexes.ppm"}; int texScale[NUMTEX]; /* number of tiles (linearly) - should be 1 if it's a picture, and not a real texture */ GLuint texNames[NUMTEX]; /* hooks for the textures */ int texCurr=0; /* current texture */ int flag_texture=0; /* textures on */ int flag_stipple=0; /* stipple on */ int flag_axes = 0; /* show axes */ int flag_diagonals = 0; /* show diagonals */ int param_width = 1; /* line width */ /* ********************************************************************** */ /* check whether n is a power of 2 */ int is2pow(int n) { while(!(n&1)) { n = n >> 1; } return (n==1); } /* change the coordinates from (-1,1) to (1,0) to place the imagemap properly. * use the scale to tile many images. */ float tex_coord(float n) { return 1 - (n+1)/2 * texScale[texCurr]; } /* read in a ppm(ascii) file */ int load_image(char *file, GLubyte **map, GLuint *width, GLuint *height) { FILE *fp; char buf[BUFSIZ]; unsigned int i,j,k; GLuint n; fp = fopen(file, "r"); if(!fp) { perror("open"); exit(1); } fgets(buf, BUFSIZ, fp); /* skip header (P3) */ fgets(buf, BUFSIZ, fp); /* skip comment(s) */ while(buf[0] == '#') { fgets(buf, BUFSIZ, fp); } sscanf(buf, "%d%d", width, height); fgets(buf, BUFSIZ, fp); if(!is2pow(*width) || !is2pow(*height)) { printf("bad image: %s\n", file); exit(1); } if(*map) { free(*map); /* cleanup old image */ } *map = (GLubyte *)calloc(*height * *width * 4, sizeof(GLubyte)); assert(*map); /* read in data */ for(i=0; i< *height; i++) { for(j=0; j< *width; j++) { for(k=0;k<3;k++) { fscanf(fp, "%d", &n); (*map)[(i* *width+j)*4+k] = (GLubyte)n; } (*map)[(i* *width+j)*4+3]= (GLubyte)255; } } fclose(fp); return 0; } void init(){ int i, j, k, n; GLubyte *texmap = NULL; GLuint texmapHeight; GLuint texmapWidth; /* load & setup the texture maps, assume we have space etc.. */ glPixelStorei(GL_UNPACK_ALIGNMENT, 1); for(i=0;i= 32); assert(texmapHeight >= 32); for(i=0; i<32; i++) { for(j=0; j<32/8; j++) { for(k=0; k<8; k++) { n = (texmap[(i * texmapWidth + j*8+k)*4 + 0] + texmap[(i * texmapWidth + j*8+k)*4 + 1] + texmap[(i * texmapWidth + j*8+k)*4 + 2])/3; stipple_mask[i*32/8 + j] |= (n>100?1:0) << (8-k); } } } glPolygonStipple(stipple_mask); glClearColor(0, 0, 0, 0); /* Background color = Black*/ glShadeModel(GL_SMOOTH); glEnable(GL_DEPTH_TEST); glLineStipple(1, 0xCCCC); } /* ********************************************************************** */ /* drawing functions */ /* figure out the coordinates for the circle at step i */ void circle_coords(GLfloat *x, GLfloat *y, GLfloat rad, GLfloat i) { /* the final number of steps is global :( */ GLfloat step = (GLfloat)asin(1)*4/(nfins); GLfloat t = step * i; *x = rad * cos(t); *y = rad * sin(t); } /* compute the outline coords for our figure * 1 step corresponds to 1 fin, so we need to adjust i */ void compute_coords(GLfloat *x, GLfloat *y, int i, int j) { switch(j) { case 0: /* leading (smaller theta) inner */ circle_coords(x, y, min, i+0.5); break; case 1: /* leading outer */ circle_coords(x, y, maj, i+0.5); break; case 2: /* trailing outer */ circle_coords(x, y, maj, i+1); break; case 3: /* trailing inner */ circle_coords(x, y, min, i+1); break; } } void draw_axes2D(void) { glLineWidth(1); /* draw x,y axes */ glBegin(GL_LINES); { glColor3f(1, 1, 1); glVertex2f(-1, 0); glVertex2f(1, 0); glVertex2f(0, -1); glVertex2f(0, 1); } glEnd(); } void draw_axes3D(void) { glLineWidth(1); #ifdef SOUP /* draw axes as planes */ glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBegin(GL_QUADS); { glColor4f(0.5, 0.5, 0.0, 0.5); glVertex3f(-1, 0, -1); glVertex3f(1, 0, -1); glVertex3f(1, 0, 1); glVertex3f(-1, 0, 1); glColor4f(0.1, 0.1, 0.7, 0.5); glVertex3f(0, -1, -1); glVertex3f(0, 1, -1); glVertex3f(0, 1, 1); glVertex3f(0, -1, 1); glColor4f(1.0, 0.0, 0.0, 0.3); glVertex3f(-1, -1, 0); glVertex3f(1, -1, 0); glVertex3f(1, 1, 0); glVertex3f(-1, 1, 0); } glEnd(); /* draw x,y axes */ glBegin(GL_LINES); { glColor3f(1, 1, 1); glVertex3f(-1, 0, 0); glVertex3f( 1, 0, 0); glVertex3f(0, -1, 0); glVertex3f( 0, 1, 0); } glEnd(); #endif /* draw x,y axes, but in front of x-y plane */ glBegin(GL_LINES); { glColor3f(1, 1, 1); glVertex3f(-1, 0, -0.2); glVertex3f( 1, 0, -0.2); glVertex3f(0, -1, -0.2); glVertex3f( 0, 1, -0.2); #if(0) glColor3f(1, 1, 1); glVertex2f(-1, 0); glVertex2f(1, 0); glVertex2f(0, -1); glVertex2f(0, 1); #endif } glEnd(); } void draw_axes(void) { #if(0) draw_axes3D(); #endif draw_axes2D(); } /* draw the inner part of the polygon, with or without diagonals */ void draw_inside(int diagonals) { int i,j; GLfloat x, y; glBegin(GL_QUADS); glEdgeFlag(GL_TRUE); for(i=0;i0)?GL_FALSE:GL_TRUE); circle_coords(&x, &y, min, i+j/2.0); glColor3fv(cols[colset][(j-1?3:0)]); glTexCoord2f(tex_coord(x), tex_coord(y)); glVertex2f(x, y); } glEdgeFlag(GL_FALSE); glColor3fv(cols[colset][1]); glTexCoord2f(tex_coord(0), tex_coord(0)); glVertex2f(0, 0); } glEnd(); } void display(void) { int i,j; GLfloat x, y; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLineWidth(param_width); if(flag_stipple) glEnable(GL_POLYGON_STIPPLE); if(flag_texture) { glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texNames[texCurr]); } /* draw the outer polygons (the fins) */ glBegin(GL_QUADS); for(i=0; i': nfins += 4; /* fall to next */ case '.': nfins++; glutPostRedisplay(); break; case '<': nfins -= 4; /* fall to next */ case ',': nfins--; if(nfins<2) nfins = 2; glutPostRedisplay(); break; case 'q': exit(0); break; } } /* ********************************************************************** */ /* main */ int main(int argc, char **argv) { int width_menu_id, fill_menu_id, tex_menu_id; int i; glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(500, 500); glutInitWindowPosition(100,100); glutCreateWindow(argv[0]); init(); glutDisplayFunc(display); glutCreateMenu(tex_menu); tex_menu_id = glutGetMenu(); for(i=0;i