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 PI
double 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!