| Main Menu | TOC | Previous | Next | Lecture Start |
Example: movingLight.c
/* movingLight.c - Set up a light that moves independent
* of the objects in the scene. See the animate
* function to have an idea about how to use clock ticks
* to control the perceived animation speed.
*
* Left Mouse Button - change incidence and azimuth angles
* Middle Mousebutton - change the twist angle based on
* horizontal mouse movement
* Right Mousebutton - zoom in and out based on vertical
* mouse movement
* <a> key - toggle light animation
* <m> key - toggle local/infinite viewer
* <f> key - toggle fixed/not fixed frame rate
* Escape key - exit the program
*/
#include <GL/glut.h> /* includes gl.h, glu.h */
#include <math.h>
#include <stdio.h>
/* Function Prototypes */
GLvoid initgfx( GLvoid );
GLvoid animate( GLvoid );
GLvoid visibility( GLint );
GLvoid drawScene( GLvoid );
GLvoid reshape( GLsizei, GLsizei );
GLvoid keyboard( GLubyte, GLint, GLint );
GLvoid mouse( GLint, GLint, GLint, GLint );
GLvoid motion( GLint, GLint );
void resetView( GLvoid );
void polarView( GLfloat, GLfloat, GLfloat, GLfloat );
void printHelp( char * );
/* Global Definitions */
#define KEY_ESC 27 /* ascii value for the escape key */
/* Global Variables */
static GLfloat lightAngle = 0.0; /* controls light rotation */
static GLboolean animateLight = GL_TRUE;
static GLboolean localLight = GL_FALSE;
enum actions { MOVE_EYE, TWIST_EYE, ZOOM, MOVE_NONE };
static GLint action;
static GLdouble xStart = 0.0, yStart = 0.0;
static GLfloat fovy, nearClip, farClip, distance, twistAngle, incAngle, azimAngle;
static GLint before;
static GLint fixFrameRate = 0;
void
main( int argc, char *argv[] )
{
GLsizei width, height;
glutInit( &argc, argv );
width = glutGet( GLUT_SCREEN_WIDTH );
height = glutGet( GLUT_SCREEN_HEIGHT );
glutInitWindowPosition( width / 4, height / 4 );
glutInitWindowSize( (width / 2) - 4, height / 2 );
glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
glutCreateWindow( argv[0] );
initgfx();
glutIdleFunc( animate );
glutVisibilityFunc( visibility );
glutMouseFunc( mouse );
glutMotionFunc( motion );
glutKeyboardFunc( keyboard );
glutReshapeFunc( reshape );
glutDisplayFunc( drawScene );
printHelp( argv[0] );
glutMainLoop();
}
void
printHelp( char *progname )
{
fprintf(stdout, "\n%s - demonstrate how to add a moving light\n\n"
"Left Mousebutton - move eye position\n"
"Middle Mousebutton - change twist angle\n"
"Right Mousebutton - move up / down to zoom in / out\n"
"<a> Key - toggle light animation\n"
"<m> Key - toggle local/infinite viewer\n"
"<f> Key - toggle fixed/not fixed frame rate\n"
"Escape Key - exit the program\n\n",
progname);
}
GLvoid
initgfx( GLvoid )
{
glClearColor( 0.0, 0.0, 0.0, 1.0 );
glEnable( GL_DEPTH_TEST );
nearClip = 2.0; /* Near clipping plane location */
farClip = 15.0; /* Far clipping plane location */
resetView();
/* Turn on a default light */
glEnable( GL_LIGHT0 );
before = glutGet( GLUT_ELAPSED_TIME );
}
GLvoid
keyboard( GLubyte key, GLint x, GLint y )
{
GLfloat infinite[] = {0.0};
GLfloat local[] = {1.0};
switch (key) {
case 'a': /* toggle light animation */
animateLight = !animateLight;
if ( animateLight )
glutIdleFunc(animate);
else
glutIdleFunc(NULL);
glutPostRedisplay();
break;
case 'm': /* toggle lighting model */
localLight = !localLight;
if ( localLight )
{
glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local);
printf("local viewer ON\n");
}
else
{
glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, infinite);
printf("local viewer OFF\n");
}
glutPostRedisplay();
break;
case 'f':
fixFrameRate = !fixFrameRate;
glutPostRedisplay();
break;
case KEY_ESC: /* Exit when the Escape key is pressed */
exit(0);
}
}
GLvoid
mouse( GLint button, GLint state, GLint x, GLint y )
{
static GLint buttons_down = 0;
if (state == GLUT_DOWN) {
switch (button) {
case GLUT_LEFT_BUTTON:
action = MOVE_EYE;
break;
case GLUT_MIDDLE_BUTTON:
action = TWIST_EYE;
break;
case GLUT_RIGHT_BUTTON:
action = ZOOM;
break;
}
/* Update the saved mouse position */
xStart = x;
yStart = y;
} else {
if (--buttons_down == 0)
action = MOVE_NONE;
}
}
GLvoid
motion( GLint x, GLint y )
{
switch (action) {
case MOVE_EYE:
/* Adjust the eye position based on the mouse position */
azimAngle += (GLdouble) (x - xStart);
incAngle -= (GLdouble) (y - yStart);
break;
case TWIST_EYE:
/* Adjust the eye twist based on the mouse position */
twistAngle = fmod(twistAngle+(x - xStart), 360.0);
break;
case ZOOM:
/* Adjust the eye distance based on the mouse position */
distance -= (GLdouble) (y - yStart)/10.0;
break;
default:
printf("unknown action %d\n", action);
}
/* Update the stored mouse position for later use */
xStart = x;
yStart = y;
glutPostRedisplay();
}
void
resetView( GLvoid )
{
distance = nearClip + (farClip - nearClip) / 2.0;
twistAngle = 0.0; /* rotation of viewing volume (camera) */
incAngle = 60.0;
azimAngle = 0.0;
fovy = 60.0; /* Field of view in Y angle */
}
GLvoid
reshape( GLsizei width, GLsizei height )
{
GLdouble aspect;
glViewport( 0, 0, width, height );
aspect = (GLdouble) width / (GLdouble) height;
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( fovy, aspect, nearClip, farClip );
glMatrixMode( GL_MODELVIEW );
}
GLvoid
animate( GLvoid )
{
/* update the rotation of the light for each scene */
GLint now;
now = glutGet( GLUT_ELAPSED_TIME );
if (abs(now - before) >= 40 || !fixFrameRate) {
lightAngle = fmod( (lightAngle + 2.0), 360.0 );
before = now;
/* Tell GLUT to redraw the scene */
glutPostRedisplay();
}
}
GLvoid
visibility( int state )
{
if (state == GLUT_VISIBLE && animateLight) {
glutIdleFunc( animate );
} else {
glutIdleFunc( NULL );
}
}
void
polarView( GLfloat distance, GLfloat azimuth, GLfloat incidence,
GLfloat twist)
{
glTranslatef( 0.0, 0.0, -distance);
glRotatef( -twist, 0.0, 0.0, 1.0);
glRotatef( -incidence, 1.0, 0.0, 0.0);
glRotatef( -azimuth, 0.0, 0.0, 1.0);
}
GLvoid
drawScene( GLvoid )
{
/* Define a few materials properties */
GLfloat redAmbient[] = { 0.3, 0.1, 0.1, 1.0 };
GLfloat redDiffuse[] = { 1.0, 0.0, 0.0, 1.0 };
GLfloat blueAmbient[] = { 0.1, 0.1, 0.3, 1.0 };
GLfloat blueDiffuse[] = { 0.0, 0.0, 1.0, 1.0 };
GLfloat defaultEmission[] = { 0.0, 0.0, 0.0, 1.0 };
GLfloat whiteSpecular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat greenSpecular[] = { 0.0, 1.0, 0.0, 1.0 };
GLfloat defaultSpecular[] = { 0.0, 0.0, 0.0, 1.0 };
/* local light */
GLfloat lightPosition[] = { 0.0, 0.0, 0.0, 1.0 };
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glPushMatrix();
polarView( distance, azimAngle, incAngle, twistAngle );
XYZaxes();
/* Animate the light with its own set of transformations */
glPushMatrix();
glRotatef( lightAngle, 0.0, 1.0, 1.0 );
glTranslatef( 2.7, 0.0, 0.0 );
/* By giving the light position its own modeling
* transformations (due to the glPushMatrix()
* and glPopMatrix() calls), the light moves
* independently of the objects in the scene.
*/
glLightfv( GL_LIGHT0, GL_POSITION, lightPosition );
/* draw a small (unlit) white sphere to
* represent the light in our scene.
*/
glColor3f( 1.0, 1.0, 1.0 );
glutSolidSphere( 0.07, 4, 7);
glPopMatrix();
glEnable( GL_LIGHTING );
glMaterialfv( GL_FRONT, GL_EMISSION, defaultEmission );
/* Set properties for a shiny red material,
* with a green highlight */
glMaterialfv( GL_FRONT, GL_AMBIENT, redAmbient );
glMaterialfv( GL_FRONT, GL_DIFFUSE, redDiffuse );
glMaterialfv( GL_FRONT, GL_SPECULAR, greenSpecular );
glMaterialf( GL_FRONT, GL_SHININESS, 128.0 );
glPushMatrix();
glTranslatef( -2.5, 0.5, 0.0 );
glutSolidSphere( 0.7, 31, 31 );
glPopMatrix();
glPushMatrix();
glTranslatef( 1.0, 2.0, 2.0 );
glutSolidSphere( 0.9, 31, 31 );
glPopMatrix();
/* Set properties for a dull blue material with
* a small white highlight */
glMaterialfv( GL_FRONT, GL_AMBIENT, blueAmbient );
glMaterialfv( GL_FRONT, GL_DIFFUSE, blueDiffuse );
glMaterialfv( GL_FRONT, GL_SPECULAR, whiteSpecular );
glMaterialf( GL_FRONT, GL_SHININESS, 20.0 );
glPushMatrix();
glTranslatef( 2.5, 0.0, 0.0 );
glutSolidTorus( 0.25, 0.75, 16, 31 );
glPopMatrix();
glDisable( GL_LIGHTING );
glPopMatrix();
glutSwapBuffers();
}
|
| Main Menu | TOC | Previous | Next | Lecture Start |
Notes:
This program demonstrates how the position of the light can be made to move in a scene. By giving the light source its own transformations, it acts like any other object in the scene. The program uses a small, (unlit) white sphere to represent the light, but the light source would still behave the same way even if the program did not create an object to represent it.
Run movingLight and try to stop the light inside the torus. Then move around so the torus is sideways (so you cannot see the sphere). What is odd about this scene? The light still shines on the sphere even though it is blocked by the torus.
OpenGL lighting does not do any checking for objects that obscure one another. You would have to do your own ray tracing for this.
| Main Menu | TOC | Previous | Next | Lecture Start |