Animating the camera
CS-116A: Introduction to Computer Graphics
Instructor: Rob Bruce
Fall 2016

SLIDE 1: Animating the camera.

  • In OpenGL, your perspective view is from the camera.
  • The camera can be moved or undergo motion just as you could take a real camera and move it while recording a movie.
  • In the following slides, I will be dissecting a program I created which animates the camera.

SLIDE 2: Animating the camera: main().

  • Step 1 of 11: The skeleton of our main() program.

int main (int argc, char *argv[])
{
}

SLIDE 3: Animating the camera: main().

  • Step 2 of 11: Defining a status variable, window. This variable will eventually hold one of two values:
  • 1 = window successfully created.
  • 0 = window creation failed.

int main (int argc, char *argv[])
{
  int window;
}

SLIDE 4: Animating the camera: main().

  • Step 3 of 11: glutInit() calls the window manager (Microsoft Windows, Apple OSX, X-windows, etc.) to request a window widget. GLUT will report an error if it is unable to successfully create a window.

int main (int argc, char *argv[])
{
  int window;

  glutInit (&argc, argv);
}

SLIDE 5: Animating the camera: main().

  • Step 4 of 11: glutInitDisplayMode() establishes criteria for how windows will be displayed. We want the following:
  • GLUT_RGBA: Default window mode with 32 bits per pixel (R, G, B, A).
  • GLUT_DOUBLE: Use double buffering.
  • GLUT_ALPHA: Window will use the alpha channel.
  • GLUT_DEPTH: Enable depth buffer. This is important for visibility of stacked images.

int main (int argc, char *argv[])
{
  int window;

  glutInit (&argc, argv);
  glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
}

SLIDE 6: Animating the camera: main().

  • Step 5 of 11: glutInitWindowSize() defines the horizontal and vertical pixel resolution of the window we are creating.

int main (int argc, char *argv[])
{
  int window;

  glutInit (&argc, argv);
  glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
  glutInitWindowSize (1280, 720);
}

SLIDE 7: Animating the camera: main().

  • Step 6 of 11: glutInitWindowPosition() defines the location where the window should appear on the user's screen. Note: windowing systems (e.g. Microsoft Windows, OSX, etc.) are not obligated to adhere to this value. GLUT merely passes these values to the windowing manager.

int main (int argc, char *argv[])
{
  int window;

  glutInit (&argc, argv);
  glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
  glutInitWindowSize (1280, 720);
  glutInitWindowPosition (0, 0);
}

SLIDE 8: Animating the camera: main().

  • Step 7 of 11: glutCreateWindow defines the title for the window being created. The text, "Rotating Camera Demonstration" will literally be displayed in the window's title bar. glutcreateWindow() returns 1 on successfully creating the window or 0 on failure.

int main (int argc, char *argv[])
{
  int window;

  glutInit (&argc, argv);
  glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
  glutInitWindowSize (1280, 720);
  glutInitWindowPosition (0, 0);
  window = glutCreateWindow ("Rotating Camera Demonstration");
}

SLIDE 9: Animating the camera: main().

  • Step 8 of 11: Init() is a user defined subroutine. In this subroutine, we will be adding some OpenGL lights so our moving spheres will be visible.

int main (int argc, char *argv[])
{
  int window;

  glutInit (&argc, argv);
  glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
  glutInitWindowSize (1280, 720);
  glutInitWindowPosition (0, 0);
  window = glutCreateWindow ("Rotating Camera Demonstration");
  init ();
}

SLIDE 10: Animating the camera: main().

  • Step 9 of 11: glutDisplayFunc() allows the user to define the subroutine responsible for displaying the current window being defined. The user-defined subroutine determines what is actually displayed in the window we created with glutCreateWindow().

int main (int argc, char *argv[])
{
  int window;

  glutInit (&argc, argv);
  glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
  glutInitWindowSize (1280, 720);
  glutInitWindowPosition (0, 0);
  window = glutCreateWindow ("Rotating Camera Demonstration");
  init ();
  glutDisplayFunc (display);
}

SLIDE 11: Animating the camera: main().

  • Step 10 of 11: glutReshapeFunc() allows the user to define a subroutine to be called when the user resizes their window in the window manager (e.g. Microsoft Windows). For example, a window that displays an image would need to be redrawn if the window were resized. This means scaling the image up or down but maintaining its aspect ratio when redrawing the image (e.g. so the image does not appear squashed or stretched).

int main (int argc, char *argv[])
{
  int window;

  glutInit (&argc, argv);
  glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
  glutInitWindowSize (1280, 720);
  glutInitWindowPosition (0, 0);
  window = glutCreateWindow ("Rotating Camera Demonstration");
  init ();
  glutDisplayFunc (display);
  glutReshapeFunc (reshape);
}

SLIDE 12: Animating the camera: main().

  • Step 11 of 11: glutMainLoop() is GLUT's main event-driven loop to process events in the window manager (e.g. mouse clicks, keyboard presses, window resizing, etc.).

int main (int argc, char *argv[])
{
  int window;

  glutInit (&argc, argv);
  glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
  glutInitWindowSize (1280, 720);
  glutInitWindowPosition (0, 0);
  window = glutCreateWindow ("Rotating Camera Demonstration");
  init ();
  glutDisplayFunc (display);
  glutReshapeFunc (reshape);
  glutMainLoop ();
}

SLIDE 13: Animating the camera: main().

Our main() calls the following user-defined subroutines:

  • init()
  • display()
  • reshape()

We'll dissect init() next...

SLIDE 14: Animating the camera: init().

  • Step 1 of 20: The skeleton of our init() subroutine.

void init (void)
{
}

SLIDE 15: Animating the camera: init().

  • Step 2 of 20: glShadeModel (GL_SMOOTH): Specifies how light should reflect off the surface. The possible values are flat shading or smooth shading. In OpenGL, flat shading draws surfaces quickly but the surfaces can look faceted or geometrically rough. With Smooth shading, OpenGL interpolates light reflections over the entire surface to create a consistently smooth surface appearence. We'll use the GL_SMOOTH option to create a smooth surface appearence.

void init (void)
{
  glShadeModel (GL_SMOOTH);
}

SLIDE 16: Animating the camera: init().

  • Step 3 of 20: glClearColor (1.0f, 1.0f, 1.0f, 0.0f): Specifies the background color of our drawing window (or canvas). In this case, we'll be drawing on a white background with no transparency (no alpha channel).

void init (void)
{
  glShadeModel (GL_SMOOTH);
  glClearColor (1.0f, 1.0f, 1.0f, 0.0f);
}

SLIDE 17: Animating the camera: init().

  • Step 4 of 20: glClearDepth (1.0f): specifies a threshold to determine what is visible in the far clipping plane in terms of z-depth. The default value is 1.0. OpenGL needs to determine and draw only those portions of a surface that are visible between the near and far clipping planes. Remember: OpenGL is projecting a 3-dimensional image onto a 2-dimensional screen. What dimensional parts are invisible because of clipping plane? This is all determined through depth testing and pre-defined value for the depth threshold.

void init (void)
{
  glShadeModel (GL_SMOOTH);
  glClearColor (1.0f, 1.0f, 1.0f, 0.0f);
  glClearDepth (1.0f);
}

SLIDE 18: Animating the camera: init().

  • Step 5 of 20: glEnable (GL_DEPTH_TEST): We are enabling depth testing in OpenGL to determine what portions of a surface to display between near and far clipping planes.

void init (void)
{
  glShadeModel (GL_SMOOTH);
  glClearColor (1.0f, 1.0f, 1.0f, 0.0f);
  glClearDepth (1.0f);
  glEnable (GL_DEPTH_TEST);
}

SLIDE 19: Animating the camera: init().

  • Step 6 of 20: glDepthFunc (GL_LEQUAL): Used to determine if a given pixel passes the depth-test function. Any pixel less than or equal to 1.0 (defined early with glClearDepth) will pass this function.

void init (void)
{
  glShadeModel (GL_SMOOTH);
  glClearColor (1.0f, 1.0f, 1.0f, 0.0f);
  glClearDepth (1.0f);
  glEnable (GL_DEPTH_TEST);
  glDepthFunc (GL_LEQUAL);
}

SLIDE 20: Animating the camera: init().

  • Step 7 of 20: glEnable (GL_COLOR_MATERIAL): tells OpenGL to display the surface's color when light is reflected off that surface.

