problem with textures

Started by
11 comments, last by AndyEsser 14 years, 11 months ago
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
Advertisement
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.
Don't make the Texture class a Static. Try that.
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.
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
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.
Apologies, wasn't sure exactly which bit you meant you had tried. Could you show me your rendering routine?
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);}
Have you tried replacing your setActive() call with:

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

Changing the 0 accordingly obviously.
Have tried it right now, no luck, looks still the same.

This topic is closed to new replies.

Advertisement