Выбрать главу

{

 if (g_keys->keyDown [VK_ESCAPE] == TRUE) // Is ESC Being Pressed?

 {

  TerminateApplication (g_window); // Terminate The Program

 }

 if (g_keys->keyDown [VK_F1] == TRUE) // Is F1 Being Pressed?

 {

  ToggleFullscreen (g_window); // Toggle Fullscreen Mode

 }

 if ((g_keys->keyDown [' ']) && !sp) // Is Space Being Pressed And Not Held?

 {

  sp=TRUE; // Set sp To True

  effect++; // Change Effects (Increase effect)

  if (effect>3) // Over Our Limit?

   effect=0; // Reset Back To 0

 }

 if (!g_keys->keyDown[' ']) // Is Space Released?

  sp=FALSE; // Set sp To False

 if ((g_keys->keyDown ['B']) && !bp) // Is 'B' Being Pressed And Not Held?

 {

  bp=TRUE; // Set bp To True

  bg=!bg; // Toggle Background Off/On

 }

 if (!g_keys->keyDown['B']) // Is 'B' Released?

  bp=FALSE; // Set bp To False

 if ((g_keys->keyDown ['E']) && !ep) // Is 'E' Being Pressed And Not Held?

 {

  ep=TRUE; // Set ep To True

  env=!env; // Toggle Environment Mapping Off/On

 }

 if (!g_keys->keyDown['E']) // Is 'E' Released?

  ep=FALSE; // Set ep To False

 angle += (float)(milliseconds) / 60.0f; // Update angle Based On The Timer

In the original tutorial, all AVI files were played at the same speed. Since then, the tutorial has been rewritten to play the video at the correct speed. next is increased by the number of milliseconds that have passed since this section of code was last called. If you remember earlier in the tutorial, we calculated how long each frame should be displayed in milliseconds (mpf). To calculate the current frame, we take the amount of time that has passed (next) and divide it by the time each frame is displayed for (mpf).

After that, we check to make sure that the current frame of animation hasn't passed the last frame of the video. If it has, frame is reset to zero, the animation timer (next) is reset to 0, and the animation starts over.

The code below will drop frames if your computer is running to slow, or another application is hogging the CPU. If you want every frame to be displayed no matter how slow the users computer is, you could check to see if next is greater than mpf if it is, you would reset next to 0 and increase frame by one. Either way will work, although the code below is better for faster machines.

If you feel energetic, try adding rewind, fast forward, pause or reverse play!

 next+= milliseconds; // Increase next Based On Timer (Milliseconds)

 frame=next/mpf; // Calculate The Current Frame

 if (frame>=lastframe) // Have We Gone Past The Last Frame?

 {

  frame=0; // Reset The Frame Back To Zero (Start Of Video)

  next=0; // Reset The Animation Timer (next)

 }

}

Now for the drawing code :) We clear the screen and depth buffer. We then grab a frame of animation. Again, I tried to keep it simple! You pass the requested frame (frame) to GrabAVIFrame(). Pretty simple! Of course, if you wanted multiple AVI's, you would have to pass a texture ID. (More for you to do).

void Draw (void) // Draw Our Scene

{

 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer

 GrabAVIFrame(frame); // Grab A Frame From The AVI

The code below checks to see if we want to draw a background image. If bg is TRUE, we reset the modelview matrix and draw a single texture mapped quad (mapped with a frame from the AVI video) large enough to fill the entire screen. The quad is drawn 20 units into the screen so it appears behind the object (futher in the distance).

 if (bg) // Is Background Visible?

 {

  glLoadIdentity(); // Reset The Modelview Matrix

  glBegin(GL_QUADS); // Begin Drawing The Background (One Quad)

   // Front Face

   glTexCoord2f(1.0f, 1.0f); glVertex3f( 11.0f, 8.3f, –20.0f);

   glTexCoord2f(0.0f, 1.0f); glVertex3f(-11.0f, 8.3f, –20.0f);

   glTexCoord2f(0.0f, 0.0f); glVertex3f(-11.0f, –8.3f, –20.0f);

   glTexCoord2f(1.0f, 0.0f); glVertex3f( 11.0f, –8.3f, –20.0f);

  glEnd(); // Done Drawing The Background

 }

After drawing the background (or not), we reset the modelview matrix (starting us back at the center of the screen). We then translate 10 units into the screen.

After that, we check to see if env is TRUE. If it is, we enable sphere mapping to create the environment mapping effect.

 glLoadIdentity(); // Reset The Modelview Matrix

 glTranslatef (0.0f, 0.0f, –10.0f); // Translate 10 Units Into The Screen

 if (env) // Is Environment Mapping On?

 {

  glEnable(GL_TEXTURE_GEN_S); // Enable Texture Coord Generation For S (NEW)

  glEnable(GL_TEXTURE_GEN_T); // Enable Texture Coord Generation For T (NEW)

 }

I added the code below at the last minute. It rotates on the x-axis and y-axis (based on the value of angle) and then translates 2 units on the z-axis. This move us away from the center of the screen. If you remove the three lines of code below, the object will spin in the center of the screen. With the three lines of code, the objects move around a bit as they spin :)

If you don't understand rotations and translations… you shouldn't be reading this tutorial :)

 glRotatef(angle*2.3f,1.0f,0.0f,0.0f); // Throw In Some Rotations To Move Things Around A Bit

 glRotatef(angle*1.8f,0.0f,1.0f,0.0f); // Throw In Some Rotations To Move Things Around A Bit

 glTranslatef(0.0f,0.0f,2.0f); // After Rotating Translate To New Position

The code below checks to see which effect (object) we want to draw. If the value of effect is 0, we do a few rotations and then draw a cube. The rotations keep the cube spinning on the x-axis, y-axis and z-axis. By now, you should have the code to create a cube burned into your head :)

 switch (effect) // Which Effect?

 {

 case 0: // Effect 0 – Cube

  glRotatef (angle*1.3f, 1.0f, 0.0f, 0.0f); // Rotate On The X-Axis By angle

  glRotatef (angle*1.1f, 0.0f, 1.0f, 0.0f); // Rotate On The Y-Axis By angle

  glRotatef (angle*1.2f, 0.0f, 0.0f, 1.0f); // Rotate On The Z-Axis By angle

  glBegin(GL_QUADS); // Begin Drawing A Cube

   // Front Face

   glNormal3f( 0.0f, 0.0f, 0.5f);

   glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, –1.0f, 1.0f);

   glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, –1.0f, 1.0f);

   glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);

   glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);

   // Back Face

   glNormal3f( 0.0f, 0.0f,-0.5f);

   glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, –1.0f, –1.0f);