void init (void)
{
  glShadeModel (GL_SMOOTH);
  glClearColor (1.0f, 1.0f, 1.0f, 0.0f);
  glClearDepth (1.0f);
  glEnable (GL_DEPTH_TEST);
  glDepthFunc (GL_LEQUAL);
  glEnable (GL_COLOR_MATERIAL);
}

SLIDE 21: Animating the camera: init().

  • Step 8 of 20: glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST): tells OpenGL to use the highest quality color render settings when drawing with lights cast on the surface.

void init (void)
{
  glShadeModel (GL_SMOOTH);
  glClearColor (1.0f, 1.0f, 1.0f, 0.0f);
  glClearDepth (1.0f);
  glEnable (GL_DEPTH_TEST);
  glDepthFunc (GL_LEQUAL);
  glEnable (GL_COLOR_MATERIAL);
  glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}

SLIDE 22: Animating the camera: init().

  • Step 9 of 20: glEnable (GL_LIGHTING): computes the color to display on a polygon based on the lights that shine on the surface.

void init (void)
{
  glShadeModel (GL_SMOOTH);
  glClearColor (1.0f, 1.0f, 1.0f, 0.0f);
  glClearDepth (1.0f);
  glEnable (GL_DEPTH_TEST);
  glDepthFunc (GL_LEQUAL);
  glEnable (GL_COLOR_MATERIAL);
  glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  glEnable (GL_LIGHTING);
}

SLIDE 23: Animating the camera: init().

  • Step 10 of 20: glEnable (GL_LIGHT0): LIGHT 0 influences the surface color of polygons.

void init (void)
{
  glShadeModel (GL_SMOOTH);
  glClearColor (1.0f, 1.0f, 1.0f, 0.0f);
  glClearDepth (1.0f);
  glEnable (GL_DEPTH_TEST);
  glDepthFunc (GL_LEQUAL);
  glEnable (GL_COLOR_MATERIAL);
  glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  glEnable (GL_LIGHTING);
  glEnable (GL_LIGHT0);
}

SLIDE 24: Animating the camera: init().

  • Step 11 of 20: Defining a floating point type (GLfloat) array, lightPos with four elements related to lighting position.

void init (void)
{
  glShadeModel (GL_SMOOTH);
  glClearColor (1.0f, 1.0f, 1.0f, 0.0f);
  glClearDepth (1.0f);
  glEnable (GL_DEPTH_TEST);
  glDepthFunc (GL_LEQUAL);
  glEnable (GL_COLOR_MATERIAL);
  glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  glEnable (GL_LIGHTING);
  glEnable (GL_LIGHT0);
  GLfloat lightPos[4] = {-1.0, 1.0, 0.5, 0.0};
}

SLIDE 25: Animating the camera: init().

  • Step 12 of 20: glLightfv (GL_LIGHT0, GL_POSITION, (GLfloat *) &lightPos): enables a light source in OpenGL with parameters defined by GL_LIGHT 0.

void init (void)
{
  glShadeModel (GL_SMOOTH);
  glClearColor (1.0f, 1.0f, 1.0f, 0.0f);
  glClearDepth (1.0f);
  glEnable (GL_DEPTH_TEST);
  glDepthFunc (GL_LEQUAL);
  glEnable (GL_COLOR_MATERIAL);
  glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  glEnable (GL_LIGHTING);
  glEnable (GL_LIGHT0);
  GLfloat lightPos[4] = {-1.0, 1.0, 0.5, 0.0};
  glLightfv (GL_LIGHT0, GL_POSITION, (GLfloat *) &lightPos);
}

SLIDE 26: Animating the camera: init().

  • Step 13 of 20: glEnable (GL_LIGHT1): GL_LIGHT 1 influences the surface color of polygons.

void init (void)
{
  glShadeModel (GL_SMOOTH);
  glClearColor (1.0f, 1.0f, 1.0f, 0.0f);
  glClearDepth (1.0f);
  glEnable (GL_DEPTH_TEST);
  glDepthFunc (GL_LEQUAL);
  glEnable (GL_COLOR_MATERIAL);
  glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  glEnable (GL_LIGHTING);
  glEnable (GL_LIGHT0);
  GLfloat lightPos[4] = {-1.0, 1.0, 0.5, 0.0};
  glLightfv (GL_LIGHT0, GL_POSITION, (GLfloat *) &lightPos);
  glEnable (GL_LIGHT1);
}

SLIDE 27: Animating the camera: init().

  • Step 14 of 20: Defining a floating point type (GLfloat) array, lightAmbient1 with four elements referring to the ambient light intensity of the red, green, blue, and alpha channels.

void init (void)
{
  glShadeModel (GL_SMOOTH);
  glClearColor (1.0f, 1.0f, 1.0f, 0.0f);
  glClearDepth (1.0f);
  glEnable (GL_DEPTH_TEST);
  glDepthFunc (GL_LEQUAL);
  glEnable (GL_COLOR_MATERIAL);
  glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  glEnable (GL_LIGHTING);
  glEnable (GL_LIGHT0);
  GLfloat lightPos[4] = {-1.0, 1.0, 0.5, 0.0};
  glLightfv (GL_LIGHT0, GL_POSITION, (GLfloat *) &lightPos);
  glEnable (GL_LIGHT1);
  GLfloat lightAmbient1[4] = {0.0, 0.0, 0.0, 0.0};
}

SLIDE 28: Animating the camera: init().

  • Step 15 of 20: Defining a floating point type (GLfloat) array, lightPos1 with four elements used for defining light position.

void init (void)
{
  glShadeModel (GL_SMOOTH);
  glClearColor (1.0f, 1.0f, 1.0f, 0.0f);
  glClearDepth (1.0f);
  glEnable (GL_DEPTH_TEST);
  glDepthFunc (GL_LEQUAL);
  glEnable (GL_COLOR_MATERIAL);
  glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  glEnable (GL_LIGHTING);
  glEnable (GL_LIGHT0);
  GLfloat lightPos[4] = {-1.0, 1.0, 0.5, 0.0};
  glLightfv (GL_LIGHT0, GL_POSITION, (GLfloat *) &lightPos);
  glEnable (GL_LIGHT1);
  GLfloat lightAmbient1[4] = {0.0, 0.0, 0.0, 0.0};
  GLfloat lightPos1[4] = {1.0, 0.0, -0.2, 0.0};
}

SLIDE 29: Animating the camera: init().

  • Step 16 of 20: Defining a floating point type (GLfloat) array, lightDiffuse1 with the four elements referring to intensities for the red, green, blue, and alpha channels.

void init (void)
{
  glShadeModel (GL_SMOOTH);
  glClearColor (1.0f, 1.0f, 1.0f, 0.0f);
  glClearDepth (1.0f);
  glEnable (GL_DEPTH_TEST);
  glDepthFunc (GL_LEQUAL);
  glEnable (GL_COLOR_MATERIAL);
  glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  glEnable (GL_LIGHTING);
  glEnable (GL_LIGHT0);
  GLfloat lightPos[4] = {-1.0, 1.0, 0.5, 0.0};
  glLightfv (GL_LIGHT0, GL_POSITION, (GLfloat *) &lightPos);
  glEnable (GL_LIGHT1);
  GLfloat lightAmbient1[4] = {0.0, 0.0, 0.0, 0.0};
  GLfloat lightPos1[4] = {1.0, 0.0, -0.2, 0.0};
  GLfloat lightDiffuse1[4] = {0.5, 0.5, 0.3, 0.0};
}

SLIDE 30: Animating the camera: init().

  • Step 17 of 20: glLightfv (GL_LIGHT1, GL_POSITION, (GLfloat *) &lightPos1): specifies the position for GL_LIGHT 1.

void init (void)
{
  glShadeModel (GL_SMOOTH);
  glClearColor (1.0f, 1.0f, 1.0f, 0.0f);
  glClearDepth (1.0f);
  glEnable (GL_DEPTH_TEST);
  glDepthFunc (GL_LEQUAL);
  glEnable (GL_COLOR_MATERIAL);
  glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  glEnable (GL_LIGHTING);
  glEnable (GL_LIGHT0);
  GLfloat lightPos[4] = {-1.0, 1.0, 0.5, 0.0};
  glLightfv (GL_LIGHT0, GL_POSITION, (GLfloat *) &lightPos);
  glEnable (GL_LIGHT1);
  GLfloat lightAmbient1[4] = {0.0, 0.0, 0.0, 0.0};
  GLfloat lightPos1[4] = {1.0, 0.0, -0.2, 0.0};
  GLfloat lightDiffuse1[4] = {0.5, 0.5, 0.3, 0.0};
  glLightfv (GL_LIGHT1, GL_POSITION, (GLfloat *) &lightPos1);
}

