# 4/14/04

We started with Quiz 6:

Consider the unit cube with vertices (0,0,0), (1,0,0), (1,0,1), (0,0,1), (0,1,0), (1,1,0), (1,1,1), (0,1,1).

(a) What normal should be specified on the face containing the first 4 of these points if the cube is to be displayed with sharp edges?

These four points all have y-coordinate 0, so this is the bottom of the cube. The normal is <0,-1,0>.

(b) How would you calculate normals if you want the 6 faces of the cube to blend smoothly into one another? Give a specific normal as an example.

Give a different normal at each vertex, obtained by averaging the normals of three faces meeting at that vertex. For example, at (1,1,1) the normal vector would point in the direction <1,1,1>.

The idea was to understand the role of normal specification in drawing polyhedrons. If you specify a normal only once for a polygon, the polygon will be uniformly shaded. If you specify a normal for each vertex, obtained for example by averaging the normals of all polygons meeting at that vertex, the shading will blend along the edges. Here are images of a cube with (1) a single normal specified for each face, and (2) normals for each vertex, averaging the normals of the three faces meeting at the vertex:

Here are the programs which generated the two images. Note the use of the gluPerspective function -- it's a replacement for the glFrustum function which easier to use. You specify the camera's angle of vision rather than worrying about ratios of the near distance to the dimensions of the x-y rectangle being viewed. Try experimenting with the angle! Larger values give wide-angle lenses; smaller values give telephoto lenses.

Program 1:

`#include <GL/glut.h>typedef GLfloat point3[3];point3 p[8]={	{0,0,0},  	{0,0,1},	{1,0,1},  	{1,0,0},  	{0,1,0},  	{0,1,1},  	{1,1,1},  	{1,1,0}   };point3 n[6]={ // normals for each face	{0,-1,0},	{0,0,1},	{1,0,0},	{0,0,-1},	{0,1,0},	{-1,0,0}};void drawPoint(int i){	glVertex3fv(p[i]);}void drawFace(int i1,int i2,int i3,int i4,int k){	glBegin(GL_POLYGON);	glNormal3fv(n[k]); // use normal for this face	drawPoint(i1);	drawPoint(i2);	drawPoint(i3);	drawPoint(i4);	glEnd();}	void drawCube(){	drawFace(0,3,2,1,0);	drawFace(1,2,6,5,1); 	drawFace(2,3,7,6,2); 	drawFace(3,0,4,7,3); 	drawFace(4,5,6,7,4); 	drawFace(5,4,0,1,5); }void display( void ){	glClearColor(1.0, 1.0, 1.0, 1.0); /* white background */	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);  /*clear the window */	glMatrixMode(GL_MODELVIEW);	glLoadIdentity();	gluLookAt(1.5,2,4,.5,.5,.5,0,1,0);	drawCube();	glFlush(); /* clear buffers */}void main(int argc, char** argv){	glutInit(&argc, argv);	glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH);	glMatrixMode(GL_MODELVIEW);	glEnable(GL_DEPTH_TEST);  	glutInitWindowSize(500, 500);	glutCreateWindow("Cube");	glutDisplayFunc(display);	GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };	GLfloat mat_shininess[] = { 50.0 };	GLfloat light_position[] = { 1.0, 2.0, 3.0};	glLightfv(GL_LIGHT0, GL_POSITION, light_position);	glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);	glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);	GLfloat mat_amb_diff_red[] = { 1, 0, 0, 1.0 };	glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE,mat_amb_diff_red);	glEnable(GL_LIGHTING);	glEnable(GL_LIGHT0);	glEnable(GL_DEPTH_TEST); /* enable z buffer */	glEnable(GL_NORMALIZE);	glMatrixMode(GL_PROJECTION);	// gluPerspective is an alternative to glFrustum in which	// the 'lens' is specified by angle and aspect ratio rather	// than frustum coordinates	// The near and far planes have the same meaning as before.	gluPerspective( /* field of view in degree */ 40.0,		/* aspect ratio */ 1.0,		/* Z near */ .1, /* Z far */ 100);	glMatrixMode(GL_MODELVIEW);	glutMainLoop();}`

Program 2:

`#include <GL/glut.h>typedef GLfloat point3[3];point3 p[8]={	{0,0,0},  	{0,0,1},	{1,0,1},  	{1,0,0},  	{0,1,0},  	{0,1,1},  	{1,1,1},  	{1,1,0}   };void drawPoint(int i){	glVertex3fv(p[i]);}void makeNormal(int i){// make each vertex normal point from middle of cube to itself	double x,y,z;	x=p[i][0]-.5;	y=p[i][1]-.5;	z=p[i][2]-.5;	glNormal3f(x,y,z);	drawPoint(i);}void drawFace(int i1,int i2,int i3,int i4,int k){	glBegin(GL_POLYGON);	makeNormal(i1);	makeNormal(i2);	makeNormal(i3);	makeNormal(i4);	glEnd();}	void drawCube(){	drawFace(0,3,2,1,0);	drawFace(1,2,6,5,1); 	drawFace(2,3,7,6,2); 	drawFace(3,0,4,7,3); 	drawFace(4,5,6,7,4); 	drawFace(5,4,0,1,5); }void display( void ){	glClearColor(1.0, 1.0, 1.0, 1.0); /* white background */	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);  /*clear the window */	glMatrixMode(GL_MODELVIEW);	glLoadIdentity();	gluLookAt(1.5,2,4,.5,.5,.5,0,1,0);	drawCube();	glFlush(); /* clear buffers */}void main(int argc, char** argv){	glutInit(&argc, argv);	glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH);	glMatrixMode(GL_MODELVIEW);	glEnable(GL_DEPTH_TEST);  	glutInitWindowSize(500, 500);	glutCreateWindow("Cube");	glutDisplayFunc(display);	GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };	GLfloat mat_shininess[] = { 50.0 };	GLfloat light_position[] = { 1.0, 2.0, 3.0};	glLightfv(GL_LIGHT0, GL_POSITION, light_position);	glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);	glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);	GLfloat mat_amb_diff_red[] = { 1, 0, 0, 1.0 };	glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE,mat_amb_diff_red);	glEnable(GL_LIGHTING);	glEnable(GL_LIGHT0);	glEnable(GL_DEPTH_TEST); /* enable z buffer */	glEnable(GL_NORMALIZE);	glMatrixMode(GL_PROJECTION);	// gluPerspective is an alternative to glFrustum in which	// the 'lens' is specified by angle and aspect ratio rather	// than frustum coordinates	// The near and far planes have the same meaning as before.	gluPerspective( /* field of view in degree */ 40.0,		/* aspect ratio */ 1.0,		/* Z near */ .1, /* Z far */ 100);	glMatrixMode(GL_MODELVIEW);	glutMainLoop();}`