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

Finally, the flap speed (fi) and fall speed (yi) are also given a random value.

void SetObject(int loop) // Sets The Initial Value Of Each Object (Random)

{

 obj[loop].tex=rand()%3; // Texture Can Be One Of 3 Textures

 obj[loop].x=rand()%34-17.0f; // Random x Value From –17.0f To 17.0f

 obj[loop].y=18.0f; // Set y Position To 18 (Off Top Of Screen)

 obj[loop].z=-((rand()%30000/1000.0f)+10.0f); // z Is A Random Value From –10.0f To –40.0f

 obj[loop].spinzi=(rand()%10000)/5000.0f-1.0f; // spinzi Is A Random Value From –1.0f To 1.0f

 obj[loop].flap=0.0f; // flap Starts Off At 0.0f;

 obj[loop].fi=0.05f+(rand()%100)/1000.0f; // fi Is A Random Value From 0.05f To 0.15f

 obj[loop].yi=0.001f+(rand()%1000)/10000.0f; // yi Is A Random Value From 0.001f To 0.101f

}

Now for the fun part! Loading a bitmap from the resource file and converting it to a texture.

hBMP is a pointer to our bitmap file. It will tell our program where to get the data from. BMP is a bitmap structure that we can fill with data from our resource file.

We tell our program which ID's to use in the third line of code. We want to load IDB_BUTTEFLY1, IDB_BUTTEFLY2 and IDB_BUTTERFLY3. If you wish to add more images, add the image to the resource file, and add the ID to Texture[ ].

void LoadGLTextures() // Creates Textures From Bitmaps In The Resource File

{

 HBITMAP hBMP; // Handle Of The Bitmap

 BITMAP BMP; // Bitmap Structure

 // The ID Of The 3 Bitmap Images We Want To Load From The Resource File

 byte Texture[]={ IDB_BUTTERFLY1, IDB_BUTTERFLY2, IDB_BUTTERFLY3 };

The line below uses sizeof(Texture) to figure out how many textures we want to build. We have 3 ID's in Texture[ ] so the value will be 3. sizeof(Texture) is also used for the main loop.

 glGenTextures(sizeof(Texture), &texture[0]); // Generate 3 Textures (sizeof(Texture)=3 ID's)

 for (int loop=0; loop<sizeof(Texture); loop++) // Loop Through All The ID's (Bitmap Images)

 {

LoadImage takes the following parameters: GetModuleHandle(NULL) – A handle to an instance. MAKEINTRESOURCE(Texture[loop]) – Converts an Integer Value (Texture[loop]) to a resource value (this is the image to load). IMAGE_BITMAP – Tells our program that the resource to load is a bitmap image.

The next two parameters (0,0) are the desired height and width of the image in pixels. We want to use the default size so we set both to 0.

The last parameter (LR_CREATEDIBSECTION) returns a DIB section bitmap, which is a bitmap without all the color information stored in the data. Exactly what we need.

hBMP points to the bitmap data that is loaded by LoadImage( ).

  hBMP = (HBITMAP)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(Texture[loop]), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);

Next we check to see if the pointer (hBMP) actually points to data. If you wanted to add error checking, you could check hBMP and pop up a messagebox if there's no data.

If data exists, we use GetObject( ) to grab all of the data (sizeof(BMP)) from hBMP and store it in our BMP (bitmap structure).

glPixelStorei tells OpenGL that the data is stored in word alignments (4 bytes per pixel).

We then bind to our texture, set the filtering to GL_LINEAR_MIPMAP_LINEAR (nice and smooth), and generate the texture.

Notice that we use BMP.bmWidth and BMP.bmHeight to get the height and width of the bitmap. We also have to swap the Red and Blue colors using GL_BGR_EXT. The actual resource data is retreived from BMP.bmBits.

The last step is to delete the bitmap object freeing all system resources associated with the object.

  if (hBMP) // Does The Bitmap Exist?

  { // If So…

   GetObject(hBMP,sizeof(BMP), &BMP); // Get The Object

   // hBMP: Handle To Graphics Object

   // sizeof(BMP): Size Of Buffer For Object Information

   // Buffer For Object Information

   glPixelStorei(GL_UNPACK_ALIGNMENT,4); // Pixel Storage Mode (Word Alignment / 4 Bytes)

   glBindTexture(GL_TEXTURE_2D, texture[loop]); // Bind Our Texture

   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Linear Filtering

   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // Mipmap Linear Filtering

   // Generate Mipmapped Texture (3 Bytes, Width, Height And Data From The BMP)

   gluBuild2DMipmaps(GL_TEXTURE_2D, 3, BMP.bmWidth, BMP.bmHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, BMP.bmBits);

   DeleteObject(hBMP); // Delete The Bitmap Object

  }

 }

}

Nothing really fancy in the init code. We add LoadGLTextures() to call the code above. The screen clear color is black. Depth testing is disabled (cheap way to blend). We enable texture mapping, then set up and enable blending.

BOOL Initialize (GL_Window* window, Keys* keys) // Any GL Init Code & User Initialiazation Goes Here

{

 g_window = window;

 g_keys = keys;

 // Start Of User Initialization

 LoadGLTextures(); // Load The Textures From Our Resource File

 glClearColor (0.0f, 0.0f, 0.0f, 0.5f); // Black Background

 glClearDepth (1.0f); // Depth Buffer Setup

 glDepthFunc (GL_LEQUAL); // The Type Of Depth Testing (Less Or Equal)

 glDisable(GL_DEPTH_TEST); // Disable Depth Testing

 glShadeModel (GL_SMOOTH); // Select Smooth Shading

 glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Set Perspective Calculations To Most Accurate

 glEnable(GL_TEXTURE_2D); // Enable Texture Mapping

 glBlendFunc(GL_ONE,GL_SRC_ALPHA); // Set Blending Mode (Cheap / Quick)

 glEnable(GL_BLEND); // Enable Blending

We need to initialize all 50 objects right off the start so they don't appear in the middle of the screen or all in the same location. The loop below does just that.

 for (int loop=0; loop<50; loop++) // Loop To Initialize 50 Objects

 {

  SetObject(loop); // Call SetObject To Assign New Random Values

 }

 return TRUE; // Return TRUE (Initialization Successful)

}

void Deinitialize (void) // Any User DeInitialization Goes Here

{ }

void Update (DWORD milliseconds) // Perform Motion Updates Here

{

 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

 }

}

Now for the drawing code. In this section I'll attempt to explain the easiest way to texture map a single image across two triangles. For some reason everyone seems to think it's near impossible to texture an image to a triangle.

The truth is, you can texture an image to any shape you want. With very little effort. The image can match the shape or it can be a completely different pattern. It really doesn't matter.