SLIDE 31: Animating the camera: init().

  • Step 18 of 20: glLightfv (GL_LIGHT1, GL_AMBIENT, (GLfloat *) &lightAmbient1): defines the ambient light intensities for the red, green, blue, and alpha channels for GL_LIGHT 1.

void init (void)
{
  glShadeModel (GL_SMOOTH);
  glClearColor (1.0f, 1.0f, 1.0f, 0.0f);
  glClearDepth (1.0f);
  glEnable (GL_DEPTH_TEST);
  glDepthFunc (GL_LEQUAL);
  glEnable (GL_COLOR_MATERIAL);
  glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  glEnable (GL_LIGHTING);
  glEnable (GL_LIGHT0);
  GLfloat lightPos[4] = {-1.0, 1.0, 0.5, 0.0};
  glLightfv (GL_LIGHT0, GL_POSITION, (GLfloat *) &lightPos);
  glEnable (GL_LIGHT1);
  GLfloat lightAmbient1[4] = {0.0, 0.0, 0.0, 0.0};
  GLfloat lightPos1[4] = {1.0, 0.0, -0.2, 0.0};
  GLfloat lightDiffuse1[4] = {0.5, 0.5, 0.3, 0.0};
  glLightfv (GL_LIGHT1, GL_POSITION, (GLfloat *) &lightPos1);
  glLightfv (GL_LIGHT1, GL_AMBIENT, (GLfloat *) &lightAmbient1);
}

SLIDE 31: Animating the camera: init().

  • Step 19 of 20: glLightfv (GL_LIGHT1, GL_DIFFUSE, (GLfloat *) &lightDiffuse1): defines the diffused light intensities for the red, green, blue, and alpha channels for GL_LIGHT 1.

void init (void)
{
  glShadeModel (GL_SMOOTH);
  glClearColor (1.0f, 1.0f, 1.0f, 0.0f);
  glClearDepth (1.0f);
  glEnable (GL_DEPTH_TEST);
  glDepthFunc (GL_LEQUAL);
  glEnable (GL_COLOR_MATERIAL);
  glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  glEnable (GL_LIGHTING);
  glEnable (GL_LIGHT0);
  GLfloat lightPos[4] = {-1.0, 1.0, 0.5, 0.0};
  glLightfv (GL_LIGHT0, GL_POSITION, (GLfloat *) &lightPos);
  glEnable (GL_LIGHT1);
  GLfloat lightAmbient1[4] = {0.0, 0.0, 0.0, 0.0};
  GLfloat lightPos1[4] = {1.0, 0.0, -0.2, 0.0};
  GLfloat lightDiffuse1[4] = {0.5, 0.5, 0.3, 0.0};
  glLightfv (GL_LIGHT1, GL_POSITION, (GLfloat *) &lightPos1);
  glLightfv (GL_LIGHT1, GL_AMBIENT, (GLfloat *) &lightAmbient1);
  glLightfv (GL_LIGHT1, GL_DIFFUSE, (GLfloat *) &lightDiffuse1);
}

SLIDE 32: Animating the camera: init().

  • Step 20 of 20: glLightModeli (GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE): Enable two-sided lighting for polygonal surfaces (front and back of polygon).

void init (void)
{
  glShadeModel (GL_SMOOTH);
  glClearColor (1.0f, 1.0f, 1.0f, 0.0f);
  glClearDepth (1.0f);
  glEnable (GL_DEPTH_TEST);
  glDepthFunc (GL_LEQUAL);
  glEnable (GL_COLOR_MATERIAL);
  glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  glEnable (GL_LIGHTING);
  glEnable (GL_LIGHT0);
  GLfloat lightPos[4] = {-1.0, 1.0, 0.5, 0.0};
  glLightfv (GL_LIGHT0, GL_POSITION, (GLfloat *) &lightPos);
  glEnable (GL_LIGHT1);
  GLfloat lightAmbient1[4] = {0.0, 0.0, 0.0, 0.0};
  GLfloat lightPos1[4] = {1.0, 0.0, -0.2, 0.0};
  GLfloat lightDiffuse1[4] = {0.5, 0.5, 0.3, 0.0};
  glLightfv (GL_LIGHT1, GL_POSITION, (GLfloat *) &lightPos1);
  glLightfv (GL_LIGHT1, GL_AMBIENT, (GLfloat *) &lightAmbient1);
  glLightfv (GL_LIGHT1, GL_DIFFUSE, (GLfloat *) &lightDiffuse1);
  glLightModeli (GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
}

SLIDE 33: Animating the camera: main().

Our main() calls the following user-defined subroutines:

  • init()
  • display()
  • reshape()

We'll dissect display() next...

SLIDE 34: Animating the camera: display().

  • Step 1 of 48: Skeleton of the display() subroutine.

void display (void)
{
}

SLIDE 35: Animating the camera: display().

  • Step 2 of 48: Defining the variable to store the radius for each of the spheres.

void display (void)
{
  float sphere_radius;
}

SLIDE 36: Animating the camera: display().

  • Step 3 of 48: Defining the variables to store the Cartesian (X,Y,Z) coordinates for the location of the red sphere.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
}

SLIDE 37: Animating the camera: display().

  • Step 4 of 48: Defining the variables to store the Cartesian (X,Y,Z) coordinates for the location of the green sphere.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
}

SLIDE 38: Animating the camera: display().

  • Step 5 of 48: Defining the variables to store the Cartesian (X,Y,Z) coordinates for the location of the blue sphere.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
}

SLIDE 39: Animating the camera: display().

  • Step 6 of 48: Defining the variables to store the Cartesian (X,Y,Z) coordinates for the location of the camera.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
}

SLIDE 40: Animating the camera: display().

  • Step 7 of 48: The variables center_x, center_y, and center_z store the location (Cartesian coordinates) where the camera will be focused (i.e. where the camera will be "looking").

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
}

SLIDE 41: Animating the camera: display().

  • Step 8 of 48: The variable camera_angle_radians will store the current angle of the camera in radians (as opposed to degrees) because the sine and cosine functions expect the angle in radians, not degrees.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
}

SLIDE 42: Animating the camera: display().

  • Step 9 of 48: Each sphere will have a radius of 1.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
}

SLIDE 43: Animating the camera: display().

  • Step 10 of 48: The spheres are all being plotted on the (x,z) plane. Therefore, the Y axis for each sphere will be the same. The red sphere's Y coordinate will be (-6).

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
}

SLIDE 44: Animating the camera: display().

  • Step 11 of 48: The green sphere's Y coordinate will be (-6).

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
}

SLIDE 45: Animating the camera: display().

  • Step 12 of 48: The blue sphere's Y coordinate will be (-6).

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
}

SLIDE 46: Animating the camera: display().

  • Step 13 of 48: The red sphere will have an X coordinate of 6.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
}

SLIDE 47: Animating the camera: display().

  • Step 14 of 48: The red sphere will have a Z coordinate of (-3.25).

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
}

SLIDE 48: Animating the camera: display().

  • Step 15 of 48: The green sphere will have an X coordinate of 5.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
}

SLIDE 49: Animating the camera: display().

  • Step 16 of 48: The green sphere will have a Z coordinate of (-5).

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
}

SLIDE 50: Animating the camera: display().

  • Step 17 of 48: The blue sphere will have an X coordinate of 7.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
}

SLIDE 51: Animating the camera: display().

  • Step 18 of 48: The blue sphere will have a Z coordinate of (-5).

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
}

SLIDE 52: Animating the camera: display().

  • Step 19 of 48: The red, green, and blue spheres are arranged in a triangular pattern adjacent to each other. The variable center_x represents the absolute center of the three spheres in the X plane. The camera will be focused on this point.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
  center_x = (red_sphere_position_x + green_sphere_position_x + blue_sphere_position_x) / 3.0f;
}

SLIDE 53: Animating the camera: display().

  • Step 20 of 48: Since the red, green, and blue spheres are being drawn in the (X,Z) plane, the spheres are all level at Y=(-6). The camera's Y coordinate for focus is therefore set to (-6).

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
  center_x = (red_sphere_position_x + green_sphere_position_x + blue_sphere_position_x) / 3.0f;
  center_y = -6.0f;
}

