/* ==================================================================== Sphere Lighting Demo Version 2.0 Slightly Rewritten by H Masterman 16 October 2009 to correct errors in the flat shading version and to introduce animation for better viewing. Also, several errors in the original Angel example were cleaned up. It uses ecursive subdivision of a tetrahedron to approximate a sphere. mode 0 = wire frame mode 1 = constant shading, mode 3 = interpolative shading =======================================================================*/ #include #include #include #include using namespace std; typedef float point[3]; /* 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 n; int mode; float theta = 0.0; int number_of_triangles = 0; 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 */ { float flat_normal_0 = (a[0] + b[0] + c[0])/3.0; float flat_normal_1 = (a[1] + b[1] + c[1])/3.0; float flat_normal_2 = (a[2] + b[2] + c[2])/3.0; if (mode==0) glBegin(GL_LINE_LOOP); else glBegin(GL_POLYGON); if(mode==1) glNormal3f(flat_normal_0, flat_normal_1, flat_normal_2); if(mode==2|mode==0) glNormal3fv(a); glVertex3fv(a); if(mode==2| mode==0) glNormal3fv(b); glVertex3fv(b); if(mode==2| mode==0) glNormal3fv(c); glVertex3fv(c); glEnd(); } void normal(point p) { /* normalize a vector */ 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; } void divide_triangle(point a, point b, point c, int m) { /* triangle subdivision using vertex numbers righthand rule applied to create outward pointing faces */ point v1, v2, v3, vmiddle; int j; 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 */ } void tetrahedron( int m) { /* Apply triangle subdivision to faces of tetrahedron */ 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); } void display(void) { /* Displays all three modes, side by side */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glRotatef(theta, 0,1,0); mode=0; tetrahedron(n); mode=1; glTranslatef(-2.0, 0.0,0.0); tetrahedron(n); mode=2; glTranslatef( 4.0, 0.0,0.0); tetrahedron(n); glFlush(); glutSwapBuffers(); } void myReshape(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w <= h) glOrtho(-3.0, 3.0, -3.0 * (GLfloat) h / (GLfloat) w, 3.0 * (GLfloat) h / (GLfloat) w, -10.0, 10.0); else glOrtho(-3.0 * (GLfloat) w / (GLfloat) h, 3.0 * (GLfloat) w / (GLfloat) h, -3.0, 3.0, -10.0, 10.0); glMatrixMode(GL_MODELVIEW); } void myinit() { GLfloat mat_specular[]={0.5, 00.0, 0.0, 1.0}; GLfloat mat_diffuse[]={0.00, 0.30, 0.0, 1.0}; GLfloat mat_ambient[]={0.0, 0.1, 0.0, 0.0}; GLfloat mat_shininess={30.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}; GLfloat light_position[]={0.0, 5.0, 10.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); glLightfv(GL_LIGHT0, GL_POSITION, light_position); /* 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); glShadeModel(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, 1.0); } void idle() { theta += 0.2; glutPostRedisplay(); } void main(int argc, char **argv) { n=4; glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH |GLUT_DOUBLE); glutInitWindowSize(500, 500); glutCreateWindow("sphere"); myinit(); glutReshapeFunc(myReshape); glutDisplayFunc(display); //glutIdleFunc(idle); glutMainLoop(); }