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.