SLIDE 54: Animating the camera: display().

  • Step 21 of 48: The red, green, and blue spheres are arranged in a triangular pattern adjacent to each other. The variable center_z represents the absolute center of the three spheres in the Z plane. The camera will be focused on this point.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
  center_x = (red_sphere_position_x + green_sphere_position_x + blue_sphere_position_x) / 3.0f;
  center_y = -6.0f;
  center_z = (red_sphere_position_z + green_sphere_position_z + blue_sphere_position_z) / 3.0f;
}

SLIDE 55: Animating the camera: display().

  • Step 22 of 48: The camera will be spinning around in circles in one-degree increments. When the camera has reached 360 degrees, it will be reset to zero degrees again.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
  center_x = (red_sphere_position_x + green_sphere_position_x + blue_sphere_position_x) / 3.0f;
  center_y = -6.0f;
  center_z = (red_sphere_position_z + green_sphere_position_z + blue_sphere_position_z) / 3.0f;
  if (camera_angle_degrees >= 360.0f)
  {
  }
  else
  {
  }
}

SLIDE 56: Animating the camera: display().

  • Step 23 of 48: Here we set the camera back to zero degrees.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
  center_x = (red_sphere_position_x + green_sphere_position_x + blue_sphere_position_x) / 3.0f;
  center_y = -6.0f;
  center_z = (red_sphere_position_z + green_sphere_position_z + blue_sphere_position_z) / 3.0f;
  if (camera_angle_degrees >= 360.0f)
  {
    camera_angle_degrees = 0;
  }
  else
  {
  }
}

SLIDE 57: Animating the camera: display().

  • Step 24 of 48: The camera hasn't turned a complete revolution yet so increment by another degree.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
  center_x = (red_sphere_position_x + green_sphere_position_x + blue_sphere_position_x) / 3.0f;
  center_y = -6.0f;
  center_z = (red_sphere_position_z + green_sphere_position_z + blue_sphere_position_z) / 3.0f;
  if (camera_angle_degrees >= 360.0f)
  {
    camera_angle_degrees = 0;
  }
  else
  {
    camera_angle_degrees = camera_angle_degrees + 1.0f;
  }
}

SLIDE 58: Animating the camera: display().

  • Step 25 of 48: Convert the camera's degree rotation into radians since sine and cosine functions accept input in radians, not degrees.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
  center_x = (red_sphere_position_x + green_sphere_position_x + blue_sphere_position_x) / 3.0f;
  center_y = -6.0f;
  center_z = (red_sphere_position_z + green_sphere_position_z + blue_sphere_position_z) / 3.0f;
  if (camera_angle_degrees >= 360.0f)
  {
    camera_angle_degrees = 0;
  }
  else
  {
    camera_angle_degrees = camera_angle_degrees + 1.0f;
  }
  camera_angle_radians = camera_angle_degrees * M_PI / 180.0f;
}

SLIDE 59: Animating the camera: display().

  • Step 26 of 48: The camera will have a turning radius of 6 and be offset by 6. This is done so the camera can completely encapsulate the three spheres as it rotates around them. The spheres were not originally drawn at the origin (0,0,0) so we add the 6 offset since that represents the offset where the spheres were drawn.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
  center_x = (red_sphere_position_x + green_sphere_position_x + blue_sphere_position_x) / 3.0f;
  center_y = -6.0f;
  center_z = (red_sphere_position_z + green_sphere_position_z + blue_sphere_position_z) / 3.0f;
  if (camera_angle_degrees >= 360.0f)
  {
    camera_angle_degrees = 0;
  }
  else
  {
    camera_angle_degrees = camera_angle_degrees + 1.0f;
  }
  camera_angle_radians = camera_angle_degrees * M_PI / 180.0f;
  camera_position_x = sin(camera_angle_radians) * 6.0f + 6.0f;
}

SLIDE 60: Animating the camera: display().

  • Step 27 of 48: The camera's is rotated about the X-Z plane. In the Y plane, the camera is held at a constant value of (-6). The Y plane would move the camera up and down. We want the camera to move horizontally. That is why it moves in the X-Z plane.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
  center_x = (red_sphere_position_x + green_sphere_position_x + blue_sphere_position_x) / 3.0f;
  center_y = -6.0f;
  center_z = (red_sphere_position_z + green_sphere_position_z + blue_sphere_position_z) / 3.0f;
  if (camera_angle_degrees >= 360.0f)
  {
    camera_angle_degrees = 0;
  }
  else
  {
    camera_angle_degrees = camera_angle_degrees + 1.0f;
  }
  camera_angle_radians = camera_angle_degrees * M_PI / 180.0f;
  camera_position_x = sin(camera_angle_radians) * 6.0f + 6.0f;
  camera_position_y = -6.0f;
}

SLIDE 61: Animating the camera: display().

  • Step 28 of 48: The camera radius in the Z plane is also set to 6. The -4.5 represents the offset of the three spheres from the origin.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
  center_x = (red_sphere_position_x + green_sphere_position_x + blue_sphere_position_x) / 3.0f;
  center_y = -6.0f;
  center_z = (red_sphere_position_z + green_sphere_position_z + blue_sphere_position_z) / 3.0f;
  if (camera_angle_degrees >= 360.0f)
  {
    camera_angle_degrees = 0;
  }
  else
  {
    camera_angle_degrees = camera_angle_degrees + 1.0f;
  }
  camera_angle_radians = camera_angle_degrees * M_PI / 180.0f;
  camera_position_x = sin(camera_angle_radians) * 6.0f + 6.0f;
  camera_position_y = -6.0f;
  camera_position_z = cos(camera_angle_radians) * 6.0f - 4.50f;
}

SLIDE 62: Animating the camera: display().

  • Step 29 of 48: glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) clears the color and depth buffers.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
  center_x = (red_sphere_position_x + green_sphere_position_x + blue_sphere_position_x) / 3.0f;
  center_y = -6.0f;
  center_z = (red_sphere_position_z + green_sphere_position_z + blue_sphere_position_z) / 3.0f;
  if (camera_angle_degrees >= 360.0f)
  {
    camera_angle_degrees = 0;
  }
  else
  {
    camera_angle_degrees = camera_angle_degrees + 1.0f;
  }
  camera_angle_radians = camera_angle_degrees * M_PI / 180.0f;
  camera_position_x = sin(camera_angle_radians) * 6.0f + 6.0f;
  camera_position_y = -6.0f;
  camera_position_z = cos(camera_angle_radians) * 6.0f - 4.50f;
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}

SLIDE 63: Animating the camera: display().

  • Step 30 of 48: Initialize the project and modelview matrices to the default state. Matrix manipulation is cummulative. This can lead to some weird transformations if we don't initialize it before drawing!

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
  center_x = (red_sphere_position_x + green_sphere_position_x + blue_sphere_position_x) / 3.0f;
  center_y = -6.0f;
  center_z = (red_sphere_position_z + green_sphere_position_z + blue_sphere_position_z) / 3.0f;
  if (camera_angle_degrees >= 360.0f)
  {
    camera_angle_degrees = 0;
  }
  else
  {
    camera_angle_degrees = camera_angle_degrees + 1.0f;
  }
  camera_angle_radians = camera_angle_degrees * M_PI / 180.0f;
  camera_position_x = sin(camera_angle_radians) * 6.0f + 6.0f;
  camera_position_y = -6.0f;
  camera_position_z = cos(camera_angle_radians) * 6.0f - 4.50f;
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity ();
}

SLIDE 64: Animating the camera: display().

  • Step 31 of 48: Define the location of the camera and the position where the camera is "looking". This is the key function that moves the camera.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
  center_x = (red_sphere_position_x + green_sphere_position_x + blue_sphere_position_x) / 3.0f;
  center_y = -6.0f;
  center_z = (red_sphere_position_z + green_sphere_position_z + blue_sphere_position_z) / 3.0f;
  if (camera_angle_degrees >= 360.0f)
  {
    camera_angle_degrees = 0;
  }
  else
  {
    camera_angle_degrees = camera_angle_degrees + 1.0f;
  }
  camera_angle_radians = camera_angle_degrees * M_PI / 180.0f;
  camera_position_x = sin(camera_angle_radians) * 6.0f + 6.0f;
  camera_position_y = -6.0f;
  camera_position_z = cos(camera_angle_radians) * 6.0f - 4.50f;
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity ();
  gluLookAt (camera_position_x, camera_position_y, camera_position_z, center_x, center_y, center_z, 0.0f, 1.0f, 0.0f);
}

