/* Abe Grief, 351-66-3167, abey@cs.ucr.edu, cs130 */ /* Recursive subdivision of cube (Chapter 6). Three display modes: wire frame, constant, and interpolative shading */ /*Program also illustrates defining materials and light sources in myiit() */ /* mode 0 = wire frame, mode 1 = constant shading, mode 3 = interpolative shading */ #include #include #include #define X .525731112119133606 #define Z .850650808352039932 typedef float point[4]; /* initial tetrahedron */ point v[]={{0.0, 0.0, 1.0}, {0.0, 0.942809, -0.33333}, {-0.816497, -0.471405, -0.333333}, {0.816497, -0.471405, -0.333333}}; static GLfloat theta[] = {0.0,0.0,0.0}; int mode; /* initial icosahedron, coordinates were given in handout */ static GLfloat vdata[12][3] = { {-X, 0.0, Z}, {X, 0.0, Z}, {-X, 0.0, -Z}, {X, 0.0, -Z}, {0.0, Z, X}, {0.0, Z, -X}, {0.0, -Z, X}, {0.0, -Z, -X}, {Z, X, 0.0}, {-Z, X, 0.0}, {Z, -X, 0.0}, {-Z, -X, 0.0} }; static GLuint tindices[20][3] = { {0, 4, 1}, {0, 9, 4}, {9, 5, 4}, {4, 5, 8}, {4, 8, 1}, {8, 10, 1}, {8, 3, 10}, {5, 3, 8}, {5, 2, 3}, {2, 7, 3}, {7, 10, 3}, {7, 6, 10}, {7, 11, 6}, {11, 0, 6}, {0, 1, 6}, {6, 1, 10}, {9, 0, 11}, {9, 11, 2}, {9, 2, 5}, {7, 2, 11} }; void triangle( point a, point b, point c) /* display one triangle using a line loop for wire frame, a single normal for constant shading, or three normals for interpolative shading */ { if (mode==0) glBegin(GL_LINE_LOOP); else glBegin(GL_POLYGON); if(mode==1) glNormal3fv(a); if(mode==2) glNormal3fv(a); glVertex3fv(a); if(mode==2) glNormal3fv(b); glVertex3fv(b); if(mode==2) glNormal3fv(c); glVertex3fv(c); glEnd(); } /* normalize a vector by making its length one */ void normal(point p) { float d =0.0; int i; for(i=0; i<3; i++) d+=p[i]*p[i]; d=sqrt(d); if(d>0.0) for(i=0; i<3; i++) p[i]/=d; } /* triangle subdivision using vertex numbers righthand rule applied to create outward pointing faces */ void divide_triangle(point a, point b, point c, int m) { point v1, v2, v3; int j; /* subdivide triangle until no more subdivisions are necessary */ if(m>0) { for(j=0; j<3; j++) v1[j]=a[j]+b[j]; normal(v1); for(j=0; j<3; j++) v2[j]=a[j]+c[j]; normal(v2); for(j=0; j<3; j++) v3[j]=b[j]+c[j]; normal(v3); divide_triangle(a, v1, v2, m-1); divide_triangle(c, v2, v3, m-1); divide_triangle(b, v3, v1, m-1); divide_triangle(v1, v3, v2, m-1); } else(triangle(a,b,c)); /* draw triangle at end of recursion */ } /* Apply triangle subdivision to faces of tetrahedron */ void tetrahedron( int m) { /* there are 4 triangular faces in a tetrahedron, so 4 faces to divide */ divide_triangle(v[0], v[1], v[2], m); divide_triangle(v[3], v[2], v[1], m); divide_triangle(v[0], v[3], v[1], m); divide_triangle(v[0], v[2], v[3], m); } /* Displays an icosahedron, and 5 tetrahedron subdivided to different levels.*/ void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); /* move the icosahedron near the top */ glTranslatef(0.0, 2.5, 0.0); /* draw the icosahedron */ glBegin(GL_TRIANGLES); for(int i = 0; i < 20; i++) { glNormal3fv(&vdata[tindices[i][0]][0]); glVertex3fv(&vdata[tindices[i][0]][0]); glNormal3fv(&vdata[tindices[i][1]][0]); glVertex3fv(&vdata[tindices[i][1]][0]); glNormal3fv(&vdata[tindices[i][2]][0]); glVertex3fv(&vdata[tindices[i][2]][0]); } glEnd(); /* draw 5 different tetrahedron, each to different levels of subdivision, and placing them nicely on the screen */ mode = 2; /* what style of drawing we're using */ glTranslatef(-5.0, -4.0, 0.0); tetrahedron(0); glTranslatef(2.5, 0.0, 0.0); tetrahedron(1); glTranslatef(2.5, 0.0, 0.0); tetrahedron(2); glTranslatef(2.5, 0.0, 0.0); tetrahedron(3); glTranslatef(2.5, 0.0, 0.0); tetrahedron(4); glFlush(); } /* set some important settings before drawing, given to me by example */ void myReshape(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w <= h) glOrtho(-4.0, 4.0, -4.0 * (GLfloat) h / (GLfloat) w, 4.0 * (GLfloat) h / (GLfloat) w, -10.0, 10.0); else glOrtho(-4.0 * (GLfloat) w / (GLfloat) h, 4.0 * (GLfloat) w / (GLfloat) h, -4.0, 4.0, -10.0, 10.0); glMatrixMode(GL_MODELVIEW); display(); } /* sets up colors, lighting and other stuff. Most of the stuff was given to me by example, I just fiddled with the numbers to change some colors. */ void myinit() { GLfloat mat_specular[]={0.0, 1.0, 0.0, 1.0}; GLfloat mat_diffuse[]={0.0, 1.0, 0.0, 1.0}; GLfloat mat_ambient[]={0.0, 0.0, 1.0, 1.0}; GLfloat mat_shininess={10.0}; GLfloat light_ambient[]={1.0, 1.0, 1.0, 1.0}; GLfloat light_diffuse[]={1.0, 1.0, 1.0, 1.0}; GLfloat light_specular[]={1.0, 1.0, 1.0, 1.0}; /* set up ambient, diffuse, and specular components for light 0 */ glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); /* define material proerties for front face of all polygons */ glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialf(GL_FRONT, GL_SHININESS, mat_shininess); glEnable(GL_SMOOTH); /*enable smooth shading */ glEnable(GL_LIGHTING); /* enable lighting */ glEnable(GL_LIGHT0); /* enable light 0 */ glEnable(GL_DEPTH_TEST); /* enable z buffer */ glClearColor (0.0, 0.0, 0.0, 0.0); glColor3f (0.0, 0.0, 0.0); } void main() { /* make more important settings */ glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(800, 500); /* window size */ glutCreateWindow("cs130 lab #1"); /* window label */ /* initialize settings */ myinit(); /* go draw the shapes */ glutReshapeFunc(myReshape); glutDisplayFunc(display); glutMainLoop(); }