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

You'll notice that the colors for each star are made up of random values from 0 to 255. You might be wondering how we can use such large values when normally the colors are from 0.0f to 1.0f. When we set the color we'll use glColor4ub instead of glColor4f. ub means Unsigned Byte. A byte can be any value from 0 to 255. In this program it's easier to use bytes than to come up with a random floating point value.

  star[loop].dist=(float(loop)/num)*5.0f; // Calculate Distance From The Center

  star[loop].r=rand()%256; // Give star[loop] A Random Red Intensity

  star[loop].g=rand()%256; // Give star[loop] A Random Green Intensity

  star[loop].b=rand()%256; // Give star[loop] A Random Blue Intensity

 }

 return TRUE; // Initialization Went OK

}

The Resize code is the same, so we'll jump to the drawing code. If you're using the code from lesson one, delete the DrawGLScene code, and just copy what I have below. There's only 2 lines of code in lesson one anyways, so there's not a lot to delete.

int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing

{

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

 glBindTexture(GL_TEXTURE_2D, texture[0]); // Select Our Texture

 for (loop=0; loop<num; loop++) // Loop Through All The Stars

 {

  glLoadIdentity(); // Reset The View Before We Draw Each Star

  glTranslatef(0.0f,0.0f,zoom); // Zoom Into The Screen (Using The Value In 'zoom')

  glRotatef(tilt,1.0f,0.0f,0.0f); // Tilt The View (Using The Value In 'tilt')

 Now we move the star. The star starts off in the middle of the screen. The first thing we do is spin the scene on the y axis. If we spin 90 degrees, the x axis will no longer run left to right, it will run into and out of the screen. As an example to help clarify. Imagine you were in the center of a room. Now imagine that the left wall had –x written on it, the front wall had –z written on it, the right wall had +x written on it, and the wall behind you had +z written on it. If the room spun 90 degrees to the right, but you did not move, the wall in front of you would no longer say –z it would say –x. All of the walls would have moved. –z would be on the right, +z would be on the left, –x would be in front, and +x would be behind you. Make sense? By rotating the scene, we change the direction of the x and z planes.

The second line of code moves to a positive value on the x plane. Normally a positive value on x would move us to the right side of the screen (where +x usually is), but because we've rotated on the y plane, the +x could be anywhere. If we rotated by 180 degrees, it would be on the left side of the screen instead of the right. So when we move forward on the positive x plane, we could be moving left, right, forward or backward.

  glRotatef(star[loop].angle,0.0f,1.0f,0.0f); // Rotate To The Current Stars Angle

  glTranslatef(star[loop].dist,0.0f,0.0f); // Move Forward On The X Plane

Now for some tricky code. The star is actually a flat texture. Now if you drew a flat quad in the middle of the screen and texture mapped it, it would look fine. It would be facing you like it should. But if you rotated on the y axis by 90 degrees, the texture would be facing the right and left sides of the screen. All you'd see is a thin line. We don't want that to happen. We want the stars to face the screen all the time, no matter how much we rotate and tilt the screen.

We do this by cancelling any rotations that we've made, just before we draw the star. You cancel the rotations in reverse order. So above we tilted the screen, then we rotated to the stars current angle. In reverse order, we'd un-rotate (new word) the stars current angle. To do this we use the negative value of the angle, and rotate by that. So if we rotated the star by 10 degrees, rotating it back –10 degrees will make the star face the screen once again on that axis. So the first line below cancels the rotation on the y axis. Then we need to cancel the screen tilt on the x axis. To do that we just tilt the screen by –tilt. After we've cancelled the x and y rotations, the star will face the screen completely.

  glRotatef(-star[loop].angle,0.0f,1.0f,0.0f); // Cancel The Current Stars Angle

  glRotatef(-tilt,1.0f,0.0f,0.0f); // Cancel The Screen Tilt

If twinkle is TRUE, we'll draw a non-spinning star on the screen. To get a different color, we take the maximum number of stars (num) and subtract the current stars number (loop), then subtract 1 because our loop only goes from 0 to num-1. If the result was 10 we'd use the color from star number 10. That way the color of the two stars is usually different. Not a good way to do it, but effective. The last value is the alpha value. The lower the value, the darker the star is.

If twinkle is enabled, each star will be drawn twice. This will slow down the program a little depending on what type of computer you have. If twinkle is enabled, the colors from the two stars will mix together creating some really nice colors. Also because this star does not spin, it will appear as if the stars are animated when twinkling is enabled. (look for yourself if you don't understand what I mean).

Notice how easy it is to add color to the texture. Even though the texture is black and white, it will become whatever color we select before we draw the texture. Also take note that we're using bytes for the color values rather than floating point numbers. Even the alpha value is a byte.

  if (twinkle) // Twinkling Stars Enabled

  {

   // Assign A Color Using Bytes

   glColor4ub(star[(num-loop)-1].r,star[(num-loop)-1].g,star[(num-loop)-1].b,255);

   glBegin(GL_QUADS); // Begin Drawing The Textured Quad

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

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

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

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

   glEnd(); // Done Drawing The Textured Quad

  }

Now we draw the main star. The only difference from the code above is that this star is always drawn, and this star spins on the z axis.

  glRotatef(spin,0.0f,0.0f,1.0f); // Rotate The Star On The Z Axis

  // Assign A Color Using Bytes

  glColor4ub(star[loop].r,star[loop].g,star[loop].b,255);

  glBegin(GL_QUADS); // Begin Drawing The Textured Quad

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

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

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

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

  glEnd(); // Done Drawing The Textured Quad

Here's where we do all the movement. We spin the normal stars by increasing the value of spin. Then we change the angle of each star. The angle of each star is increased by loop/num. What this does is spins the stars that are farther from the center faster. The stars closer to the center spin slower. Finally we decrease the distance each star is from the center of the screen. This makes the stars look as if they are being sucked into the middle of the screen.

  spin+=0.01f; // Used To Spin The Stars