SLIDE 65: Animating the camera: display().

  • Step 32 of 48: Temporarily store the current matrix view on a stack to preserve its value.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
  center_x = (red_sphere_position_x + green_sphere_position_x + blue_sphere_position_x) / 3.0f;
  center_y = -6.0f;
  center_z = (red_sphere_position_z + green_sphere_position_z + blue_sphere_position_z) / 3.0f;
  if (camera_angle_degrees >= 360.0f)
  {
    camera_angle_degrees = 0;
  }
  else
  {
    camera_angle_degrees = camera_angle_degrees + 1.0f;
  }
  camera_angle_radians = camera_angle_degrees * M_PI / 180.0f;
  camera_position_x = sin(camera_angle_radians) * 6.0f + 6.0f;
  camera_position_y = -6.0f;
  camera_position_z = cos(camera_angle_radians) * 6.0f - 4.50f;
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity ();
  gluLookAt (camera_position_x, camera_position_y, camera_position_z, center_x, center_y, center_z, 0.0f, 1.0f, 0.0f);
  glPushMatrix ();
}

SLIDE 66: Animating the camera: display().

  • Step 33 of 48: The glTranslatef() function uses transformation matrices to position an object (in our case a sphere) at a given location on the screen. Unfortunately, glTranslatef() permanently transforms our view matrix. That's why we previously used a push function to retain a copy of the matrix before this operation. every glTranslatef() function is cumulative. That is why there are a serious of push/pop, push/pop, push/pop as we translate then draw each sphere in its appropriate location.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
  center_x = (red_sphere_position_x + green_sphere_position_x + blue_sphere_position_x) / 3.0f;
  center_y = -6.0f;
  center_z = (red_sphere_position_z + green_sphere_position_z + blue_sphere_position_z) / 3.0f;
  if (camera_angle_degrees >= 360.0f)
  {
    camera_angle_degrees = 0;
  }
  else
  {
    camera_angle_degrees = camera_angle_degrees + 1.0f;
  }
  camera_angle_radians = camera_angle_degrees * M_PI / 180.0f;
  camera_position_x = sin(camera_angle_radians) * 6.0f + 6.0f;
  camera_position_y = -6.0f;
  camera_position_z = cos(camera_angle_radians) * 6.0f - 4.50f;
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity ();
  gluLookAt (camera_position_x, camera_position_y, camera_position_z, center_x, center_y, center_z, 0.0f, 1.0f, 0.0f);
  glPushMatrix ();
  glTranslatef (red_sphere_position_x, red_sphere_position_y, red_sphere_position_z);
}

SLIDE 67: Animating the camera: display().

  • Step 34 of 48: Defines the color of the sphere as pure red.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
  center_x = (red_sphere_position_x + green_sphere_position_x + blue_sphere_position_x) / 3.0f;
  center_y = -6.0f;
  center_z = (red_sphere_position_z + green_sphere_position_z + blue_sphere_position_z) / 3.0f;
  if (camera_angle_degrees >= 360.0f)
  {
    camera_angle_degrees = 0;
  }
  else
  {
    camera_angle_degrees = camera_angle_degrees + 1.0f;
  }
  camera_angle_radians = camera_angle_degrees * M_PI / 180.0f;
  camera_position_x = sin(camera_angle_radians) * 6.0f + 6.0f;
  camera_position_y = -6.0f;
  camera_position_z = cos(camera_angle_radians) * 6.0f - 4.50f;
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity ();
  gluLookAt (camera_position_x, camera_position_y, camera_position_z, center_x, center_y, center_z, 0.0f, 1.0f, 0.0f);
  glPushMatrix ();
  glTranslatef (red_sphere_position_x, red_sphere_position_y, red_sphere_position_z);
  glColor3f (1.0f, 0.0f, 0.0f);
}

SLIDE 68: Animating the camera: display().

  • Step 35 of 48: Draw a high quality sphere. The 50, 50 values refer to number of mesh subdivisions in the sphere. The values I am using will create a high resolution, smooth sphere.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
  center_x = (red_sphere_position_x + green_sphere_position_x + blue_sphere_position_x) / 3.0f;
  center_y = -6.0f;
  center_z = (red_sphere_position_z + green_sphere_position_z + blue_sphere_position_z) / 3.0f;
  if (camera_angle_degrees >= 360.0f)
  {
    camera_angle_degrees = 0;
  }
  else
  {
    camera_angle_degrees = camera_angle_degrees + 1.0f;
  }
  camera_angle_radians = camera_angle_degrees * M_PI / 180.0f;
  camera_position_x = sin(camera_angle_radians) * 6.0f + 6.0f;
  camera_position_y = -6.0f;
  camera_position_z = cos(camera_angle_radians) * 6.0f - 4.50f;
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity ();
  gluLookAt (camera_position_x, camera_position_y, camera_position_z, center_x, center_y, center_z, 0.0f, 1.0f, 0.0f);
  glPushMatrix ();
  glTranslatef (red_sphere_position_x, red_sphere_position_y, red_sphere_position_z);
  glColor3f (1.0f, 0.0f, 0.0f);
  glutSolidSphere (sphere_radius, 50, 50);
}

SLIDE 69: Animating the camera: display().

  • Step 36 of 48: Now restore the view matrix to its state before the last glTranslatef() function. Remember: glTranslatef() manipulations are cumulative. We get around this by restoring the view after each manipulation.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
  center_x = (red_sphere_position_x + green_sphere_position_x + blue_sphere_position_x) / 3.0f;
  center_y = -6.0f;
  center_z = (red_sphere_position_z + green_sphere_position_z + blue_sphere_position_z) / 3.0f;
  if (camera_angle_degrees >= 360.0f)
  {
    camera_angle_degrees = 0;
  }
  else
  {
    camera_angle_degrees = camera_angle_degrees + 1.0f;
  }
  camera_angle_radians = camera_angle_degrees * M_PI / 180.0f;
  camera_position_x = sin(camera_angle_radians) * 6.0f + 6.0f;
  camera_position_y = -6.0f;
  camera_position_z = cos(camera_angle_radians) * 6.0f - 4.50f;
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity ();
  gluLookAt (camera_position_x, camera_position_y, camera_position_z, center_x, center_y, center_z, 0.0f, 1.0f, 0.0f);
  glPushMatrix ();
  glTranslatef (red_sphere_position_x, red_sphere_position_y, red_sphere_position_z);
  glColor3f (1.0f, 0.0f, 0.0f);
  glutSolidSphere (sphere_radius, 50, 50);
  glPopMatrix ();
}

SLIDE 70: Animating the camera: display().

  • Step 37 of 48: Use glPushMatrix() again so the modelview matrix can be restored after we do another subsequent glTranslatef matrix manipulation to draw our second sphere.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
  center_x = (red_sphere_position_x + green_sphere_position_x + blue_sphere_position_x) / 3.0f;
  center_y = -6.0f;
  center_z = (red_sphere_position_z + green_sphere_position_z + blue_sphere_position_z) / 3.0f;
  if (camera_angle_degrees >= 360.0f)
  {
    camera_angle_degrees = 0;
  }
  else
  {
    camera_angle_degrees = camera_angle_degrees + 1.0f;
  }
  camera_angle_radians = camera_angle_degrees * M_PI / 180.0f;
  camera_position_x = sin(camera_angle_radians) * 6.0f + 6.0f;
  camera_position_y = -6.0f;
  camera_position_z = cos(camera_angle_radians) * 6.0f - 4.50f;
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity ();
  gluLookAt (camera_position_x, camera_position_y, camera_position_z, center_x, center_y, center_z, 0.0f, 1.0f, 0.0f);
  glPushMatrix ();
  glTranslatef (red_sphere_position_x, red_sphere_position_y, red_sphere_position_z);
  glColor3f (1.0f, 0.0f, 0.0f);
  glutSolidSphere (sphere_radius, 50, 50);
  glPopMatrix ();
  glPushMatrix ();
}

