Skip to main content
gamedev.net
🔒 Locked

problem with textures

Started by evoid May 17, 2009 at 11:05 AM 11 replies 1.2k views
Original Post
evoid
evoid
Hi, I am trying to texture a scene I've written in C++ utilizing OpenGL. Purposeful I have written the following class for handling textures:
class Texture
{

    private:

        Texture (const GLuint nTextureID) : m_nTextureID (nTextureID) { }


    public:

        ~Texture () { glDeleteTextures (1, &m_nTextureID); }


    public:

        static Texture* loadFromBMP (const std::string& sFile);

        GLuint getID () const
        {
            return m_nTextureID;
        }

        void setActive () const
        {
            glBindTexture (GL_TEXTURE_2D, m_nTextureID);
        }


    private:

        const GLuint m_nTextureID;

};
The function for loading a texture from file is defined as follows:
Texture* Texture::loadFromBMP (const std::string& sFile)
{
    std::ifstream fIn (sFile.c_str (), std::ios::in | std::ios::binary);
    if (fIn.good ())
    {
        try
        {
            // read header
            unsigned short nFormat;
            fIn.read (reinterpret_cast <char*> (&nFormat), 2);
            if (nFormat != 19778)
            {
                std::cerr << "(EE) Failed to read: " << sFile << std::endl;
                std::cerr << "(EE)   Not a Windows Bitmap." << std::endl;
                std::cerr << std::endl;
                fIn.close ();
                return NULL;
            }

            fIn.seekg (18);
            signed int nWidth, nHeight;
            fIn.read (reinterpret_cast <char*> (&nWidth), 4);
            fIn.read (reinterpret_cast <char*> (&nHeight), 4);

            // compute body size
            const unsigned int nBodySize = 3 * nWidth * nHeight;

            // read planes
            unsigned short nPlanes;
            fIn.read (reinterpret_cast <char*> (&nPlanes), 2);

            // read bits per pixel
            unsigned short nBPP;
            fIn.read (reinterpret_cast <char*> (&nBPP), 2);

            // ensure format is supported
            if (nPlanes != 1 || nBPP != 24)
            {
                std::cerr << "(EE) Failed to read: " << sFile << std::endl;
                std::cerr << "(EE)   Unsupported format: " << nBPP << " bpp, " << nPlanes << " plane(s)" << std::endl;
                std::cerr << "(EE)   Only bitmaps with 24 color depth and 1 plane are supported." << std::endl;
                std::cerr << std::endl;
                fIn.close ();
                return NULL;
            }

            // seek past the rest of the header
            fIn.seekg (54);

            // read body data
            char* const pcData = new char [nBodySize];
            fIn.read (pcData, nBodySize);

            // we are done reading the file
            fIn.close ();

            // reverse byte order (convert 'BGR' to 'RGB')
            for (unsigned int j = 0; j < nBodySize ; j += 3)
            {
                pcData [j] ^= pcData [j + 2];
                pcData [j + 2] ^= pcData [j];
            }

            // now we need to create the texture
            GLuint nTextureID;
            glGenTextures (1, &nTextureID);
            glBindTexture (GL_TEXTURE_2D, nTextureID);
            glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

            // 2D texture, level of detail 0 (normal), 3 components (red, green, blue), x size, y size,
            // border 0 (normal), rgb color data, unsigned byte data, and finally the data itself
            glTexImage2D (GL_TEXTURE_2D, 0, 3, nWidth, nHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, pcData);
            delete [] pcData;

            // finish
            return new Texture (nTextureID);
        }
        catch (...)
        {
            fIn.close ();
            std::cerr << "(EE) Failed to read: " << sFile << std::endl;
            std::cerr << "(EE)   Unknown error." << std::endl;
            std::cerr << std::endl;
            return NULL;
        }
    }
    else
    {
        fIn.close ();
        std::cerr << "(EE) Failed to read: " << sFile << std::endl;
        std::cerr << "(EE)   Either file not found or not allowed to open for reading." << std::endl;
        std::cerr << std::endl;
        return NULL;
    }
}
So far. When the program is initialized I call these:
static Texture* s_aTextures []; // member of a class named C

