program crashing when glubuild2dmipmap is called

so in the process of loading a .3ds file into my program i past the part of getting the triangular mesh vertices, polygons, uv coords, material properties, and the texture filenames. now i’m onto the step of actually loading the texture files for use in rendering. however, i have hit a snag – whenever i try to call gluBuild2dMipmaps() the program crashes before ever drawing a frame.

i have narrowed it down to the call of gluBuild2dMipmaps because when i comment it out, the program runs fine. i would like to keep the call in there because mipmaps provide some visual improvment to the different textures, correct?

i’m using DevIL to load the images and then assign/bind them to a GLuint variable called textureidnum. the filename variable is a c++ string.

anyways, here is the code that is breaking (with some of the variable names simplified for brevity):

for(int k = 0; k < testobj.nummaterials; k++)
{
  if(testobj.materials[k].filename.size() > 0)
  {
    ilGenImages(1, &ImageName);
    ilBindImage(ImageName);
    ilLoadImage(const_cast<char*> (testobj.materials[k].filename.c_str()));
    testobj.materials[k].textureidnum = ilutGLBindTexImage();
    gluBuild2DMipmaps(GL_TEXTURE_2D, 3, ilGetInteger(IL_IMAGE_WIDTH), ilGetInteger(IL_IMAGE_HEIGHT), GL_RGB8, GL_UNSIGNED_BYTE, ilGetData());
    ilDeleteImages(1, &ImageName);
  }
}

any help would be most appreciated!

Change the 3 to GL_RGB8 or GL_RGBA8 depending on if you are using 24bit or 32bit images. For the format parameter which you have set to GL_RGB8 is wrong, set this to GL_RGB or GL_RGBA depending on what textures you are using.

well, unfortunately neither of those options helped. :frowning:

i’m using .tif files and i don’t believe there are any alpha values, but i tried GL_RGBA8 and GL_RGBA just in case and that didn’t work.

so i’m still stuck. i’m thinking of just loading the files and then after that going back through to see which files actually loaded and then rebinding and mipmapping them outside of the loading loop. i’ll report on how that works, unless someone can think of another fix that might exist for the current code i have.

thanks for the suggestion!

You only use GL_RGBA if your textures are 32bit. I am guessing they aren’t so try GL_RGB8 for the internal format and GL_RGB for the format(one next to GL_UNSIGNED_BYTE) if this doesn’t work does glTexImage2D() work?

i’ll try that. i have one question that i haven’t really been able to find the answer to: what exactly is the purpose of the mipmap and how do i know if it is in use?

okay, something is very very wrong with the code i have written beyond the call to gluBind2DMipmaps().

this code will compile and execute:

for(int i = 0; i < testobj.nummaterials; i++)
{
  if(testobj.materials[i].texture.filename.size() > 0)
  {
    cout << "Loading texture " << testobj.materials[i].texture.filename << endl;

    ilGenImages(1, &ImageName);
    ilBindImage(ImageName);
    testobj.materials[i].texture.textureidnum = ilutGLBindTexImage();
//      gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB8, ilGetInteger(IL_IMAGE_WIDTH), ilGetInteger(IL_IMAGE_HEIGHT), GL_RGB, GL_UNSIGNED_BYTE, ilGetData());
//      glTexImage2D(GL_TEXTURE_2D, 3, 3, ilGetInteger(IL_IMAGE_WIDTH), ilGetInteger(IL_IMAGE_HEIGHT), 0, GL_RGB, GL_UNSIGNED_BYTE, ilGetData());
    ilDeleteImages(1, &ImageName);
  }
  cout << "testobj.nummaterials part 2: " << testobj.nummaterials << endl;
  cout << "i part 2: " << i << endl;
}

so i added a check to make sure that the files were being opened correctly, and this code compiles and executes:

for(int i = 0; i < testobj.nummaterials; i++)
{
  if(testobj.materials[i].texture.filename.size() > 0)
  {
    cout << "Loading texture " << testobj.materials[i].texture.filename << endl;

    ilGenImages(1, &ImageName);
    ilBindImage(ImageName);
    if(ilLoadImage(const_cast<char*> (testobj.materials[i].texture.filename.c_str())) == IL_FALSE)
    {
      cout << "unable to open: " << testobj.materials[i].texture.filename << endl;
    }
    else
    {
      testobj.materials[i].texture.textureidnum = ilutGLBindTexImage();
//        gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB8, ilGetInteger(IL_IMAGE_WIDTH), ilGetInteger(IL_IMAGE_HEIGHT), GL_RGB, GL_UNSIGNED_BYTE, ilGetData());
//        glTexImage2D(GL_TEXTURE_2D, 3, 3, ilGetInteger(IL_IMAGE_WIDTH), ilGetInteger(IL_IMAGE_HEIGHT), 0, GL_RGB, GL_UNSIGNED_BYTE, ilGetData());
      ilDeleteImages(1, &ImageName);
    }
  }
  cout << "testobj.nummaterials part 2: " << testobj.nummaterials << endl; // check to make sure that the nummaterials hasn't changed somehow
  cout << "i part 2: " << i << endl; // same for the iterator
}