SLIDE 71: Animating the camera: display().

  • Step 38 of 48: Define the location where the green sphere will be drawn using glTranslatef().

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
  center_x = (red_sphere_position_x + green_sphere_position_x + blue_sphere_position_x) / 3.0f;
  center_y = -6.0f;
  center_z = (red_sphere_position_z + green_sphere_position_z + blue_sphere_position_z) / 3.0f;
  if (camera_angle_degrees >= 360.0f)
  {
    camera_angle_degrees = 0;
  }
  else
  {
    camera_angle_degrees = camera_angle_degrees + 1.0f;
  }
  camera_angle_radians = camera_angle_degrees * M_PI / 180.0f;
  camera_position_x = sin(camera_angle_radians) * 6.0f + 6.0f;
  camera_position_y = -6.0f;
  camera_position_z = cos(camera_angle_radians) * 6.0f - 4.50f;
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity ();
  gluLookAt (camera_position_x, camera_position_y, camera_position_z, center_x, center_y, center_z, 0.0f, 1.0f, 0.0f);
  glPushMatrix ();
  glTranslatef (red_sphere_position_x, red_sphere_position_y, red_sphere_position_z);
  glColor3f (1.0f, 0.0f, 0.0f);
  glutSolidSphere (sphere_radius, 50, 50);
  glPopMatrix ();
  glPushMatrix ();
  glTranslatef (green_sphere_position_x, green_sphere_position_y, green_sphere_position_z);
}

SLIDE 72: Animating the camera: display().

  • Step 39 of 48: Define the color for the second sphere as pure green.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
  center_x = (red_sphere_position_x + green_sphere_position_x + blue_sphere_position_x) / 3.0f;
  center_y = -6.0f;
  center_z = (red_sphere_position_z + green_sphere_position_z + blue_sphere_position_z) / 3.0f;
  if (camera_angle_degrees >= 360.0f)
  {
    camera_angle_degrees = 0;
  }
  else
  {
    camera_angle_degrees = camera_angle_degrees + 1.0f;
  }
  camera_angle_radians = camera_angle_degrees * M_PI / 180.0f;
  camera_position_x = sin(camera_angle_radians) * 6.0f + 6.0f;
  camera_position_y = -6.0f;
  camera_position_z = cos(camera_angle_radians) * 6.0f - 4.50f;
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity ();
  gluLookAt (camera_position_x, camera_position_y, camera_position_z, center_x, center_y, center_z, 0.0f, 1.0f, 0.0f);
  glPushMatrix ();
  glTranslatef (red_sphere_position_x, red_sphere_position_y, red_sphere_position_z);
  glColor3f (1.0f, 0.0f, 0.0f);
  glutSolidSphere (sphere_radius, 50, 50);
  glPopMatrix ();
  glPushMatrix ();
  glTranslatef (green_sphere_position_x, green_sphere_position_y, green_sphere_position_z);
  glColor3f (0.0f, 1.0f, 0.0f);
}

SLIDE 73: Animating the camera: display().

  • Step 40 of 48: Draw a high quality sphere. The 50, 50 values refer to number of mesh subdivisions in the sphere. The values I am using will create a high resolution, smooth sphere.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
  center_x = (red_sphere_position_x + green_sphere_position_x + blue_sphere_position_x) / 3.0f;
  center_y = -6.0f;
  center_z = (red_sphere_position_z + green_sphere_position_z + blue_sphere_position_z) / 3.0f;
  if (camera_angle_degrees >= 360.0f)
  {
    camera_angle_degrees = 0;
  }
  else
  {
    camera_angle_degrees = camera_angle_degrees + 1.0f;
  }
  camera_angle_radians = camera_angle_degrees * M_PI / 180.0f;
  camera_position_x = sin(camera_angle_radians) * 6.0f + 6.0f;
  camera_position_y = -6.0f;
  camera_position_z = cos(camera_angle_radians) * 6.0f - 4.50f;
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity ();
  gluLookAt (camera_position_x, camera_position_y, camera_position_z, center_x, center_y, center_z, 0.0f, 1.0f, 0.0f);
  glPushMatrix ();
  glTranslatef (red_sphere_position_x, red_sphere_position_y, red_sphere_position_z);
  glColor3f (1.0f, 0.0f, 0.0f);
  glutSolidSphere (sphere_radius, 50, 50);
  glPopMatrix ();
  glPushMatrix ();
  glTranslatef (green_sphere_position_x, green_sphere_position_y, green_sphere_position_z);
  glColor3f (0.0f, 1.0f, 0.0f);
  glutSolidSphere (sphere_radius, 50, 50);
}

SLIDE 74: Animating the camera: display().

  • Step 41 of 48: Now restore the view matrix to its state before the last glTranslatef() function. Remember: glTranslatef() manipulations are cumulative. We get around this by restoring the view after each manipulation.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
  center_x = (red_sphere_position_x + green_sphere_position_x + blue_sphere_position_x) / 3.0f;
  center_y = -6.0f;
  center_z = (red_sphere_position_z + green_sphere_position_z + blue_sphere_position_z) / 3.0f;
  if (camera_angle_degrees >= 360.0f)
  {
    camera_angle_degrees = 0;
  }
  else
  {
    camera_angle_degrees = camera_angle_degrees + 1.0f;
  }
  camera_angle_radians = camera_angle_degrees * M_PI / 180.0f;
  camera_position_x = sin(camera_angle_radians) * 6.0f + 6.0f;
  camera_position_y = -6.0f;
  camera_position_z = cos(camera_angle_radians) * 6.0f - 4.50f;
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity ();
  gluLookAt (camera_position_x, camera_position_y, camera_position_z, center_x, center_y, center_z, 0.0f, 1.0f, 0.0f);
  glPushMatrix ();
  glTranslatef (red_sphere_position_x, red_sphere_position_y, red_sphere_position_z);
  glColor3f (1.0f, 0.0f, 0.0f);
  glutSolidSphere (sphere_radius, 50, 50);
  glPopMatrix ();
  glPushMatrix ();
  glTranslatef (green_sphere_position_x, green_sphere_position_y, green_sphere_position_z);
  glColor3f (0.0f, 1.0f, 0.0f);
  glutSolidSphere (sphere_radius, 50, 50);
  glPopMatrix ();
}

SLIDE 75: Animating the camera: display().

  • Step 42 of 48: Use glPushMatrix() again so the modelview matrix can be restored after we do another subsequent glTranslatef matrix manipulation to draw our third sphere.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
  center_x = (red_sphere_position_x + green_sphere_position_x + blue_sphere_position_x) / 3.0f;
  center_y = -6.0f;
  center_z = (red_sphere_position_z + green_sphere_position_z + blue_sphere_position_z) / 3.0f;
  if (camera_angle_degrees >= 360.0f)
  {
    camera_angle_degrees = 0;
  }
  else
  {
    camera_angle_degrees = camera_angle_degrees + 1.0f;
  }
  camera_angle_radians = camera_angle_degrees * M_PI / 180.0f;
  camera_position_x = sin(camera_angle_radians) * 6.0f + 6.0f;
  camera_position_y = -6.0f;
  camera_position_z = cos(camera_angle_radians) * 6.0f - 4.50f;
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity ();
  gluLookAt (camera_position_x, camera_position_y, camera_position_z, center_x, center_y, center_z, 0.0f, 1.0f, 0.0f);
  glPushMatrix ();
  glTranslatef (red_sphere_position_x, red_sphere_position_y, red_sphere_position_z);
  glColor3f (1.0f, 0.0f, 0.0f);
  glutSolidSphere (sphere_radius, 50, 50);
  glPopMatrix ();
  glPushMatrix ();
  glTranslatef (green_sphere_position_x, green_sphere_position_y, green_sphere_position_z);
  glColor3f (0.0f, 1.0f, 0.0f);
  glutSolidSphere (sphere_radius, 50, 50);
  glPopMatrix ();
  glPushMatrix ();
}

SLIDE 76: Animating the camera: display().

  • Step 43 of 48: Use matrix transformation to place the blue sphere in the appropriate place on the screen (specified by Cartesian coordinates).

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
  center_x = (red_sphere_position_x + green_sphere_position_x + blue_sphere_position_x) / 3.0f;
  center_y = -6.0f;
  center_z = (red_sphere_position_z + green_sphere_position_z + blue_sphere_position_z) / 3.0f;
  if (camera_angle_degrees >= 360.0f)
  {
    camera_angle_degrees = 0;
  }
  else
  {
    camera_angle_degrees = camera_angle_degrees + 1.0f;
  }
  camera_angle_radians = camera_angle_degrees * M_PI / 180.0f;
  camera_position_x = sin(camera_angle_radians) * 6.0f + 6.0f;
  camera_position_y = -6.0f;
  camera_position_z = cos(camera_angle_radians) * 6.0f - 4.50f;
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity ();
  gluLookAt (camera_position_x, camera_position_y, camera_position_z, center_x, center_y, center_z, 0.0f, 1.0f, 0.0f);
  glPushMatrix ();
  glTranslatef (red_sphere_position_x, red_sphere_position_y, red_sphere_position_z);
  glColor3f (1.0f, 0.0f, 0.0f);
  glutSolidSphere (sphere_radius, 50, 50);
  glPopMatrix ();
  glPushMatrix ();
  glTranslatef (green_sphere_position_x, green_sphere_position_y, green_sphere_position_z);
  glColor3f (0.0f, 1.0f, 0.0f);
  glutSolidSphere (sphere_radius, 50, 50);
  glPopMatrix ();
  glPushMatrix ();
  glTranslatef (blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z);
}