// [...]

Texture* C::s_aTextures [] = { NULL, NULL, NULL, NULL, NULL, NULL };

// [...]

s_aTextures [0] = Texture::loadFromBMP ("test1.bmp");
s_aTextures [1] = Texture::loadFromBMP ("test2.bmp");
s_aTextures [2] = Texture::loadFromBMP ("test3.bmp");
s_aTextures [3] = Texture::loadFromBMP ("test4.bmp");
s_aTextures [4] = Texture::loadFromBMP ("test5.bmp");
s_aTextures [5] = Texture::loadFromBMP ("test6.bmp");
When 'pre-rendering' the scene into a display-list I call setActive on the various elements of the array:
s_aTextures [2] -> setActive ();
The actual problem: Everything that I render is being drawn with one and the same texture, although I call setActive on different textures. To be precisely, everything is being rendered with the texture I have created (loaded) lastly - Dont't misunderstand me, it's not the texture I call setActive upon lastly. I have no idea what I could have done wrong. The local variable nTextureID in Texture::loadFromBMP has a correct value, namely an unique one everytime the function is called. Anyone got an idea? Thanks in advance
mrr
mrr
I am not a C++ expert but why do you not let the memmber function loadFromBMP update m_nTextureID directly? Im not sure it is the way you do it.
AndyEsser
AndyEsser
Don't make the Texture class a Static. Try that.
evoid
evoid
Quote:
Original post by mrr
I am not a C++ expert but why do you not let the memmber function loadFromBMP update m_nTextureID directly? Im not sure it is the way you do it.


Actually loadFromBMP does update m_nTextureID directly by calling the constructor of Texture.

Quote:
Original post by AndyEsser
Don't make the Texture class a Static. Try that.


What do you mean? Can you explain that? I don't know what a static class is and as far as I can see I haven't used static classes.

In case you meant making the function loadFromBMP non-static: I tried it and it did not change anything.

Anyway, here are the altered files, in case you want to take a look on them:
texture.cpp: http://pastebin.com/f74e9ac1a
texture.h: http://pastebin.com/f7001a619

Or did you mean making the instances of Texture non-static? I tried that too but also without any effect.
AndyEsser
AndyEsser
In your header file you have commented out the line:

//static Texture* loadFromBMP (const std::string& sFile);

How come?

Have you tried it with just

Texture* loadFromBMP (const std::string& sFile);

And have you checked when doing SetActive that the value in m_nTextureID is different for each texture?

Also, it was this line I meant don't make static:

static Texture* s_aTextures []; // member of a class named C
evoid
evoid
Quote:
Original post by AndyEsser
In your header file you have commented out the line:

//static Texture* loadFromBMP (const std::string& sFile);

How come?

Have you tried it with just

Texture* loadFromBMP (const std::string& sFile);

I had moved the loadFromBMP-functionallity to the Texture::Texture(const std::string&) constructor. So, to answer your question: Yes, I've tried it.

Quote:
Original post by AndyEsser
And have you checked when doing SetActive that the value in m_nTextureID is different for each texture?

Yes, I've checked this. All values are definetly unique.

Quote:
Original post by AndyEsser
Also, it was this line I meant don't make static:

*** Source Snippet Removed ***

OK. As I wrote in my previous post, I've tried making it non-static but had no luck.
AndyEsser
AndyEsser
Apologies, wasn't sure exactly which bit you meant you had tried. Could you show me your rendering routine?
evoid
evoid
Sure, here it is:

void C::draw (){    glEnable (GL_TEXTURE_2D);    glColor3ub (230, 230, 230);    glBegin (GL_QUADS);        // front        s_aTextures [0] -> setActive ();        //std::cout << s_aTextures [0] -> getID () << std::endl;        glTexCoord2f (0.0f, 0.0f);  glVertex3f (-1.0f, -1.0f,  1.0f);        glTexCoord2f (0.0f, 1.0f);  glVertex3f (-1.0f,  1.0f,  1.0f);        glTexCoord2f (1.0f, 1.0f);  glVertex3f ( 1.0f,  1.0f,  1.0f);        glTexCoord2f (1.0f, 0.0f);  glVertex3f ( 1.0f, -1.0f,  1.0f);        // back        s_aTextures [1] -> setActive ();        //std::cout << s_aTextures [1] -> getID () << std::endl;        glTexCoord2f (0.0f, 0.0f);  glVertex3f ( 1.0f, -1.0f, -1.0f);        glTexCoord2f (0.0f, 1.0f);  glVertex3f ( 1.0f,  1.0f, -1.0f);        glTexCoord2f (1.0f, 1.0f);  glVertex3f (-1.0f,  1.0f, -1.0f);        glTexCoord2f (1.0f, 0.0f);  glVertex3f (-1.0f, -1.0f, -1.0f);        // left        s_aTextures [2] -> setActive ();        glTexCoord2f (0.0f, 0.0f);  glVertex3f (-1.0f, -1.0f, -1.0f);        glTexCoord2f (0.0f, 1.0f);  glVertex3f (-1.0f,  1.0f, -1.0f);        glTexCoord2f (1.0f, 1.0f);  glVertex3f (-1.0f,  1.0f,  1.0f);        glTexCoord2f (1.0f, 0.0f);  glVertex3f (-1.0f, -1.0f,  1.0f);        // right        s_aTextures [3] -> setActive ();        glTexCoord2f (0.0f, 0.0f);  glVertex3f ( 1.0f, -1.0f,  1.0f);        glTexCoord2f (0.0f, 1.0f);  glVertex3f ( 1.0f,  1.0f,  1.0f);        glTexCoord2f (1.0f, 1.0f);  glVertex3f ( 1.0f,  1.0f, -1.0f);        glTexCoord2f (1.0f, 0.0f);  glVertex3f ( 1.0f, -1.0f, -1.0f);        // top        s_aTextures [4] -> setActive ();        glTexCoord2f (0.0f, 0.0f);  glVertex3f (-1.0f,  1.0f,  1.0f);        glTexCoord2f (0.0f, 1.0f);  glVertex3f (-1.0f,  1.0f, -1.0f);        glTexCoord2f (1.0f, 1.0f);  glVertex3f ( 1.0f,  1.0f, -1.0f);        glTexCoord2f (1.0f, 0.0f);  glVertex3f ( 1.0f,  1.0f,  1.0f);        // bottom        s_aTextures [5] -> setActive ();        glTexCoord2f (0.0f, 0.0f);  glVertex3f ( 1.0f, -1.0f,  1.0f);        glTexCoord2f (0.0f, 1.0f);  glVertex3f ( 1.0f, -1.0f, -1.0f);        glTexCoord2f (1.0f, 1.0f);  glVertex3f (-1.0f, -1.0f, -1.0f);        glTexCoord2f (1.0f, 0.0f);  glVertex3f (-1.0f, -1.0f,  1.0f);    glEnd ();    glDisable (GL_TEXTURE_2D);}
AndyEsser
AndyEsser
Have you tried replacing your setActive() call with:

glBindTexture (GL_TEXTURE_2D, s_aTextures [0] -> getID () );

Changing the 0 accordingly obviously.
evoid
evoid
Have tried it right now, no luck, looks still the same.
AndyEsser
AndyEsser
I'm fresh out of ideas except for one last one, and apologies if you've already tried this.

In your constructor you have this:

Texture::Texture (const std::string& sFile)

If you change it to this, does it help at all:

Texture::Texture (std::string& sFile)

Have you breakpointed it on entry to check that the correct path is being passed?

Other than that I'm afraid I'm all out of ideas.
Brother Bob
Brother Bob
You cannot change active texture within a glBegin/glEnd pair. If you need to change texture for each face, you need to start a new pair as well.
AndyEsser
AndyEsser
How the hell did I not notice that. Lol, my bad. Apologies.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.