#include #include #include #include #include #include #include GLdouble PI; GLint MAXDEPTH = 4; GLdouble RADIUS = 0.95; char pict_fname[] = "l1.1.ppm"; char image_fname[] = "l1.ppm"; GLint line_width = 1; GLint texture = 0; GLint texture_stipple = 0; GLint stipple = 0; GLint axes = 0; GLint fill = 0; GLint diagonals = 0; GLfloat blue[3] = {0.0, 0.0, 1.0}; GLfloat white[3] = {1.0, 1.0, 1.0}; GLfloat gray[3] = {0.5, 0.5, 0.5}; GLubyte mask[] = { 0xA0, 0xA0, 0xA0, 0xA0, 0xFF, 0xFF, 0xFF, 0xFF, 0xA0, 0xA0, 0xA0, 0xA0, 0xFF, 0xFF, 0xFF, 0xFF, 0xA0, 0xA0, 0xA0, 0xA0, 0xFF, 0xFF, 0xFF, 0xFF, 0xA0, 0xA0, 0xA0, 0xA0, 0xFF, 0xFF, 0xFF, 0xFF, 0xA0, 0xA0, 0xA0, 0xA0, 0xFF, 0xFF, 0xFF, 0xFF, 0xA0, 0xA0, 0xA0, 0xA0, 0xFF, 0xFF, 0xFF, 0xFF, 0xA0, 0xA0, 0xA0, 0xA0, 0xFF, 0xFF, 0xFF, 0xFF, 0xA0, 0xA0, 0xA0, 0xA0, 0xFF, 0xFF, 0xFF, 0xFF, 0xA0, 0xA0, 0xA0, 0xA0, 0xFF, 0xFF, 0xFF, 0xFF, 0xA0, 0xA0, 0xA0, 0xA0, 0xFF, 0xFF, 0xFF, 0xFF, 0xA0, 0xA0, 0xA0, 0xA0, 0xFF, 0xFF, 0xFF, 0xFF, 0xA0, 0xA0, 0xA0, 0xA0, 0xFF, 0xFF, 0xFF, 0xFF, 0xA0, 0xA0, 0xA0, 0xA0, 0xFF, 0xFF, 0xFF, 0xFF, 0xA0, 0xA0, 0xA0, 0xA0, 0xFF, 0xFF, 0xFF, 0xFF, 0xA0, 0xA0, 0xA0, 0xA0, 0xFF, 0xFF, 0xFF, 0xFF, 0xA0, 0xA0, 0xA0, 0xA0, 0xFF, 0xFF, 0xFF, 0xFF}; GLubyte picture_mask[128]; int imageWidth, imageHeight; static GLubyte *myimage; static GLuint texname; void drawPoly(GLint crtdepth, GLdouble R, GLint hide); void drawAxes(); /* reads myimage */ void readImage(char* image_fname) { FILE* fp; GLuint red, blue, green, i,j; char junk[81]; if ((fp = fopen(image_fname, "r")) == NULL) { fprintf(stderr,"readImage:cannot open image file..\n"); return; } /* read size */ fgets(junk, 80, fp); fgets(junk, 80, fp); fscanf(fp,"%d %d", &imageHeight, &imageWidth); printf("%d %d\n", imageHeight, imageWidth); fscanf(fp,"%d", junk); /* allocate image */ if ((myimage = (GLubyte*)(malloc(4*imageWidth*imageHeight*sizeof(GLubyte)))) == NULL) { fprintf(stderr,"readImage:cannot allocate image..\n"); return; } for (i=0;i 90) { bit[k++] = 1; } else { bit[k++] = 0; } if (k==8) { val = bit[0]*128 + bit[1]*64 + bit[2]*32 + bit[3]*16 + bit[4]*8 + bit[5]*4 + bit[6]*2 + bit[7]; picture_mask[l++] = val; k = 0; } } } fclose(fp); } void init(){ glClearColor(0, 0, 0, 0); /* Background color = Black*/ glShadeModel(GL_SMOOTH); /* Smooth shading */ PI = 2 * asin(1); /* texture stuff */ glEnable(GL_DEPTH_TEST); readImage(image_fname); glPixelStorei(GL_UNPACK_ALIGNMENT,1); glGenTextures(1,&texname); glBindTexture(GL_TEXTURE_2D, texname); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA, imageWidth, imageHeight, 0,GL_RGBA, GL_UNSIGNED_BYTE, myimage); /* image stippled */ readPictureMask(pict_fname); } void polar(GLdouble r, GLdouble fi, GLdouble* v) { v[0] = r * cos(fi); v[1] = r * sin(fi); } void rotateDrawPoly(GLdouble r, GLdouble fi, GLint crtdepth, GLdouble crtrad, GLint hide) { GLdouble t[2]; double rot; rot = (fi)*180/PI; /* translate origin: r, fi */ polar(r, fi, t); glTranslated(t[0], t[1], 0); glRotated(rot,0,0,1); drawPoly(crtdepth, crtrad, hide); /* translate origin: -r, -fi */ glRotated(-rot,0,0,1); glTranslated(-t[0], -t[1], 0); } #define FLOOR(x) ((GLint)(x)) void myglVertex2dv(GLdouble* v) { if (texture) { glTexCoord2d(-v[0]*3, -v[1]*3); } glVertex2dv(v); } void drawPoly(GLint crtdepth, GLdouble R, GLint showdiag) { GLint i; GLdouble point[3][2], a[6][2], b[3][2], r1; /* if showdiag enable stippled lines */ if (showdiag) { glEnable(GL_LINE_STIPPLE); glLineStipple(1, 0x3333); /* glLineWidth(6); */ } else { glDisable(GL_LINE_STIPPLE); glLineWidth(line_width); } for (i=0 ; i<3; i++) { polar(R, i*2*PI/3, point[i]); } if (crtdepth == MAXDEPTH) { /* this is last triangle: draw it complete */ if (!showdiag) { /* dont show hidden lines */ glBegin(GL_POLYGON); glColor3fv(blue); myglVertex2dv(point[0]); /* draw edge 2 if only single triangle */ if(crtdepth) { glEdgeFlag(GL_FALSE); } glColor3fv(white); myglVertex2dv(point[1]); if(crtdepth){ glEdgeFlag(GL_TRUE); } glColor3fv(gray); myglVertex2dv(point[2]); glEnd(); } else { /* show only hidden lines */ /* nothing to show */ } } else { /* not max depth */ /* generate a[i] and b[i] */ r1 = R/sqrt(3); for (i=0; i<6; i++) { polar(r1, 2*PI/3*FLOOR(i/2) + PI/6*((i%2)*2+1), a[i]); } for (i=0; i<3; i++) { polar(R, PI/3 + 2*PI/3*i, b[i]); } /* draw polygon v0-->a0; a1-->v1 */ glBegin(GL_POLYGON); glColor3fv(blue); glEdgeFlag(showdiag?GL_FALSE:GL_TRUE); myglVertex2dv(point[0]); glEdgeFlag(showdiag?GL_TRUE:GL_FALSE); glColor3fv(gray); myglVertex2dv(a[0]); glEdgeFlag(showdiag?GL_FALSE:GL_TRUE); glColor3fv(white); myglVertex2dv(a[1]); if(crtdepth) { glEdgeFlag(showdiag?GL_TRUE:GL_FALSE); glColor3fv(white); myglVertex2dv(point[1]); glEdgeFlag(showdiag?GL_FALSE:GL_TRUE); } else { glColor3fv(white); glEdgeFlag(showdiag?GL_FALSE:GL_TRUE); myglVertex2dv(point[1]); glEdgeFlag(showdiag?GL_TRUE:GL_FALSE); glColor3fv(white); myglVertex2dv(a[2]); glEdgeFlag(showdiag?GL_FALSE:GL_TRUE); glColor3fv(blue); myglVertex2dv(a[3]); glEdgeFlag(showdiag?GL_FALSE:GL_TRUE); } glColor3fv(gray); myglVertex2dv(point[2]); glEdgeFlag(showdiag?GL_TRUE:GL_FALSE); glColor3fv(gray); myglVertex2dv(a[4]); glEdgeFlag(showdiag?GL_FALSE:GL_TRUE); glColor3fv(white); myglVertex2dv(a[5]); glEnd(); /* recursive calls */ /* translate origin: 2*R/3, PI/3) */ rotateDrawPoly(2*R/3, PI/3, crtdepth+1, R/3, showdiag); /* translate origin: 2*R/3, PI) */ if (crtdepth == 0) { /* need three small triangles for initial case only */ rotateDrawPoly(2*R/3, PI, crtdepth+1, R/3, showdiag); } /* translate origin: 2*R/3, -PI/3) */ rotateDrawPoly(2*R/3, -PI/3, crtdepth+1, R/3, showdiag); } /* else crtdepth == MAXDEPTH */ } void drawDiagonals(GLint crtdepth, GLdouble R, GLint showdiag) { GLint i; GLdouble point[3][2], a[6][2], b[3][2], r1; /* if !hide enable stippled lines */ if (showdiag) { glEnable(GL_LINE_STIPPLE); glLineStipple(2, 0xAAA); } else { glDisable(GL_LINE_STIPPLE); } for (i=0 ; i<3; i++) { polar(R, i*2*PI/3, point[i]); } if (crtdepth == MAXDEPTH) { /* draw a complete triangle */ glBegin(GL_POLYGON); glColor3fv(blue); myglVertex2dv(point[0]); /* draw edge 2 if only single triangle */ if(crtdepth) glEdgeFlag(GL_FALSE); glColor3fv(white); myglVertex2dv(point[1]); if(crtdepth) glEdgeFlag(GL_TRUE); glColor3fv(gray); myglVertex2dv(point[2]); glEnd(); } else { /* generate a[i] and b[i] */ r1 = R/sqrt(3); for (i=0; i<6; i++) { polar(r1, 2*PI/3*FLOOR(i/2) + PI/6*((i%2)*2+1), a[i]); } for (i=0; i<3; i++) { polar(R, PI/3 + 2*PI/3*i, b[i]); } /* draw polygon v0-->a0; a1-->v1 */ glBegin(GL_POLYGON); glColor3fv(blue); myglVertex2dv(point[0]); glEdgeFlag(GL_FALSE); glColor3fv(gray); myglVertex2dv(a[0]); glEdgeFlag(GL_TRUE); glColor3fv(white); myglVertex2dv(a[1]); glColor3fv(white); if(crtdepth) { glEdgeFlag(GL_FALSE); myglVertex2dv(point[1]); glEdgeFlag(GL_TRUE); } else { myglVertex2dv(point[1]); glEdgeFlag(GL_FALSE); glColor3fv(white); myglVertex2dv(a[2]); glEdgeFlag(GL_TRUE); glColor3fv(blue); myglVertex2dv(a[3]); } glColor3fv(gray); myglVertex2dv(point[2]); glEdgeFlag(GL_FALSE); glColor3fv(gray); myglVertex2dv(a[4]); glEdgeFlag(GL_TRUE); glColor3fv(white); myglVertex2dv(a[5]); glEnd(); /* recursive calls */ /* translate origin: 2*R/3, PI/3) */ rotateDrawPoly(2*R/3, PI/3, crtdepth+1, R/3, showdiag); /* translate origin: 2*R/3, PI) */ if (crtdepth == 0) { /* need three small triangles for initial case only */ rotateDrawPoly(2*R/3, PI, crtdepth+1, R/3, showdiag); } /* translate origin: 2*R/3, -PI/3) */ rotateDrawPoly(2*R/3, -PI/3, crtdepth+1, R/3, showdiag); } /* else crtdepth == MAXDEPTH */ } void drawAxes() { glBegin(GL_LINES); glColor3f(1,1,1); glVertex2i(-1,0); glVertex2i(1,0); glVertex2i(0,1); glVertex2i(0,-1); glEnd(); } void display(void) { glClear(GL_COLOR_BUFFER_BIT); /* Set the background color */ /* draw poly level 0 */ if (!texture) { glDisable(GL_TEXTURE_2D); } else { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); glBindTexture(GL_TEXTURE_2D, texname); } if (diagonals) { /* show all lines stippled */ drawPoly(0, RADIUS, 1); } /* dont show diagonals */ drawPoly(0,RADIUS, 0); if (axes) drawAxes(); glFlush(); } void main_menu(int value) { switch (value){ case 1: /* toggle diagonals */ diagonals = !diagonals; break; case 2: /* toggle axes */ axes = !axes; break; case 3: exit(0); } glutPostRedisplay(); } void width_menu(int value) { switch (value){ case 1: line_width = 1; break; case 2: line_width = 2; break; } glLineWidth(line_width); glutPostRedisplay(); } void fill_menu(int value) { switch (value){ case 1: /* outline */ fill = texture = stipple = texture_stipple = 0; glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break; case 2: /* fill */ fill = 1; texture = stipple = texture_stipple = 0; glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glDisable(GL_POLYGON_STIPPLE); break; case 3: /* stipple */ stipple = 1; fill = texture = texture_stipple = 0; glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glEnable(GL_POLYGON_STIPPLE); glPolygonStipple(mask); break; case 4: /* texture - stipple*/ texture_stipple =1 ; fill = stipple = texture = 0; glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glEnable(GL_POLYGON_STIPPLE); glPolygonStipple(picture_mask); break; case 5: /* texture - texture */ texture = 1 ; fill = stipple = texture_stipple = 0; glDisable(GL_POLYGON_STIPPLE); break; } glutPostRedisplay(); } int main(int argc, char **argv) { int width_menu_id, fill_menu_id; glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(500, 500); glutInitWindowPosition(100,100); glutCreateWindow(argv[0]); init(); glutDisplayFunc(display); glutCreateMenu(width_menu); width_menu_id = glutGetMenu(); glutAddMenuEntry("1 pixel", 1); glutAddMenuEntry("2 pixels", 2); glutCreateMenu(fill_menu); fill_menu_id = glutGetMenu(); glutAddMenuEntry("Outline", 1); glutAddMenuEntry("Fill", 2); glutAddMenuEntry("Stipple", 3); glutAddMenuEntry("Image/stipple", 4); glutAddMenuEntry("Image/texture", 5); glutCreateMenu(main_menu); glutAddSubMenu("Line width", width_menu_id); glutAddSubMenu("Polygon", fill_menu_id); glutAddMenuEntry("Show/hide diag", 1); glutAddMenuEntry("Show/hide axes", 2); glutAddMenuEntry("Quit", 3); glutAttachMenu(GLUT_RIGHT_BUTTON); glutMainLoop(); return 0; }