SLIDE 77: Animating the camera: display().

  • Step 44 of 48: Define a pure blue color to draw the third sphere.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
  center_x = (red_sphere_position_x + green_sphere_position_x + blue_sphere_position_x) / 3.0f;
  center_y = -6.0f;
  center_z = (red_sphere_position_z + green_sphere_position_z + blue_sphere_position_z) / 3.0f;
  if (camera_angle_degrees >= 360.0f)
  {
    camera_angle_degrees = 0;
  }
  else
  {
    camera_angle_degrees = camera_angle_degrees + 1.0f;
  }
  camera_angle_radians = camera_angle_degrees * M_PI / 180.0f;
  camera_position_x = sin(camera_angle_radians) * 6.0f + 6.0f;
  camera_position_y = -6.0f;
  camera_position_z = cos(camera_angle_radians) * 6.0f - 4.50f;
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity ();
  gluLookAt (camera_position_x, camera_position_y, camera_position_z, center_x, center_y, center_z, 0.0f, 1.0f, 0.0f);
  glPushMatrix ();
  glTranslatef (red_sphere_position_x, red_sphere_position_y, red_sphere_position_z);
  glColor3f (1.0f, 0.0f, 0.0f);
  glutSolidSphere (sphere_radius, 50, 50);
  glPopMatrix ();
  glPushMatrix ();
  glTranslatef (green_sphere_position_x, green_sphere_position_y, green_sphere_position_z);
  glColor3f (0.0f, 1.0f, 0.0f);
  glutSolidSphere (sphere_radius, 50, 50);
  glPopMatrix ();
  glPushMatrix ();
  glTranslatef (blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z);
  glColor3f (0.0f, 0.0f, 1.0f);
}

SLIDE 78: Animating the camera: display().

  • Step 45 of 48: Draw a high quality sphere. The 50, 50 values refer to number of mesh subdivisions in the sphere. The values I am using will create a high resolution, smooth sphere.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
  center_x = (red_sphere_position_x + green_sphere_position_x + blue_sphere_position_x) / 3.0f;
  center_y = -6.0f;
  center_z = (red_sphere_position_z + green_sphere_position_z + blue_sphere_position_z) / 3.0f;
  if (camera_angle_degrees >= 360.0f)
  {
    camera_angle_degrees = 0;
  }
  else
  {
    camera_angle_degrees = camera_angle_degrees + 1.0f;
  }
  camera_angle_radians = camera_angle_degrees * M_PI / 180.0f;
  camera_position_x = sin(camera_angle_radians) * 6.0f + 6.0f;
  camera_position_y = -6.0f;
  camera_position_z = cos(camera_angle_radians) * 6.0f - 4.50f;
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity ();
  gluLookAt (camera_position_x, camera_position_y, camera_position_z, center_x, center_y, center_z, 0.0f, 1.0f, 0.0f);
  glPushMatrix ();
  glTranslatef (red_sphere_position_x, red_sphere_position_y, red_sphere_position_z);
  glColor3f (1.0f, 0.0f, 0.0f);
  glutSolidSphere (sphere_radius, 50, 50);
  glPopMatrix ();
  glPushMatrix ();
  glTranslatef (green_sphere_position_x, green_sphere_position_y, green_sphere_position_z);
  glColor3f (0.0f, 1.0f, 0.0f);
  glutSolidSphere (sphere_radius, 50, 50);
  glPopMatrix ();
  glPushMatrix ();
  glTranslatef (blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z);
  glColor3f (0.0f, 0.0f, 1.0f);
  glutSolidSphere (sphere_radius, 50, 50);
}

SLIDE 79: Animating the camera: display().

  • Step 46 of 48: Restore the original modelview matrix once again after our last glTranslatef() function.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
  center_x = (red_sphere_position_x + green_sphere_position_x + blue_sphere_position_x) / 3.0f;
  center_y = -6.0f;
  center_z = (red_sphere_position_z + green_sphere_position_z + blue_sphere_position_z) / 3.0f;
  if (camera_angle_degrees >= 360.0f)
  {
    camera_angle_degrees = 0;
  }
  else
  {
    camera_angle_degrees = camera_angle_degrees + 1.0f;
  }
  camera_angle_radians = camera_angle_degrees * M_PI / 180.0f;
  camera_position_x = sin(camera_angle_radians) * 6.0f + 6.0f;
  camera_position_y = -6.0f;
  camera_position_z = cos(camera_angle_radians) * 6.0f - 4.50f;
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity ();
  gluLookAt (camera_position_x, camera_position_y, camera_position_z, center_x, center_y, center_z, 0.0f, 1.0f, 0.0f);
  glPushMatrix ();
  glTranslatef (red_sphere_position_x, red_sphere_position_y, red_sphere_position_z);
  glColor3f (1.0f, 0.0f, 0.0f);
  glutSolidSphere (sphere_radius, 50, 50);
  glPopMatrix ();
  glPushMatrix ();
  glTranslatef (green_sphere_position_x, green_sphere_position_y, green_sphere_position_z);
  glColor3f (0.0f, 1.0f, 0.0f);
  glutSolidSphere (sphere_radius, 50, 50);
  glPopMatrix ();
  glPushMatrix ();
  glTranslatef (blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z);
  glColor3f (0.0f, 0.0f, 1.0f);
  glutSolidSphere (sphere_radius, 50, 50);
  glPopMatrix ();
}

SLIDE 80: Animating the camera: display().

  • Step 47 of 48: Switch graphics buffers (remember we are using two buffers (also known as double buffering) for smooth animation of the camera). This means we draw on the off screen buffer why displaying the on-screen buffer. We continue switching these two buffers (always drawing to off-screen buffer) so we can acheive flicker-free animation.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
  center_x = (red_sphere_position_x + green_sphere_position_x + blue_sphere_position_x) / 3.0f;
  center_y = -6.0f;
  center_z = (red_sphere_position_z + green_sphere_position_z + blue_sphere_position_z) / 3.0f;
  if (camera_angle_degrees >= 360.0f)
  {
    camera_angle_degrees = 0;
  }
  else
  {
    camera_angle_degrees = camera_angle_degrees + 1.0f;
  }
  camera_angle_radians = camera_angle_degrees * M_PI / 180.0f;
  camera_position_x = sin(camera_angle_radians) * 6.0f + 6.0f;
  camera_position_y = -6.0f;
  camera_position_z = cos(camera_angle_radians) * 6.0f - 4.50f;
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity ();
  gluLookAt (camera_position_x, camera_position_y, camera_position_z, center_x, center_y, center_z, 0.0f, 1.0f, 0.0f);
  glPushMatrix ();
  glTranslatef (red_sphere_position_x, red_sphere_position_y, red_sphere_position_z);
  glColor3f (1.0f, 0.0f, 0.0f);
  glutSolidSphere (sphere_radius, 50, 50);
  glPopMatrix ();
  glPushMatrix ();
  glTranslatef (green_sphere_position_x, green_sphere_position_y, green_sphere_position_z);
  glColor3f (0.0f, 1.0f, 0.0f);
  glutSolidSphere (sphere_radius, 50, 50);
  glPopMatrix ();
  glPushMatrix ();
  glTranslatef (blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z);
  glColor3f (0.0f, 0.0f, 1.0f);
  glutSolidSphere (sphere_radius, 50, 50);
  glPopMatrix ();
  glutSwapBuffers();
}

SLIDE 81: Animating the camera: display().

  • Step 48 of 48: Now it is time to redisplay or refresh our screen with our previous off-screen buffer (now the on-screen buffer). Remember we are double buffered.

