/* * CPSC 465 * Principles of Computer Graphics * Section 1 * Spring 2006 * * Assignment 10 * * Car with Lighting * */ #include #include #include #include #if !defined(__cplusplus) typedef int bool; #define false 0 #define true !false #endif #if defined(__APPLE__) || defined(MACOSX) #include #else #include #endif #define PI 3.14159265 /* GLUT window */ int width = 600, height = 400; /* world window */ double scaledWidth, scaledHeight; /* trackball rotation */ double start_x, start_y, start_z; double rotation[4 * 4]; bool tracking = false; /* lighting */ bool light0 = true; bool light1 = false; float light0_pos[] = { 3.0, 3.0, 3.0, 0.0 }; float light1_pos[] = { 0.0, 0.0, 3.0, 0.0 }; float light1_diffuse[] = { 1.0, 1.0, 1.0, 0.0 }; void cross(double X0, double Y0, double Z0, double X1, double Y1, double Z1, double *x, double *y, double *z) { (*x) = Y0 * Z1 - Z0 * Y1; (*y) = Z0 * X1 - X0 * Z1; (*z) = X0 * Y1 - Y0 * X1; } double dot(double X0, double Y0, double Z0, double X1, double Y1, double Z1) { return X0 * X1 + Y0 * Y1 + Z0 * Z1; } void drawFrontWindshield(void) { glColor3d(0.0, 1.0, 0.0); glBegin(GL_QUADS); glNormal3d(0.0, -1.0, 0.0); glVertex3d(0.5, -0.5, -0.5); glVertex3d(1.5, -0.5, -0.5); glVertex3d(1.5, -0.5, 0.5); glVertex3d(0.5, -0.5, 0.5); glEnd(); glBegin(GL_QUADS); glNormal3d(1.0, 1.0, 0.0); glVertex3d(1.5, -0.5, -0.5); glVertex3d(0.5, 0.5, -0.5); glVertex3d(0.5, 0.5, 0.5); glVertex3d(1.5, -0.5, 0.5); glEnd(); glBegin(GL_TRIANGLES); glNormal3d(0.0, 0.0, -1.0); glVertex3d(0.5, -0.5, -0.5); glVertex3d(0.5, 0.5, -0.5); glVertex3d(1.5, -0.5, -0.5); glEnd(); glBegin(GL_TRIANGLES); glNormal3d(0.0, 0.0, 1.0); glVertex3d(0.5, -0.5, 0.5); glVertex3d(1.5, -0.5, 0.5); glVertex3d(0.5, 0.5, 0.5); glEnd(); } void drawRearWindshield(void) { glColor3d(0.0, 0.0, 1.0); glBegin(GL_QUADS); glNormal3d(0.0, -1.0, 0.0); glVertex3d(-0.5, -0.5, 0.5); glVertex3d(-1.5, -0.5, 0.5); glVertex3d(-1.5, -0.5, -0.5); glVertex3d(-0.5, -0.5, -0.5); glEnd(); glBegin(GL_QUADS); glNormal3d(-1.0, 1.0, 0.0); glVertex3d(-0.5, 0.5, -0.5); glVertex3d(-1.5, -0.5, -0.5); glVertex3d(-1.5, -0.5, 0.5); glVertex3d(-0.5, 0.5, 0.5); glEnd(); glBegin(GL_TRIANGLES); glNormal3d(0.0, 0.0, -1.0); glVertex3d(-0.5, -0.5, -0.5); glVertex3d(-1.5, -0.5, -0.5); glVertex3d(-0.5, 0.5, -0.5); glEnd(); glBegin(GL_TRIANGLES); glNormal3d(0.0, 0.0, 1.0); glVertex3d(-0.5, -0.5, 0.5); glVertex3d(-0.5, 0.5, 0.5); glVertex3d(-1.5, -0.5, 0.5); glEnd(); } void setupLighting(void) { if (light0) { glEnable(GL_LIGHT0); } else { glDisable(GL_LIGHT0); } if (light1) { glEnable(GL_LIGHT1); } else { glDisable(GL_LIGHT1); } glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse); } void drawModel(void) { /* 3. Viewing parameters */ glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0.0, 0.0, 4.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); setupLighting(); /* 4. Model */ glMultMatrixd(rotation); glPushMatrix(); glTranslated(0.0, 0.5, 0.0); glColor3d(1.0, 0.0, 0.0); glutSolidCube(1.0); drawFrontWindshield(); drawRearWindshield(); glPopMatrix(); glPushMatrix(); glScaled(4.0, 1.0, 1.0); glTranslated(0.0, -0.5, 0.0); glColor3d(1.0, 1.0, 0.0); glutSolidCube(1.0); glPopMatrix(); glPushMatrix(); glTranslated(0.0, -0.5, 0.0); glColor3d(0.0, 0.0, 0.0); glPushMatrix(); glTranslated(1.5, -0.5, 0.75); glutSolidTorus(0.20, 0.5, 20, 30); glPopMatrix(); glColor3d(0.0, 0.0, 0.0); glPushMatrix(); glTranslated(-1.5, -0.5, 0.75); glutSolidTorus(0.20, 0.5, 20, 30); glPopMatrix(); glColor3d(0.0, 0.0, 0.0); glPushMatrix(); glTranslated(1.5, -0.5, -0.75); glutSolidTorus(0.20, 0.5, 20, 30); glPopMatrix(); glColor3d(0.0, 0.0, 0.0); glPushMatrix(); glTranslated(-1.5, -0.5, -0.75); glutSolidTorus(0.20, 0.5, 20, 30); glPopMatrix(); glPopMatrix(); } void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); drawModel(); glutSwapBuffers(); } void doProjection(int w, int h) { if (w > h) { scaledWidth = 2.0 * w / h; scaledHeight = 2.0; } else { scaledWidth = 2.0; scaledHeight = 2.0 * h / w; } glFrustum(-scaledWidth / 2.0, scaledWidth / 2.0, -scaledHeight / 2.0, scaledHeight / 2.0, 1.0, 8.0); } void reshape(int w, int h) { width = w; height = h; /* 1. Viewport */ glViewport(0, 0, width, height); /* 2. Projection */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); doProjection(width, height); } void calcZ(double *x, double *y, double *z) { double d = (*x) * (*x) + (*y) * (*y); if (d <= 1.0) { (*z) = sqrt(1.0 - d); } else { (*x) = (*x) / sqrt(d); (*y) = (*y) / sqrt(d); (*z) = 0; } } double length(double x, double y, double z) { return sqrt(dot(x, y, z, x, y, z)); } double rad2deg(double radians) { return radians * 180.0 / PI; } double scaleX(int x) { return ((double) x / width * scaledWidth) - (scaledWidth / 2.0); } double scaleY(int y) { return -(((double) y / height * scaledHeight) - (scaledHeight / 2.0)); } void mouse(int button, int state, int x, int y) { tracking = (state == GLUT_DOWN); if (button != GLUT_LEFT_BUTTON) return; if (state == GLUT_DOWN) { start_x = scaleX(x); start_y = scaleY(y); calcZ(&start_x, &start_y, &start_z); } } void motion(int x, int y) { double end_x, end_y, end_z; double rot_x, rot_y, rot_z; double theta; if (tracking) { end_x = scaleX(x); end_y = scaleY(y); calcZ(&end_x, &end_y, &end_z); cross(start_x, start_y, start_z, end_x, end_y, end_z, &rot_x, &rot_y, &rot_z); theta = rad2deg(asin(length(rot_x, rot_y, rot_z))); if (dot(start_x, start_y, start_z, end_x, end_y, end_z) < 0.0) { theta = 180.0 - theta; } glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glRotated(theta, rot_x, rot_y, rot_z); glMultMatrixd(rotation); glGetDoublev(GL_MODELVIEW_MATRIX, rotation); glPopMatrix(); start_x = end_x; start_y = end_y; start_z = end_z; glutPostRedisplay(); } } void keyboard(unsigned char key, int x, int y) { switch (key) { case '1': light0 = !light0; break; case '2': light1 = !light1; break; case 'r': light1_diffuse[0] = 1.0; light1_diffuse[1] = 0.3; light1_diffuse[2] = 0.3; break; case 'g': light1_diffuse[0] = 0.3; light1_diffuse[1] = 1.0; light1_diffuse[2] = 0.3; break; case 'b': light1_diffuse[0] = 0.3; light1_diffuse[1] = 0.3; light1_diffuse[2] = 1.0; break; case 'w': light1_diffuse[0] = 1.0; light1_diffuse[1] = 1.0; light1_diffuse[2] = 1.0; break; } glutPostRedisplay(); } int main(int argc, char *argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); glutInitWindowSize(width, height); glutInitWindowPosition(100, 100); glutCreateWindow("Car with Lighting"); glClearColor(0.2, 0.2, 0.2, 0.0); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glEnable(GL_CULL_FACE); glCullFace(GL_BACK); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_NORMALIZE); glEnable(GL_COLOR_MATERIAL); glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); glLightfv(GL_LIGHT0, GL_POSITION, light0_pos); glLightfv(GL_LIGHT1, GL_POSITION, light1_pos); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glGetDoublev(GL_MODELVIEW_MATRIX, rotation); glutDisplayFunc(display); glutReshapeFunc(reshape); glutMouseFunc(mouse); glutMotionFunc(motion); glutKeyboardFunc(keyboard); glutMainLoop(); return 0; }