so i finally decide to uncomment the gluBuild2DMipmap(). it compiles however it then crashes on execution of this code:

for(int i = 0; i < testobj.nummaterials; i++)
{
  if(testobj.materials[i].texture.filename.size() > 0)
  {
    cout << "Loading texture " << testobj.materials[i].texture.filename << endl;

    ilGenImages(1, &ImageName);
    ilBindImage(ImageName);
    if(ilLoadImage(const_cast<char*> (testobj.materials[i].texture.filename.c_str())) == IL_FALSE)
    {
      cout << "unable to open: " << testobj.materials[i].texture.filename << endl;
    }
    else
    {
      testobj.materials[i].texture.textureidnum = ilutGLBindTexImage();
        gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB8, ilGetInteger(IL_IMAGE_WIDTH), ilGetInteger(IL_IMAGE_HEIGHT), GL_RGB, GL_UNSIGNED_BYTE, ilGetData());
//        glTexImage2D(GL_TEXTURE_2D, 3, 3, ilGetInteger(IL_IMAGE_WIDTH), ilGetInteger(IL_IMAGE_HEIGHT), 0, GL_RGB, GL_UNSIGNED_BYTE, ilGetData());
      ilDeleteImages(1, &ImageName);
    }
  }
  cout << "testobj.nummaterials part 2: " << testobj.nummaterials << endl;
  cout << "i part 2: " << i << endl;
}

so i try commenting out gluBuild2DMipmap and uncommenting glTexImage2D and i get the same result as when i use gluBuild2DMipmap.

so i try uncommenting buildmipmap and recommenting teximage2d and commenting out:

cout << "testobj.nummaterials part 2: " << testobj.nummaterials << endl;

just to see what happens, and low-an-behold it all of a sudden compiles and executes! this is the code:

for(int i = 0; i < testobj.nummaterials; i++)
{
  if(testobj.materials[i].texture.filename.size() > 0)
  {
    cout << "Loading texture " << testobj.materials[i].texture.filename << endl;

    ilGenImages(1, &ImageName);
    ilBindImage(ImageName);
    if(ilLoadImage(const_cast<char*> (testobj.materials[i].texture.filename.c_str())) == IL_FALSE)
    {
      cout << "unable to open: " << testobj.materials[i].texture.filename << endl;
    }
    else
    {
      testobj.materials[i].texture.textureidnum = ilutGLBindTexImage();
      gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB8, ilGetInteger(IL_IMAGE_WIDTH), ilGetInteger(IL_IMAGE_HEIGHT), GL_RGB, GL_UNSIGNED_BYTE, ilGetData());
//        glTexImage2D(GL_TEXTURE_2D, 3, 3, ilGetInteger(IL_IMAGE_WIDTH), ilGetInteger(IL_IMAGE_HEIGHT), 0, GL_RGB, GL_UNSIGNED_BYTE, ilGetData());
      ilDeleteImages(1, &ImageName);
    }
  }
//    cout << "testobj.nummaterials part 2: " << testobj.nummaterials << endl;
  cout << "i part 2: " << i << endl;
}

the catch though is that after loading the first texture the value of i goes from the correct number of 1 (cause it is on loop #2 due to the first two materials not having a texture filename) to 28966984. how it does this is beyond me.

so i try uncommenting the “cout” statement and recompiling and executing and again it crashes. so i test taking out the

cout << "i part 2: " << i << endl;

statement and compiling and running the program. that runs fine too.

what does this mean? i have no clue other than something is royally effed up because no where should the value of i be changed except at the end of the for loop. and it should be noted that the value of nummaterial is not changing at any time. so i’m completely stuck. it makes no sense what is going on.

does anyone have any ideas?

just for interest- are you sure that you have a valid context made current before calling Build2DMipmaps?

if by that you mean an active and initialized window, then i believe so because when the program compiles and executes it will go to a fullscreen like it should. and if you mean glEnable(GL_TEXTURE_2D) then yes, that is called in my “initializevisuals()” function.

the devilinit function calls ilinit, iluinit, and ilutrenderer(ILUT_OPENGL). currently createmapDL does nothing because i wanted to make sure this would get through loading files correctly, and since it isn’t i haven’t bothered to uncomment the body of that function (just left the header so it compiles).

here is the main:

int main()
{
  DEVILINIT();

  if(!Load3dsFile("Arzion.3ds"))
  {
    cout << "failed to load map!" << endl;
    glfwTerminate();
    return 1;
  }
  
  int running = GL_TRUE;

  glfwInit();
  
  if(!glfwOpenWindow(WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0, 0, 0, 32, 0, GLFW_FULLSCREEN))
  {
    glfwTerminate();
    return EXIT_FAILURE;
  }
  glfwSetWindowPos(50, 70);
  glfwSetWindowTitle("GLFW Game");
	
  initializecallbacks();
  initializevisuals();
  
  for(int i = 0; i < testobj.nummaterials; i++)
  {
    if(testobj.materials[i].texture.filename.size() > 0)
    {
      cout << "Loading texture " << testobj.materials[i].texture.filename << endl;
  
      ilGenImages(1, &ImageName);
      ilBindImage(ImageName);
      if(ilLoadImage(const_cast<char*> (testobj.materials[i].texture.filename.c_str())) == IL_FALSE)
      {
        cout << "unable to open: " << testobj.materials[i].texture.filename << endl;
      }
      else
      {
        testobj.materials[i].texture.textureidnum = ilutGLBindTexImage();
        cout << "testobj.materials[i].texture.textureidnum: " << testobj.materials[i].texture.textureidnum << endl;
        gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB8, ilGetInteger(IL_IMAGE_WIDTH), ilGetInteger(IL_IMAGE_HEIGHT), GL_RGB, GL_UNSIGNED_BYTE, ilGetData());
        ilDeleteImages(1, &ImageName);
      }
    }
    cout << "testobj.nummaterials part 2: " << testobj.nummaterials << endl;
//    cout << "i part 2: " << i << endl;
  }
  
  DLid = createmapDL();

  glfwSwapInterval(0);

  while(running)
  {
    display();
  }

  glfwTerminate();

  return EXIT_SUCCESS;
}

