Hello again, everyone. Here’s what i have going:
In my project, I’ve written a small library that will open a bitmap stored somewhere on my machine and read in the bitmap’s dimensions, as well as the pixel information and store it in memory. Here is the Bitmap_24 class, and the method in that class that reads in bitmap data:
Bitmap_24 class
<div class=“ubbcode-block”><div class=“ubbcode-header”>Click to reveal… <input type=“button” class=“form-button” value=“Show me!” onclick=“toggle_spoiler(this, ‘Yikes, my eyes!’, ‘Show me!’)” />]<div style=“display: none;”>
class Bitmap_24
{
// Member Fields
private:
int m_iWidth; // Image Width in Pixels
int m_iHeight; // Image height in Pixels
DWORD *m_pPixelArray; // Actual Pixels of the image
public:
// Constructor(s) / Destructor
Bitmap_24(char *Filename);
// General Methods
void Cleanup();
bool ReadBitmap(char *Filename);
// Accessor methods
int GetWidth();
int GetHeight();
DWORD* GetPixels();
};
[/QUOTE]</div>
ReadBitmap method
<div class=“ubbcode-block”><div class=“ubbcode-header”>Click to reveal… <input type=“button” class=“form-button” value=“Show me!” onclick=“toggle_spoiler(this, ‘Yikes, my eyes!’, ‘Show me!’)” />]<div style=“display: none;”>
bool Bitmap_24::ReadBitmap(char Filename)
{
FILE pFileStream;
BITMAPFILEHEADER bmFileHeader;
BITMAPINFO bmInfo;
int iBytesPerLine;
int iTotalBytes;
// Open the file, obtaining our stream
if(!(pFileStream = fopen(Filename, "r")))
{
//TODO: Error handle
MessageBox(NULL, "Bitmap file was not opened", "An error occurred", MB_ICONERROR | MB_OK);
return false;
}
// read the BITMAPFILEHEADER
fread((char *)&bmFileHeader, sizeof(BITMAPFILEHEADER), 1, pFileStream);
// Read the BITMAPINFO
// NOTE: Because this bitmap should have a 24-bit pixel resolution, there
// should be no color table, so the entire BITMAPINFO can be read together in one call.
fread((char *)&bmInfo, sizeof(BITMAPINFO), 1, pFileStream);
//TODO: Bitmap resolution / compression validation
if((bmInfo.bmiHeader.biBitCount != 24) || (bmInfo.bmiHeader.biCompression != 0))
{
MessageBox(NULL, "Bitmap was not 24bpp or was compressed", "An error occurred", MB_ICONERROR | MB_OK);
return false;
}
// Populate Image Data Member Variables
m_iWidth = (int)bmInfo.bmiHeader.biWidth;
m_iHeight = (int)bmInfo.bmiHeader.biHeight;
// Calculate the number of bytes in a line
/*
* This is simple to calculate. We have the number of pixels in a row (Image width.)
* We know that there are 24 bits per pixel.
* Because each pixel is 24 bits, each pixel is 3 bytes. We can find the byte width (w/out padding):
* notPaddedByteWidth = (pixelWidth * 24) / 8
* Depending on the image width, there may be extra "padding" bytes in the array. In a bitmap,
* each "scan line" or "row" must have a number of bytes that is a multiple of 4. If the width in
* bytes is not naturally a multiple of four, empty padding bytes are added - 1, 2, or 3 depending.
* We can figure this out with a simple mod function:
* padBytesPerLine = notPaddedByteWidth % 4
* padBytesPerLine tells us how many extra bytes are included in each line. Knowing this, each line has
* notPaddedByteWidth + padBytesPerLine bytes per line. The total number of bytes taken up by the pixel
* data, then, is this number of bytes per line multiplied by the image height.
*/
iBytesPerLine = ((m_iWidth * 24) / 8) + (((m_iWidth * 8) / 3) % 4);
iTotalBytes = iBytesPerLine * m_iHeight;
// Now that we know how many bytes there are, we can initialize our member array.
// We can figure out the size of the array in DWORDS by dividing the number of bytes
// by 4. (One DWORD = 4 bytes).
m_pPixelArray = new DWORD[iTotalBytes / 4];
// Move the file pointer to the beginning of the array.
fseek(pFileStream, bmFileHeader.bfOffBits, SEEK_SET);
// Read in the array
fread((char *)&m_pPixelArray, sizeof(DWORD), iTotalBytes / 4, pFileStream);
// At this point, the entire bitmap should be loaded into memory!
return true;
}
[/QUOTE]</div>
The Bitmap_24 constructor requires a Filename string, and simply passes that to the ReadBitmap method.
I also have a method in my game engine that is designed to take in an array of “images” (the bitmap objects from my library), as well as an empty destination texture array. The method should create the appropriate number of Texture Objects and store their references in the texture array (pTexArray), and then one by one create the textures from the bitmap image data supplied by the image array (pImageArray). Here is the method:
BitmapToTexture
<div class=“ubbcode-block”><div class=“ubbcode-header”>Click to reveal… <input type=“button” class=“form-button” value=“Show me!” onclick=“toggle_spoiler(this, ‘Yikes, my eyes!’, ‘Show me!’)” />]<div style=“display: none;”>
bool hzGameEngine::hzBitmapToTexture(Bitmap_24 *pImageArray, GLuint *pTexArray)
{
int iArrayLength; // Length of the arrays.
// Check the length of the arrays
if((iArrayLength = (sizeof(pImageArray) / sizeof(*pImageArray))) > (sizeof(pTexArray) / sizeof(*pTexArray)))
{
// There are too many images and not enough elements in the texture array
// TODO: Error handling
MessageBox(NULL, "The image array is larger than the texture array", "An error occurred", MB_ICONERROR | MB_OK);
return false;
}
// Generate the OpenGL Texture Objects
glGenTextures(iArrayLength, pTexArray);
//Set Pixel Unpacking
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // Handles the fact that bitmap rows must
// be a multiple of 4 bytes
for(int i = 0; i < iArrayLength; i++)
{
//Bind a texture
glBindTexture(GL_TEXTURE_2D, pTexArray[i]);
//Unload image data into the current texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, pImageArray[i].GetWidth(), pImageArray[i].GetHeight(),
0, GL_BGR_EXT, GL_UNSIGNED_BYTE, pImageArray[i].GetPixels());
//Specify Filtering
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // Linear Filtering
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // Linear Filtering
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
//TODO: Free memory
return true;
}
[/QUOTE]</div>
And here is the relevant part of my game setup method, which actually calls this method. Note that _pTexArray is a global array of one GLuint:
Game Setup
<div class=“ubbcode-block”><div class=“ubbcode-header”>Click to reveal… <input type=“button” class=“form-button” value=“Show me!” onclick=“toggle_spoiler(this, ‘Yikes, my eyes!’, ‘Show me!’)” />]<div style=“display: none;”>
// Texture Setup
Bitmap_24 pImageArray[1] = { Bitmap_24(“C:\Users\Mahlon\Desktop\grasstexture.bmp”)};
if(!(_pGame->hzBitmapToTexture(pImageArray, _pTexArray)))
{
MessageBox(NULL, "BitmapToTexture failed" , "An error occurred", MB_ICONERROR | MB_OK);
}
if(_pTexArray[0] == 0)
{
MessageBox(NULL, "Nothing is in texarray", "An error occurred", MB_ICONERROR | MB_OK);
}
if(pImageArray[0].GetHeight() == 0)
{
MessageBox(NULL, "Image height is 0", "An error occurred", MB_ICONERROR | MB_OK);
}
[/QUOTE]</div>
Once that is finished I should, if everything went well, have an array of openGL texture names that i cna use to draw textures with. At the moment I’m simply trying to draw one texture to a single quad. Here is the relevant part of my draw method:
Draw
<div class=“ubbcode-block”><div class=“ubbcode-header”>Click to reveal… <input type=“button” class=“form-button” value=“Show me!” onclick=“toggle_spoiler(this, ‘Yikes, my eyes!’, ‘Show me!’)” />]<div style=“display: none;”>
//OpenGL drawing
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, _pTexArray[0]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); // Bottom-right texture coordinate
glVertex3f(_squareX, _squareY, _squareZ); //Bottom-left vertex
glTexCoord2f(1.0f, 0.0f);
glVertex3f(_squareX + _squareSize, _squareY, _squareZ); //Bottom-right vertex
glTexCoord2f(1.0f, 1.0f);
glVertex3f(_squareX + _squareSize, _squareY + _squareSize, _squareZ); //Top-Right Vertex
glTexCoord2f(0.0f, 1.0f);
glVertex3f(_squareX, _squareY + _squareSize, _squareZ); //Top-left vertex.
glEnd();
SwapBuffers(hDC);
[/QUOTE]</div>
Unfortunately, something is not working. I get no texture drawn at all. And out of all of the error messages that I’ve built into my code, only the “There is nothing in TexArray” one launches. Admittedly, this could be a false positive. I have it setup to display if the entry in _pTexArray is zero, but since I don’t know how OpenGL goes about naming textures, it may supposed to be zero.
I know this is a lot to look at, but any pointers or suggestions would be appreciated a lot. I’ve been working on this for a while, and I’m at a loss as to why it isn’t working.