/* Demo exhibiting the use of a spotlight */ #include #include // for random, among other things #include #include const GLfloat BB_Width = 10; const GLfloat BB_Height = 5; const GLfloat BB_Depth = 10; // variables for spotlight. If you change the spotlight direction, you // have to change the drawing of the cone. Search for "depends on the // light vector" GLfloat lightPosition[] = {BB_Width/2,BB_Height,BB_Depth/2,1}; GLfloat lightDirection [] = {0,-1,0}; // ================================================================ // Globals for callbacks //allows user to change number of squares int Resolution = 16; bool outline = false ; // whether to draw the squares bool smooth = true; // whether to use smooth shading GLfloat Ambient = 0; GLfloat Diffuse = 1; GLfloat Specular = 0; GLfloat lightCutoff = 35; GLfloat lightExponent = 5; void display(void) { twDisplayInit(); twCamera(); twAmbient(0); // no distracting ambient light twGraySpotlight(GL_LIGHT0,lightPosition, Ambient, Diffuse, Specular, lightDirection,lightCutoff,lightExponent); const GLfloat coneHeight = 1; // ================================================================ // Draw the light glColor3f(1,0,0); glPointSize(4); glBegin(GL_POINTS); glVertex3f(lightPosition[0],lightPosition[1],lightPosition[2]); glEnd(); // ================================================================ // Draw the light direction glColor3f(0,0,1); glLineWidth(2); glBegin(GL_LINES); glVertex3f(lightPosition[0],lightPosition[1],lightPosition[2]); // light starts here glVertex3f(lightPosition[0]+2*lightDirection[0], lightPosition[1]+2*lightDirection[1], lightPosition[2]+2*lightDirection[2]); glEnd(); // ================================================================ // Draw the cone if(false) { glPushMatrix(); glTranslatef(lightPosition[0],lightPosition[1],lightPosition[2]); // move origin to light position twTriple before = { 0, 0, 1 }; twTriple axis; twCrossProduct(axis,before,lightDirection); GLfloat angle = acos(twDot(before,lightDirection))*(180/M_PI); GLfloat coneTop = coneHeight*tan(lightCutoff*M_PI/180); glRotatef(angle,axis[0],axis[1],axis[2]); glColor3f(1,1,1); // we'll use cylinders, so that they are an "open" cone. twCylinder(0,coneTop,coneHeight,8,1); glPopMatrix(); } if(smooth) glShadeModel(GL_SMOOTH); else glShadeModel(GL_FLAT); glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); glEnable(GL_LIGHTING); // Draw a surface for the light to illuminate glPushMatrix(); glScalef(10,1,10); twTriple surfColor = {0.1, 0.9, 0.5}; twColor(surfColor,0.9,10); // primarily interested in diffuse, but still, this is pretty specular twDrawUnitSquare(Resolution,Resolution); glPopMatrix(); glFlush(); glutSwapBuffers(); } void modifySquare (unsigned char key, int x, int y) { switch(key) { case '+': Resolution=Resolution<<1; Resolution=Resolution==0?1:Resolution; break; case '-': Resolution=Resolution>>1; Resolution=Resolution==0?1:Resolution; break; } glutPostRedisplay(); } // returns a random floating point number between 0 and 1. float random01() { float n = (float) random(); float d = (float) RAND_MAX; return n/d; } void modifyLight (unsigned char key, int x, int y) { switch(key) { case 'A': Ambient+=0.1; break; case 'a': Ambient-=0.1; break; case 'D': Diffuse+=0.1; break; case 'd': Diffuse-=0.1; break; case 'S': Specular+=0.1; break; case 's': Specular-=0.1; break; // increase or decrease cutoff case 'w': if(lightCutoff<10) lightCutoff++; else lightCutoff+=5; break; case 'n': if(lightCutoff<10) lightCutoff--; else lightCutoff-=5; break; // increase or decrease exponent case 'E': lightExponent++; break; case 'e': lightExponent--; break; // random new light case 'r': // Keep lightPosition[1] at BB_Height, so that the light isn't too low. // lightPosition[0] = random01()*BB_Width; // lightPosition[1] = random01()*BB_Height; // lightPosition[2] = random01()*BB_Depth; // Keep lightDirection[1] at -1, so that the light always faces downwards // The other calculations keep the random components in the rand [-0.5,+0.5] lightDirection[0] = (random01()*-0.5); lightDirection[2] = (random01()*-0.5); lightCutoff = random01() * 90.0; lightExponent = random01() * 128.0; break; } printf("ambient = %3.2f, diffuse = %3.2f, specular = %3.2f, light dir = %3.2f %3.2f %3.2f, cutoff = %3.2f exponent = %3.2f\n", Ambient, Diffuse, Specular, lightDirection[0],lightDirection[1],lightDirection[2], lightCutoff, lightExponent); glutPostRedisplay(); } void modifyShading (unsigned char key, int x, int y) { switch(key) { case 'm': smooth = true; glutPostRedisplay(); break; case 'f': smooth = false; glutPostRedisplay(); break; } } void keyInit() { twKeyCallback('+', modifySquare, "double the number of squares"); twKeyCallback('-', modifySquare, "halve the number of squares"); twKeyCallback('A', modifyLight, "increase Ambient"); twKeyCallback('a', modifyLight, "decrease Ambient"); twKeyCallback('D', modifyLight, "increase Diffuse"); twKeyCallback('d', modifyLight, "decrease Diffuse"); twKeyCallback('S', modifyLight, "increase Specular"); twKeyCallback('s', modifyLight, "decrease Specular"); twKeyCallback('w', modifyLight, "widens the cutoff angle"); twKeyCallback('n', modifyLight, "narrows the cutoff angle"); twKeyCallback('E', modifyLight, "increase spot exponent"); twKeyCallback('e', modifyLight, "decrease spot exponent"); twKeyCallback('r', modifyLight, "random new light"); twKeyCallback('m', modifyShading, "smooth shading"); twKeyCallback('f', modifyShading, "flat shading"); } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); twInitWindowSize(800,500); twBoundingBox(0,BB_Width,0,BB_Height,0,BB_Depth); glutCreateWindow(argv[0]); glutDisplayFunc(display); twMainInit(); keyInit(); glutMainLoop(); return 0; }