this will execute.

i honestly don’t know what is wrong because before i was testing using 2 textures that had static names and everything worked fine. now though i have no idea what is wrong. and why i can’t have the two “cout” statements at the same time makes no sense whatsoever. i’m completely stumped as to what is wrong. especially strange is why the value of i is changing when “gluBuild2DMipmaps()” is called and isn’t when that function isn’t called. that makes absolutely no sense.

edit:

here is a working version of the code with static texture file names with a working call to gluBuild2DMipmaps:

texturefilename[0] = "grass.png";
texturefilename[1] = "spaceshiptexture.bmp";

for(int i = 0; i < 2; i++)
{
  ilGenImages(1, &ImageName);
  ilBindImage(ImageName);
  if(ilLoadImage(texturefilename[i]) == IL_FALSE)
  {
    cout << "unable to open: " << texturefilename[i] << endl;
  }
  else
  {
    Texture[i] = ilutGLBindTexImage();
    gluBuild2DMipmaps(GL_TEXTURE_2D, 3, ilGetInteger(IL_IMAGE_WIDTH), ilGetInteger(IL_IMAGE_HEIGHT), GL_RGB8, GL_UNSIGNED_BYTE, ilGetData());
    ilDeleteImages(1, &ImageName);
  }
}

okay, not sure how many people looked at this, but i got a work around made.

here it is:

for(int i = 0; i < testobj.nummaterials; i++)
{
  testobj.materials[i].texture.textureidnum = -1;
  if(testobj.materials[i].texture.filename.size() > 0)
  {
    ilGenImages(1, &ImageName);
    ilBindImage(ImageName);
    if(ilLoadImage(const_cast<char*> (testobj.materials[i].texture.filename.c_str())) == IL_FALSE)
    {
      cout << "unable to open: " << testobj.materials[i].texture.filename << endl;
    }
    else
    {
      testobj.materials[i].texture.textureidnum = ilutGLBindTexImage(); // get the GLuint bound value
      testobj.materials[i].texture.texwidth = ilGetInteger(IL_IMAGE_WIDTH); // store the image width
      testobj.materials[i].texture.texheight = ilGetInteger(IL_IMAGE_HEIGHT); // store the image height
      testobj.materials[i].texture.data = ilGetData(); // store pointer to image data
    }
    ilDeleteImages(1, &ImageName);
  }
}
  
for(int i = 0; i < testobj.nummaterials; i++)
{
  if(testobj.materials[i].texture.textureidnum > 0)
  {
    glBindTexture(GL_TEXTURE_2D, testobj.materials[i].texture.textureidnum);
    gluBuild2DMipmaps(GL_TEXTURE_2D, 3, testobj.materials[i].texture.texwidth, testobj.materials[i].texture.texheight, GL_RGB8, GL_UNSIGNED_BYTE, testobj.materials[i].texture.data); // use all those new variables
  }
}

as you can see i broke the “gluBuild2DMipmaps” out to another loop which seems to solve the problem (but this could just be treating symptoms and not sicknesses). the downside is that i had to add new member variables to my texture struct and now i’m having to rebind every texture. but i guess that may not be such an issue in the long run.

interesting occurance: originally i didn’t assign the textureidnum to “-1” because i thought every int was initialized to zero and so any texture without a file name would have an id of 0. so when i first implemented the two loops i thought i was out of trouble because then i could draw the scene by looping through the materials and applying that texture to only the associated polygons. well i ran into the problem that the unbound ids weren’t actually zero. so to solve that i just set everything to -1 first and then anything that had a real texture got that value assigned to it. so anyways, that worked. and then i ran into another issue from reading the .3ds file that i knew how to fix already (bizzare input stuff, but like i said, had that one already fixed from a previous occurance).

anyways, thanks to all those that bothered to read this and offer moral support! :slight_smile: