problem with basic texture mapping class

Moderator
Posts: 373
Joined: 2006.08
Post: #1
Hello everyone Smile So, I got a class off of the internet that is supposed to load a bitmap image and convert it into texture data, which I then use. Here is the header file:

Code:
#ifndef TEXTURE_HPP
#define TEXTURE_HPP

#include <fstream>   // The include file for file input/output.
#include <stdio.h>
#include <windows.h>        // Header File For Windows
#include <gl\gl.h>            // Header File For The OpenGL32 Library
#include <gl\glu.h>            // Header File For The GLu32 Library

// This is the first draft of our class.
// Soon, this segment of 1's and 0's will evolve into
// an omnipotent being that will dominate the known
// world ...

class texture
{
      


private:

    // Note that all the variables declared in the class start with m_
    // if you see that in a method, you'll know that it's declared right here

    // The texture's ID
    unsigned int m_uiTexID;

    // The actual image.
    unsigned char *m_Image;

public:

    texture();
    ~texture();
    
       // Width and Height of the image
    int m_iWidth;
    int m_iHeight;
    
    int LoadBMP( const char *sFileName );
    void generate();
    GLuint GetID();
};

#endif

and then I have the main file for the class:

Code:
#include "texture.hpp"

// This is the first draft of our class.
// Soon, this segment of 1's and 0's will evolve into
// an omnipotent being that will dominate the known
// world ...

    texture::texture()
    {
    }
    texture::~texture()
    {
    delete[] m_Image;
    }
    
    // This is the function that will load our bitmap file
int texture::LoadBMP( const char *sFileName )
{

    BITMAPFILEHEADER    BMFH; // Header of the file
    BITMAPINFOHEADER    BMIH; // Header for the image
                              // These two structs together make up the entire header of the bmp file format

    FILE *pFile;     // The pointer to our file

    int iSize;       // The size of the image, in bytes
    int q, p;        // just two integers that are used for flipping.

    pFile = fopen( sFileName, "rb" );
                     // We open the file to "read/binary"


    if( !pFile )    // If we somehow failed to open the file,
        return 0;

    
    fread( &BMFH, 1, sizeof( BITMAPFILEHEADER ), pFile );
            // We read the first part of the header to our struct

    fread( &BMIH, 1, sizeof( BITMAPINFOHEADER ), pFile );
            // We rea the second part of the header to our struct

    // Every .bmp (or .dib) starts with "BM".
    // If the this one doesn't, something is seriously wrong!
    if( BMFH.bfType != 19778 ) // 19778 == "BM"
    {

        fclose( pFile );   // Close the file
        return -1;         // Say the file is an invalid BMP

    }

    m_iWidth  = BMIH.biWidth;   // Set the class' width
    m_iHeight = BMIH.biHeight;  // and height to the image's

    iSize = BMIH.biWidth*BMIH.biHeight*3;
                                // Set the Size to the correct one
                                // it's the width in pixels,
                                // times the height in pixels,
                                // times the number of channels per pixel


    unsigned char *Temp;        // We need to have something to store temporary pixels in
                                // This will be used to read from the file, and to flip the image


    Temp = new unsigned char[iSize]; // This is deleted at the end of the function
    m_Image = new unsigned char[iSize+BMIH.biWidth]; // And this in ~CTexture()

    /*

    Okay, we are about to read the image data. I must tell you about the way BMP stores its pixels;
it's very wierd. First of all, it's flipped downwards. This means that if your image looks like
this:


                                                                            /|                        / |                        /  |  
  It will be stored like this:

        
                       \  |  /
                        \ | /
                         \|/
                          /
                         /

    Secondly, the pixel colors aren't stored as R, G and then the B value, but the other way around:
    B, G and then R. So if you ever find yourself writing your own BMP loader, miond this!

  Kudos to the arabian inventor of the BMP file format!

  */


    // So to avoid most problems, we will read everything backwards. This means that the pixel colors
    // will be okay, but the image will no longer be flipped downwards, but sidewards. This is easier
    // to solve, and we will do so later.
    for( int i = iSize - 1; i >= 0 ; )
    {

        fread( &Temp[i--],   1, 1, pFile ); // Blue value
        fread( &Temp[i--],   1, 1, pFile ); // Green value
        fread( &Temp[i--],   1, 1, pFile ); // Red value

    }

    // So now our image is completely okay, except for the fact that we have to flip it sidewards.
    // So that is what we are going to do right now:
    for( int i = 0 ; i < iSize ; i = i + BMIH.biWidth * 3 )
    {            // Go through every horizontal LINE of the image
                // (remember it's 3 channels per pixel!)

        p = 0;                    // Set p to 0
        q = BMIH.biWidth * 3;    // Set q to the max

        while( q >= 0 )        // While the one increases,
        {                    // And the other decreases,

            m_Image[i+p + 0] = Temp[i+q + 0]; // Red
            m_Image[i+p + 1] = Temp[i+q + 1]; // Green
            m_Image[i+p + 2] = Temp[i+q + 2]; // Blue
            p = p + 3;        // Increase p, and
            q = q - 3;      // Decrease q

        }

    }

    // Everything has been loaded, so we can close the file.

    fclose( pFile );

    delete[] Temp; // We delete the memory that has been allocated

    return 1; // We return a positive!

}


    // This will have OpenGL turn your pixels into a real texture :)
    void texture::generate()
    {

    // Generate one texture and let m_uiTexID be our handle to it
    glGenTextures(1, &m_uiTexID);
  
    // Here we set up the filtering.
    glBindTexture(GL_TEXTURE_2D, m_uiTexID);
    glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

    // and here we feed our width, height and pixels to OpenGL
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_iWidth, m_iHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, m_Image);
    gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, m_iWidth, m_iHeight, GL_RGB, GL_UNSIGNED_BYTE, m_Image);
    }


// This will give you the texture's ID
GLuint texture::GetID()
{
return m_uiTexID;
}

In a different file, I have this code to load a bitmap:

Code:
texture theTexture;
    theTexture.LoadBMP(textureFileName); //where textureFileName is the name of the bitmap image to be loaded
    theTexture.generate();

Then in the openGL drawing code, I have this code to draw a texture-mapped square:

Code:
glBindTexture(GL_TEXTURE_2D, theTexture.GetID());
    
         glBegin(GL_POLYGON);
         glTexCoord2f(0.0,0.0);
         glVertex3f(-1.0,-1.0,0.0);
         glTexCoord2f(0.0,1.0);
         glVertex3f(1.0,-1.0,0.0);
         glTexCoord2f(1.0,1.0);
         glVertex3f(1.0,1.0,0.0);
         glTexCoord2f(0.0,1.0);
         glVertex3f(-1.0,1.0,0.0);
         glEnd();

My bitmap is 4 X 4 pixels, and I have texure enabled with the command glEnable(GL_TEXTURE_2D);

When I run the code, all I get is a white square, instead of a textured one. Any ideas to what could be going wrong? I am pretty sure that most of the above code works because I did get a variation of it working (unfortunately, I've lost the source code Sad )
Any help is appreciated Smile
-wyrmmage

Worlds at War (Current Project) - http://www.awkward-games.com/forum/
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #2
Are you sure it's loading the texture correctly?

A couple of suggestions, even though they aren't critical, in increasing inefficiency:
First of all, if you're drawing a quad, you can use glBegin(GL_QUADS); I don't know if it's actually any less efficient for calling GL_POLYGON for a quad, but I'd imagine it must need to do more. Second of all, there's no reason to keep m_Image: the data is copied into OpenGL's memory when you load it with an OpenGL texture loading function, so it's just taking up unneeded space. Finally, glTexImage2D and gluBuild2DMipmaps are both called. Only 1 need be called, the other is just going to destroy what the previous one called. I suggest for this case you use glTexImage2D, but in a game you'd likely want gluBuild2DMipmaps.

Just as a bit of personal opinion: that class you downloaded could be... much better. Other than the 2 reasons that I mentioned earlier, it's obviously suited for Windows, and it deals with a... rather inefficient format. (BMP) My suggestion is that you use a 3rd party library (such as libpng) to load your images, then make your own texture loading/creating functions. (whether in a class or procedural format I leave to you)
Quote this message in a reply
DoG
Moderator
Posts: 869
Joined: 2003.01
Post: #3
No offense, but scrap that shit and find some proper image loading code. Preferably, some that's for Macs, unless you are doing this on Windows, in which case post on a windows forum.
Quote this message in a reply
Moderator
Posts: 373
Joined: 2006.08
Post: #4
I'm doing this both on Windows and Mac (I change the code depending on the platform). Is GLUT a good way to go as far as image loading? I prefer using hand-coded code rather than libraries, but I suppose that I could go with a library....is libpng cross-platform, I suppose?
Thanks for the help, guys Smile
-wyrmmage

Oh, and what is a good format? I've heard that TGA is good, but I don't have any software that makes TGA files, so it's not great for my purposes.

Worlds at War (Current Project) - http://www.awkward-games.com/forum/
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #5
Hand-coded code is bad, because it's mostly rubbish like what you've posted.

Yes, libPNG is cross-platform. Yes, it's a good choice.

No, TGA is not a good format. It has poor compression, and there's no standard library for loading them.

For a game, there are about three sane image formats: JPEG, PNG, and DDS. I suppose you might find a need for .HDR (Radiance) in the future, too.
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #6
I didn't know of any image loading functionality in GLUT...

I completely understand where you're coming from wanting to code things yourself instead of using a library. I was once the same way. For something like image loading, though, writing your own implementation is often cumbersome, labor-intensive, error-prone, and may involve some guesswork if the format you're reading isn't open/well-documented. libpng is cross-platform, and if PNG works for you, I'd say give it a shot.

As for pros and cons of image formats, pretty much all of them fall short in some way or another. For myself, I use PNG and JPEG for everything; PNG when I need lossless compression or an alpha channel, and JPEG for lossy compression. I'm writing an image editing program, and at some time in the future I expect to devise one or more custom file formats that more closely suit my needs, but until then, these two formats do the job for me quite adequately.
Quote this message in a reply
Moderator
Posts: 373
Joined: 2006.08
Post: #7
Well, I've found the problem Smile

Seems that I was loading all of my textures before initializing openGl at all XD
Easy fix, I just moved a line of code down a bit, and voila, it works! Smile

I suppose that I'll go for a library like libpng then, since you say that it is good Smile Yes, I believe that GLUT provides minimal functionality for image loading, as in NeHe's tutorial: http://nehe.gamedev.net/data/lessons/les...?lesson=06 (I could easily be wrong, I haven't really gone in the route that he did as far as texture loading went). PNG or JPEG is the format that I'll go with, then! Smile

Thanks for the help guys ^_^
-wyrmmage

Worlds at War (Current Project) - http://www.awkward-games.com/forum/
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #8
Except that isn't using any glut functions to load the image...
Quote this message in a reply
Moderator
Posts: 373
Joined: 2006.08
Post: #9
ah, sorry, I was looking at this code:
Code:
    if (File)                                // Does The File Exist?
    {
        fclose(File);                            // Close The Handle
        return auxDIBImageLoad(Filename);                // Load The Bitmap And Return A Pointer
    }

but now that I look at it again, never mind XD
Anyway, thanks again guys, I'm going to post this problem as solved Smile
-wyrmmage

Worlds at War (Current Project) - http://www.awkward-games.com/forum/
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Mapping 2D texture to multiple GL_TRIANGLES ardowz 2 1,119 Mar 12, 2014 08:56 AM
Last Post: ardowz
  Texture mapping single 3D object with one draw call jeonghyunhan 1 2,788 Jul 13, 2009 06:05 AM
Last Post: ThemsAllTook
  Texture coordinate problem Oddity007 0 2,037 Jan 21, 2009 06:20 PM
Last Post: Oddity007
  Texture Mapping: Loading a texture from a .bmp file? ishrock 5 6,247 Dec 13, 2008 09:27 AM
Last Post: ThemsAllTook
  Porting SDL to Cocoa OpenGL view--texture problem smittyz 7 5,194 Jul 21, 2007 07:53 PM
Last Post: smittyz