void display (void)
{
  float sphere_radius;
  float red_sphere_position_x, red_sphere_position_y, red_sphere_position_z;
  float green_sphere_position_x, green_sphere_position_y, green_sphere_position_z;
  float blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z;
  float camera_position_x, camera_position_y, camera_position_z;
  float center_x, center_y, center_z;
  float camera_angle_radians;
  
  sphere_radius = 1.0;
  red_sphere_position_y = -6.0f;
  green_sphere_position_y = -6.0f;
  blue_sphere_position_y = -6.0f;
  red_sphere_position_x = 6.0f;
  red_sphere_position_z = -3.25f;
  green_sphere_position_x = 5.0f;
  green_sphere_position_z = -5.0f;
  blue_sphere_position_x = 7.0f;
  blue_sphere_position_z = -5.0f;
  center_x = (red_sphere_position_x + green_sphere_position_x + blue_sphere_position_x) / 3.0f;
  center_y = -6.0f;
  center_z = (red_sphere_position_z + green_sphere_position_z + blue_sphere_position_z) / 3.0f;
  if (camera_angle_degrees >= 360.0f)
  {
    camera_angle_degrees = 0;
  }
  else
  {
    camera_angle_degrees = camera_angle_degrees + 1.0f;
  }
  camera_angle_radians = camera_angle_degrees * M_PI / 180.0f;
  camera_position_x = sin(camera_angle_radians) * 6.0f + 6.0f;
  camera_position_y = -6.0f;
  camera_position_z = cos(camera_angle_radians) * 6.0f - 4.50f;
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity ();
  gluLookAt (camera_position_x, camera_position_y, camera_position_z, center_x, center_y, center_z, 0.0f, 1.0f, 0.0f);
  glPushMatrix ();
  glTranslatef (red_sphere_position_x, red_sphere_position_y, red_sphere_position_z);
  glColor3f (1.0f, 0.0f, 0.0f);
  glutSolidSphere (sphere_radius, 50, 50);
  glPopMatrix ();
  glPushMatrix ();
  glTranslatef (green_sphere_position_x, green_sphere_position_y, green_sphere_position_z);
  glColor3f (0.0f, 1.0f, 0.0f);
  glutSolidSphere (sphere_radius, 50, 50);
  glPopMatrix ();
  glPushMatrix ();
  glTranslatef (blue_sphere_position_x, blue_sphere_position_y, blue_sphere_position_z);
  glColor3f (0.0f, 0.0f, 1.0f);
  glutSolidSphere (sphere_radius, 50, 50);
  glPopMatrix ();
  glutSwapBuffers();
  glutPostRedisplay();
}

SLIDE 82: Animating the camera: main().

Our main() calls the following user-defined subroutines:

  • init()
  • display()
  • reshape()

We'll dissect reshape() next...

SLIDE 83: Animating the camera: reshape().

  • Step 1 of 9: Skeleton of the reshape() subroutine.

void reshape (int w, int h)
{
}

SLIDE 84: Animating the camera: reshape().

  • Step 2 of 9: glViewport() set the viewport to dimensions of our display window: (0, 0) to (w, h) where w is width and h is height.

void reshape (int w, int h)
{
  glViewport (0, 0, w, h);
}

SLIDE 85: Animating the camera: reshape().

  • Step 3 of 9: glMatrixMode() use the GL_PROJECTION matrix. We will subsequently initialize it in the next step.

void reshape (int w, int h)
{
  glViewport (0, 0, w, h);
  glMatrixMode (GL_PROJECTION);
}

SLIDE 86: Animating the camera: reshape().

  • Step 4 of 9: glLoadIdentity() now initialize the GL_PROJECTION matrix.

void reshape (int w, int h)
{
  glViewport (0, 0, w, h);
  glMatrixMode (GL_PROJECTION);
  glLoadIdentity ();
}

SLIDE 87: Animating the camera: reshape().

  • Step 5 of 9: The reshape function is called whenever a user resizes the canvas window we are drawing in. In the event the window is resized, we want to make sure to preserve the aspect ratio of what we draw inside the window. This meeans our resized window will not have a squashed or stretched image. To preserve the aspect ratio, we first must check that the height (h) is not zero since we will be dividing by height. We do not want to divide by zero!

void reshape (int w, int h)
{
  glViewport (0, 0, w, h);
  glMatrixMode (GL_PROJECTION);
  glLoadIdentity ();
  if (h == 0)
  {
  }
  else
  {
  }
}

SLIDE 88: Animating the camera: reshape().

  • Step 6 of 9: gluPerspective() specifies the view angle (80 degrees) and the aspect ratio of the field of view, and the near and far clipping planes. If height (h) is somehow zero, then set height to 1. Under normal circumstances, we should never come here. This is just a safety measure.

void reshape (int w, int h)
{
  glViewport (0, 0, w, h);
  glMatrixMode (GL_PROJECTION);
  glLoadIdentity ();
  if (h == 0)
  {
    gluPerspective (80, (float) w, 1.0, 5000.0);
  }
  else
  {
  }
}

SLIDE 89: Animating the camera: reshape().

  • Step 7 of 9: gluPerspective() specifies the view angle (80 degrees) and the aspect ratio of the field of view, and the near and far clipping planes. Note that I'm preserving the aspect ratio of my display window by dividing the window's width by its height. This keeps my perspective view from being squashed or stretched. Since we know the height is not zero, it is safe to do this division.

void reshape (int w, int h)
{
  glViewport (0, 0, w, h);
  glMatrixMode (GL_PROJECTION);
  glLoadIdentity ();
  if (h == 0)
  {
    gluPerspective (80, (float) w, 1.0, 5000.0);
  }
  else
  {
    gluPerspective (80, (float) w / (float) h, 1.0, 5000.0);
  }
}

SLIDE 90: Animating the camera: reshape().

  • Step 8 of 9: glMatrixMode() switch back to GL_MODELVIEW matrix.

void reshape (int w, int h)
{
  glViewport (0, 0, w, h);
  glMatrixMode (GL_PROJECTION);
  glLoadIdentity ();
  if (h == 0)
  {
    gluPerspective (80, (float) w, 1.0, 5000.0);
  }
  else
  {
    gluPerspective (80, (float) w / (float) h, 1.0, 5000.0);
  }
  glMatrixMode (GL_MODELVIEW);
}

SLIDE 91: Animating the camera: reshape().

  • Step 9 of 9: after changing the perspective through gluPerspective(), initialize the GL_PROJECTION matrix again.

void reshape (int w, int h)
{
  glViewport (0, 0, w, h);
  glMatrixMode (GL_PROJECTION);
  glLoadIdentity ();
  if (h == 0)
  {
    gluPerspective (80, (float) w, 1.0, 5000.0);
  }
  else
  {
    gluPerspective (80, (float) w / (float) h, 1.0, 5000.0);
  }
  glMatrixMode (GL_MODELVIEW);
  glLoadIdentity ();
}

SLIDE 92: Animating the camera: main().

Our main() calls the following user-defined subroutines:

  • init()
  • display()
  • reshape()

SLIDE 93: Animating the camera: Define one global variable

We must define one global variable at the top of our program. Global variables are a bad programming practice. Variables should be passed into subroutines using pass by reference or pass by value. This limits the scope of variables and elliminates side-effects (i.e. a global variable changing value but we don't know where it occurs).

Unfortunately, the GLUT Application Programmer's Interface (API) is too rigid in structure. It is impossible in C to pass such variables by reference using the GLUT API. The only solution is defining the variable globally in scope.

float camera_angle_degrees = 0;

Next we need to include header files at the top of our program...

SLIDE 94: Animating the camera: Headers.

  • We can use a compiler preprocessor IF statement to include appropriate header files depending on our target operating system: OSX or GNU/Linux.

#ifdef __APPLE__
  #include <OpenGL/gl.h>
  #include <OpenGL/glu.h>
  #include <GLUT/glut.h>
#elif __linux__
  #include <GL/glut.h>
#endif
#include <math.h>

SLIDE 95: Compiling the program

  • To compile rotating_camera_demo.c on GNU/Linux, issue the following command

cc -o rotating_camera_demo rotating_camera_demo.c -lglut -lGL -lGLU -lX11 -lXmu -lXi -lm

  • To compile rotating_camera_demo.c on MAC (OSX), issue the following command

cc -o rotating_camera_demo rotating_camera_demo.c -framework GLUT -framework OpenGL -framework Cocoa -lm -Wno-deprecated