/* Demo of defining the front of a quadilateral for use in material and lighting. Implemented Fall 2004 Scott D. Anderson */ #include #include #include twTriple Quad[4] = { {-1,-1,0}, // left, bottom, front {+1,-1,0}, // right, bottom, front {-1,+1,0}, // left, top, front {+1,+1,0}, // right, top, front }; bool CullFace = false; bool Amb = true; bool Diff = true; bool Spec = true; bool LocalViewer = false; bool TwoSided = false; bool Back = true; void drawQuad(int a, int b, int c, int d) { // twTriple N; // twPlaneNormal(N,Quad[a],Quad[b],Quad[c]); glBegin(GL_QUADS); // glNormal3f(N[0],N[1],N[2]); glVertex3fv(Quad[a]); glVertex3fv(Quad[b]); glVertex3fv(Quad[c]); glVertex3fv(Quad[d]); glEnd(); } void display(void) { twDisplayInit(); twCamera(); if(CullFace) { glEnable(GL_CULL_FACE); } else { glDisable(GL_CULL_FACE); } glEnable(GL_NORMALIZE); GLfloat lightDir[] = { -1, 0, 1, 0}; // from back right twGrayLight(GL_LIGHT0,lightDir,1,1,1); glEnable(GL_LIGHTING); if(LocalViewer) { glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,1); } else { glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,0); } if(TwoSided) { glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,1); } else { glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,0); } twTriple black = {0,0,0}; twTriple red = {1,0,0}; twTriple green = {0,1,0}; twTriple blue = {0,0,1}; twTriple yellow50 = {0.5,0.5,0}; twTriple cyan50 = {0,0.5,0.5}; twTriple magenta50 = {0.5,0,0.5}; glMaterialfv(GL_FRONT,GL_AMBIENT,Amb?red:black); glMaterialfv(GL_FRONT,GL_DIFFUSE,Diff?green:black); glMaterialfv(GL_FRONT,GL_SPECULAR,Spec?blue:black); glMaterialf(GL_FRONT,GL_SHININESS,10); if(Back) { glMaterialfv(GL_BACK,GL_AMBIENT,Amb?magenta50:black); glMaterialfv(GL_BACK,GL_DIFFUSE,Diff?yellow50:black); glMaterialfv(GL_BACK,GL_SPECULAR,Spec?cyan50:black); glMaterialf(GL_BACK,GL_SHININESS,10); } else { glMaterialfv(GL_BACK,GL_AMBIENT,Amb?red:black); glMaterialfv(GL_BACK,GL_DIFFUSE,Diff?green:black); glMaterialfv(GL_BACK,GL_SPECULAR,Spec?blue:black); glMaterialf(GL_BACK,GL_SHININESS,10); } glutSolidSphere(1,32,32); // Upper right quad is proper: CCW and N=(0,0,1); glPushMatrix(); glTranslatef(+2,+2,0); glNormal3f(0,0,1); drawQuad(0,1,3,2); glPopMatrix(); // Upper left quad is bad: CW. It disappears with backface culling glPushMatrix(); glTranslatef(-2,+2,0); glNormal3f(0,0,1); drawQuad(0,2,3,1); glPopMatrix(); // Lower left quad is bad: N=(0,0,-1). It doesn't disappear with // backface culling, but we only see the ambient, not the // ambient+diffuse glPushMatrix(); glTranslatef(-2,-2,0); glNormal3f(0,0,-1); drawQuad(0,1,3,2); glPopMatrix(); // Lower right is a proper cube. Looks just like the upper left glPushMatrix(); glTranslatef(+2,-2,0); glScalef(2,2,0.1); glutSolidCube(1); glPopMatrix(); glFlush(); glutSwapBuffers(); } void keys(unsigned char k, int x, int y) { switch(k) { case 'a': Amb = !Amb; break; case 'd': Diff = !Diff; break; case 's': Spec = !Spec; break; case 'c': CullFace = !CullFace; break; case '1': { twTriple Y={0,1,0}; twRotateViewpoint(180,Y); } break; case 'l': LocalViewer = !LocalViewer; break; case '2': TwoSided = !TwoSided; break; case 'b': Back = !Back; break; case 'p': printf("\nAmbient %s\nDiffuse %s\nSpecular %s\nCullFace %s\nLocalViewer %s\nTwoSided %s\nBack Material %s\n", Amb?"on":"off", Diff?"on":"off", Spec?"on":"off", CullFace?"on":"off", LocalViewer?"on":"off", TwoSided?"on":"off", Back?"on":"off"); break; } glutPostRedisplay(); } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); twInitWindowSize(500,500); glutCreateWindow(argv[0]); glutDisplayFunc(display); twBoundingBox(-2,+2,-2,+2,-1,+1); // a lie twMainInit(); twKeyCallback('c',keys,"toggle backface culling"); twKeyCallback('a',keys,"toggle Ambient = red"); twKeyCallback('d',keys,"toggle Diffuse = green"); twKeyCallback('s',keys,"toggle Specular = blue"); twKeyCallback('1',keys,"180 degree rotation"); twKeyCallback('2',keys,"toggle two-sided lighting"); twKeyCallback('l',keys,"toggle local viewer"); twKeyCallback('b',keys,"toggle back material"); twKeyCallback('p',keys,"print settings"); glutMainLoop(); return 0; }