# 4/7/04

We built a cylinder, complete with normals. We then added a top face (so the cylinder is closed when viewed from the top -- we might want to add a bottom face as well). Finally, we made the top radius different from the bottom to create a truncated cone, and we did an animation in which the top radius varies from 0 (a cone) to twice the bottom radius.

A cylinder is a nice special case to generate out of polygons. We can use rectangular rather than triangular panels since we know the rectangles are coplanar. (Convince yourself of this!) If we want a cylinder with radius 1 and height 2, we can use rectangles connecting these points:

(cos(t),-1,sin(t)), (cos(t+h),-1,sin(t+h)), (cos(t+h),1,sin(t+h)), (cos(t),1,sin(t))

where t is increased in increments of h from 0 to 2 pi. If we change the four points to

(cos(t),-1,sin(t)), (cos(t+h),-1,sin(t+h)), (r*cos(t+h),1,r*sin(t+h)), (r*cos(t),1,r*sin(t))

then the base radius stays at 1 and the top radius is r.

To (start to) make a closed cylinder, we can fill in the top by using triangles from 0,1,0 to cos(t),1,sin(t) to cos(t+h),1,sin(t+h), again letting t increase by h until a circle is covered.

Finally, we can make a nifty animation by varying the top radius in an idle function. Here's the program:

`/* A truncated cone animation, 3/9/01 by Mark Harris*/#include <math.h>#include <GL/glut.h>double t=0;double PI2; // 2 PIdouble rad=1;double inc=.05;void cylinder(){	int n=8;	double h=PI2/n;	double x,z,xn,zn;	double t=0;	x=cos(t);	z=sin(t);	glBegin(GL_QUADS);	for(int i=0;i<n;i++){		t=t+h;		xn=cos(t);		zn=sin(t);		glNormal3f(x,0,z);		glVertex3f(xn,-1,zn);		glVertex3f(xn,1,zn);		glVertex3f(x,1,z);		glVertex3f(x,-1,z);		x=xn; z=zn;	}	glEnd();	glBegin(GL_TRIANGLES);	t=0;	x=cos(t); z=sin(t);	glNormal3f(0,1,0);	for(i=0;i<n;i++){		t+=h;		xn=cos(t);		zn=sin(t);		glVertex3f(0,0,0);		glVertex3f(x,1,z);		glVertex3f(xn,1,zn);		x=xn; z=zn;	}	glEnd();		}void trunccylinder(double toprad,int sides){	int n=sides;	double h=PI2/n;	double x,z,xn,zn;	double t=0;	x=cos(t);	z=sin(t);	glBegin(GL_QUADS);	for(int i=0;i<n;i++){		t=t+h;		xn=cos(t);		zn=sin(t);		glNormal3f(cos(t),0,sin(t));		glVertex3f(cos(t+h),-1,sin(t+h));		glVertex3f(toprad*cos(t+h),1,toprad*sin(t+h));		glVertex3f(toprad*cos(t),1,toprad*sin(t));		glVertex3f(cos(t),-1,sin(t));		x=xn; z=zn;	}	glEnd();	glBegin(GL_TRIANGLES);	t=0;	x=toprad*cos(t); z=toprad*sin(t);	glNormal3f(0,1,0);	for(i=0;i<n;i++){		t+=h;		xn=toprad*cos(t);		zn=toprad*sin(t);		glVertex3f(0,0,0);		glVertex3f(x,1,z);		glVertex3f(xn,1,zn);		x=xn; z=zn;	}	glEnd();		}void display(){	int i;	glClearColor(1,1,1,0);	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	glMatrixMode(GL_MODELVIEW);	glLoadIdentity();	gluLookAt(0,2,4,0,0,0,0,1,0);	trunccylinder(rad,36);	glFlush();	glutSwapBuffers();}void myinit(){	PI2=atan(1)*8;    GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };    GLfloat mat_shininess[] = { 50.0 };	GLfloat mat_amb_diff[] = { 0.1, 0.5, 0.8, 1.0 };	GLfloat light_position[] = { 1.0, 2.0, 3.0};	glLightfv(GL_LIGHT0, GL_POSITION, light_position);	glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE,             mat_amb_diff);    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);    glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);    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.0, /* Z far */ 10);	glMatrixMode(GL_MODELVIEW);}void idle(){	rad+=inc;	if(rad<0){		rad=0;		inc=-inc;	}else if(rad>2){		rad=2;		inc=-inc;	}	glutPostRedisplay();}int main(int argc,char** argv){	glutInit(&argc,argv);	glutInitWindowSize(400,400);	glutInitDisplayMode (GLUT_DOUBLE| GLUT_RGB|GLUT_DEPTH); 	glutInitWindowPosition(100,100);	glutCreateWindow("Cylinders");	glutDisplayFunc(display);	glutIdleFunc(idle);	myinit();	glutMainLoop();	return 0;}`

Here are a couple of screen shots:

Let's have a quiz on Monday covering polygons, normals and lighting!