# 3/29/04

We looked more closely at shadows today, covering the material in 5.9 of our text. To cast a shadow of a polygon, we move the origin to the light source (Lx,Ly,Lz), find the coordinates of x and z when y is -Ly along the ray from the light source to a given vertex, then translate back to where we were. We calculated our own projection matrix, shown on page 234 of our text. You can use your own 4x4 matrices in OpenGL by creating a one-dimensional array m with the 4x4 array entries listed in column-major order (ordered by columns rather than the usual order by rows). Then glMultMatrix(m) will apply the transformation.

Following is a short program which illustrates shadows by having a light source rotate around a cube. Every time the light makes a complete circle, it is raised by a short distance (thus casting shorter shadows). Here's the program:

`// By Late Dr. Mark Harris #include <math.h>#include <GL/glut.h>typedef GLfloat point3[3];GLfloat LightRadius=4;GLfloat LightHeight=2;GLfloat Lx=LightRadius,Ly=LightHeight,Lz=0;double PI,PI2;GLfloat m[16]={	1,0,0,0,	0,1,0,0,	0,0,1,0,	0,0,0,0};GLfloat t=0;// List all vertices in array and reference later by indexpoint3 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,int shadow){	// Draw point i in color i	if(shadow)glColor3f(0,0,0);	else glColor3fv(p[i]);	glVertex3fv(p[i]);}void drawFace(int i1,int i2,int i3,int i4, int shadow){	// draw a face of the cube	glBegin(GL_POLYGON);	drawPoint(i1,shadow);	drawPoint(i2,shadow);	drawPoint(i3,shadow);	drawPoint(i4,shadow);	glEnd();}void myinit(void){	PI=atan(1)*4;	PI2=2*PI;	m[7]=-1/Ly;	/* attributes */	glClearColor(1.0, 1.0, 1.0, 1.0); /* white background */	glColor3f(0.0, 0.0, 0.0); /* draw in black */	/* set up viewing */	glMatrixMode(GL_PROJECTION);	glLoadIdentity();	double w=.1;	glFrustum(-w,w,-w,w,.2,10);}void drawCube(int shadow){	drawFace(0,3,2,1,shadow); //bottom	drawFace(1,2,6,5,shadow); //front	drawFace(2,3,7,6,shadow); //right side	drawFace(0,1,5,4,shadow); //left side	drawFace(3,0,4,7,shadow); //back side	drawFace(4,5,6,7,shadow); //top}void display( void ){	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); /*clear the window */	glMatrixMode(GL_MODELVIEW);	glLoadIdentity();	gluLookAt(4,2,4,0,0,0,0,1,0);	drawCube(0);	glTranslatef(Lx,Ly,Lz); //translate back	glMultMatrixf(m);	glTranslatef(-Lx,-Ly,-Lz);	drawCube(1);	glFlush(); /* clear buffers */	glutSwapBuffers();}void idle(){	t+=.1;	Lx=LightRadius*cos(t);	Ly=LightHeight;	Lz=LightRadius*sin(t);	m[7]=-1/Ly;	if(t>=PI2){		t-=PI2;		LightHeight+=.5;	}	glutPostRedisplay();}void main(int argc, char** argv){	/* Standard GLUT initialization */	glutInit(&argc,argv);	glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB|GLUT_DEPTH);	glutInitWindowSize(500,500); /* 500 x 500 pixel window */	glutInitWindowPosition(0,0); /* place window top left on display */	glutCreateWindow("Cube"); /* window title */	glutDisplayFunc(display); /* display callback invoked when window opened */	glutIdleFunc(idle);	myinit(); /* set attributes */	glEnable(GL_DEPTH_TEST); /* Enable hidden--surface--removal */	glEnable(GL_SMOOTH); /* Enable smooth shading and color interpolation */	glutMainLoop(); /* enter event loop */}`

Here's a sample image from the resulting animation: