glGenTexture problem (or something else...)

Hi,
I’ve some code loading a medical picture as 2D texture like this (problem’s explained after) :

void load_texture () {	
   GLfloat *params;
   GLubyte *raw_bitmap;
   //here starts my problem
   if (!file_name) 
      Form1->file_name= "test.dcm"; //A: like this it works
      //return; //B: black screen (cfr explanations)
   else file_name= "test.dcm"; //B: doesn't work even if I do this (so it's not a path problem)
   raw_bitmap = chargementImage(&Image_Width,&Image_Height); //file_name is global   
   if (raw_bitmap) {
      if (allocated)
          glDeleteTextures(1, texture_id);
      else
          allocated= true;
      if (glIsTexture(texture_id[0])==GL_TRUE)
         glDeleteTextures(1, texture_id);
      glGenTextures (1, texture_id);
      glBindTexture (GL_TEXTURE_2D, texture_id[0]);
      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Image_Width, Image_Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, raw_bitmap);
      free (raw_bitmap);
   }  else
      allocated= false;
}
//------------------------------------------------------------------------------
void draw_texture (int number) {
   float tempX= -0.5f, tempY=-0.5f;
   int i;
   glEnable(GL_TEXTURE_2D);
   glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
   glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
   glPushMatrix ();
   glColor3f (1.0, 1.0, 1.0);
   glBindTexture (GL_TEXTURE_2D, texture_id[number]);
   glTranslatef(panX0+panX, panY0+panY, 0.);
   glScalef(fact,fact,1.0);
   glBegin (GL_QUADS);
      glTexCoord2f(0.0f, 0.0f); glVertex3f(tempX, tempY, 0.);
      glTexCoord2f(1.0f, 0.0f); glVertex3f(tempX+1.0F, tempY, 0.);
      glTexCoord2f(1.0f, 1.0f); glVertex3f(tempX+1.0F, tempY+1.0F, 0.);
      glTexCoord2f(0.0f, 1.0f); glVertex3f(tempX, tempY+1.0F, 0.);
   glEnd ();
   glColor3f (1.0, 0.0, 0.0);
   glDisable(GL_TEXTURE_2D);
   if (C1.finished) {
      glBegin (GL_LINE_LOOP);
         for (i=0; i<C1.nbr; ++i)
            glVertex3f(C1.points[i].x,C1.points[i].y,0.);
      glEnd ();
   } else
      for (i=1; i<C1.nbr; ++i) {
         glBegin (GL_LINES);
            glVertex3f(C1.points[i-1].x,C1.points[i-1].y,0.);
            glVertex3f(C1.points[i].x,C1.points[i].y,0.);
         glEnd();
      }
   glColor3f (0.0, 1.0, 0.0);
   for (i=0; i<C1.nbr; ++i) {
      glBegin (GL_QUADS);
         glVertex3f(C1.points[i].x-0.004f,C1.points[i].y-0.004f,0.);
         glVertex3f(C1.points[i].x-0.004f,C1.points[i].y+0.004f,0.);
         glVertex3f(C1.points[i].x+0.004f,C1.points[i].y+0.004f,0.);
         glVertex3f(C1.points[i].x+0.004f,C1.points[i].y-0.004f,0.);
      glEnd ();
   }
   glPopMatrix ( );
}

(C++ Builder 5)

I’d like to load my texture or change it with the BCB File selection component but I can’t get it working!
Altough it works fine when I load the texture giving the name of the file manually on the first pass (cfr the comment : //here is the problem).

When I trace the error I see that glGenTexture doesn’t allow a name when I don’t do it manually at the first o_O

Summary of my problem :
A. Init the file_name var with the relative path of my image :

  1. init my prog
  2. load texture giving the “filename” manually (as none has been selected yet : initialisation)
  3. texture_id has 1 after glGenTexture (ok!)
  4. it works (image on the screen)
  5. when I try to select a file after it, it gives me a white screen (my white quad)

B. try to not do it with the initialisation but when i select an image :

  1. init my prog (file_name is NULL)
  2. loading the texture returns NULL as there are no file_name given (this time)
  3. texture_id has 0 after glGenTexture (normal)
  4. my screen is black (it would be a white quad o_O I don’t understand this)
  5. try to select an image
  6. texture_id has 0 after glGenTexture (weird problem as nothing change but the time when I set file_name - even if i put it manually at this moment so it’s not a path problem)
  7. My screen is white (my quad but no pic on it)

Anyone has an idea? You’re welcome…

Thanks,
acerb

[This message has been edited by acerb (edited 03-19-2003).]

Looks like you’re not specifying the correct filters.
First some general hints.

  • Texture id 0 (zero) is the immediate mode texture.
  • To switch from any texture object to the immediate texture you have to glBindTexture 0.
  • Texture objects store the filter mode among other state (look in the specs).
  • Default texture filters are for mag: GL_LINEAR, for min: GL_LINEAR_MIPMAP_NEAREST (mipmapped!).

glEnable(GL_TEXTURE_2D);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Which texture object is active? Immediate mode texture 0?
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glPushMatrix ();
glColor3f (1.0, 1.0, 1.0);
glBindTexture (GL_TEXTURE_2D, texture_id[number]); // Which filters does this have? Defaults?

You need to check WHEN you set the filters. That needs to be done once for each texture object. That is, first bind the texture object and then set the filters while it is bound. If you bind it again, the settings stored in the object are automatically set.

In case you don’t do that, the texture assumes to have the default filters, but you haven’t specified a mipmapped texture, which leaves the texture inconsistent.
Inconsistent textures will disable the texture unit in which it is bound.

[This message has been edited by Relic (edited 03-20-2003).]

DAMN! I just spent 15 minutes answering this on the beginners forum. Ok, so I’m waiting for my animation assignment to render and don’t have anything better to do anyway, but still. NEVER post the same question on multiple forums again!

-Ilkka

I see several logic problems, btw.

First, you don’t need both checks for whether to delete the texture – the glIsTexture() is superfluous.

Second, you don’t need to delete a texture and re-generate the texture Id to re-specify the image. Just use TexImage on an existing texture name.

Thus, your entire code at the top could probably collapse to something like:

if( texture_id[0] == 0 ) {
glGenTextures( 1, texture_id );
}
glBindTexture( GL_TEXTURE_2D, texture_id[0] );
glTexImage2D( … );

You don’t need “allocated” at all, assuming the constructor initializes texture_id to 0. If loading the data failed, you could delete the texture and set texture_id to 0 again; that’s a sum total of 2 if()-s and rather simpler logic and shorter code.

If texture_id[] is an array of a single element, you probably just want to make it a single element (not an array) and use “&texture_id” in GenTextures, btw.

Hi,

Thanks all, I’m trying those things…
But first, Sorry Ilkka, someone on the beginner’s forum said me to put it on the advanced as nobody seemd to see something ang i got no answer, but I forgot to delete it in the beginner’s forum =/
Some explanations:

  • I call glTexParameter when drawing because sometimes I’ve to switch between linear and nearest dynamically… (and it works when I draw the first time) but maybe I’ve to set it at the textures generation and the drawing ??? Before it was :

glEnable(GL_TEXTURE_2D);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);

(was trying to simplify but I shouldn’t change my code for the post, sorry)

  • It’s the same about the glDeletetextures lines :
if (allocated)
   glDeleteTextures(1, texture_id);
else
   allocated= true;
if (glIsTexture(texture_id[0])==GL_TRUE)
   glDeleteTextures(1, texture_id);

Originally, it wasn’t there. It’s just a try to detect my error by myself =/

  • I’ve only 1 texture at the moment but it will change when this step gonna work(…)

Thanks a lot… (still trying) ^^ (and sorry for my english)

acerb

[This message has been edited by acerb (edited 03-21-2003).]

Nah, nevermind, I don’t stay angry for long periods of time. I was just letting out some momentary frustation. Hope you get it work!

-Ilkka

Hi,

Thanks for your indulgence, illka ^^ but it doesn’t work yet =/

Relic :

I’ve tried with glTexParameter after and before glTexBind and it produces the same result… It gives :

//creating texture (1 at the moment):
//------------------------------------
glGenTextures (1, texture_id);
glBindTexture (GL_TEXTURE_2D, texture_id[0]);      
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

//drawing:
//---------
glBindTexture (GL_TEXTURE_2D, texture_id[number]);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); //externally defined
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);

I need to redefine the glTexParameter for my filter to be dynamic (to avoid reload the texture at each change for “filter”) and it works ^^ (dynamically). Is there a better way? The problem is when I wanna load a texture after the initialisation of my program (either it works) =/

jwatte:

I don’t load the texture each time I draw but only when I want to change the texture (with a file selector). So your code seems “strange” (not using glGenTextures each times I want to load a new texture) o_O
What do you mean by (how it could be coded)

If loading the data failed, you could delete the texture and set texture_id to 0 again
I think maybe I’ve not understood your point at all (sorry)

Thanks again.
Continue to make suggestions please ^^

acerb

[This message has been edited by acerb (edited 03-21-2003).]

Ok, I got somethink to work but not like I would do it…

The file is actually not loaded until I select one with
the file selector) and change every call to the file selector.

raw_bitmap is now global :

//loading textures:
void load_texture () {
   if (!Form1->file_name)
      return;
      //Form1->file_name= "test.dcm"; //not needed anymore
   if (raw_bitmap) free(raw_bitmap);
   raw_bitmap = chargementImage(&Image_Width,&Image_Height);
   if (raw_bitmap) {
      //glDeleteTextures(1, texture_id);
      //glGenTextures (1, texture_id); //(2)
      //glBindTexture (0, texture_id[0]); //(2)
      //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); //(2)
      //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); //(2)
      //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Image_Width, Image_Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, raw_bitmap); //(2)
   }
}
//------------------------------------------------------------------------------
//OpenGL Panel Init
void __fastcall TForm1::OpenGLPanel1Init(TObject *Sender)
{
   glViewport(0,0,(GLsizei)OpenGLPanel1->Width,(GLsizei)OpenGLPanel1->Height);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   glOrtho(-0.5, 0.5, -0.5, 0.5, 1., -1.); glMatrixMode(GL_MODELVIEW);
   glMatrixMode (GL_MODELVIEW);
   glLoadIdentity();
   glClearColor (0.0, 0.0, 0.0, 1.0);
}
//---------------------------------------------------------------------------
//OpenGL Panel Resize
void __fastcall TForm1::OpenGLPanel1Resize(TObject *Sender)
{
   glViewport(0,0,(GLsizei)OpenGLPanel1->Width,(GLsizei)OpenGLPanel1->Height);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   glOrtho(-0.5, 0.5, -0.5, 0.5, 1., -1.); 
   glMatrixMode (GL_MODELVIEW);
   glLoadIdentity();
}
//---------------------------------------------------------------------------
//OpenGL Panel Refresh (drawing)
void __fastcall TForm1::OpenGLPanel1Paint(TObject *Sender)
{
   const float point_size= 0.005f;
   float tempX= -0.5f, tempY=-0.5f;
   int i;

   glClear (GL_COLOR_BUFFER_BIT);
   glEnable (GL_TEXTURE_2D);
   //glDeleteTextures(1, texture_id);
   glGenTextures (1, texture_id); //(1)
   glBindTexture (0, texture_id[0]);
   glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Image_Width, Image_Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, raw_bitmap); //(1)!!!

   glPushMatrix ();
   glColor3f (1.0, 1.0, 1.0);
   glTranslatef(panX0+panX, panY0+panY, 0.);
   glScalef(fact,fact,1.0);
   glBegin (GL_QUADS);
   glTexCoord2f(0.0f, 0.0f); glVertex3f(tempX, tempY, 0.);
   glTexCoord2f(1.0f, 0.0f); glVertex3f(tempX+1.0F, tempY, 0.);
   glTexCoord2f(1.0f, 1.0f); glVertex3f(tempX+1.0F, tempY+1.0F, 0.);
   glTexCoord2f(0.0f, 1.0f); glVertex3f(tempX, tempY+1.0F, 0.);
   glEnd ();
   glColor3f (1.0, 0.0, 0.0);
   glDisable(GL_TEXTURE_2D);
   if (C1.finished) {
      glBegin (GL_LINE_LOOP);
         for (i=0; i<C1.nbr; ++i)
            glVertex3f(C1.points[i].x,C1.points[i].y,0.);
      glEnd ();
   } else
         for (i=1; i<C1.nbr; ++i) {
         glBegin (GL_LINES);
            glVertex3f(C1.points[i-1].x,C1.points[i-1].y,0.);
            glVertex3f(C1.points[i].x,C1.points[i].y,0.);
         glEnd();
   }
   glColor3f (0.0, 1.0, 0.0);
   for (i=0; i<C1.nbr; ++i) {
      glBegin (GL_QUADS);
         glVertex3f(C1.points[i].x-point_size,C1.points[i].y-point_size,0.);
         glVertex3f(C1.points[i].x-point_size,C1.points[i].y+point_size,0.);
         glVertex3f(C1.points[i].x+point_size,C1.points[i].y+point_size,0.);
         glVertex3f(C1.points[i].x+point_size,C1.points[i].y-point_size,0.);
      glEnd ();
   }
   glPopMatrix ( );
}
//---------------------------------------------------------------------------
//File selection 
void __fastcall TForm1::Open1Click(TObject *Sender)
{
   OpenDialog1->Filter = "Dicom Images (*.dcm)|*.dcm";
   if (OpenDialog1->Execute())
      file_name= OpenDialog1->FileName.c_str();
   load_texture ();
   OpenGLPanel1->Repaint(); //It's internal to the panel, reloading paint() I presume
}

It works only when the //(1) marked lines aren’t put in
comments. This way, the //(2) marked lines become unnecessary
but it’s weird I’ve to ‘gen’ the texture each frame to
make it work!!!

Help please…
Thanks

acerb

[This message has been edited by acerb (edited 03-21-2003).]

Typo? glBindTexture (0, texture_id[0]); has an illegal target. You’re not working on the texture object at all. You should add some glGetErrors() while debugging.
I didn’t look at the rest.

Hi,

Yup, I replaced glBindTexture (0, texture_id[0]) with glBindTexture (GL_TEXTURE_2D, texture_id[0]) but no change (it’s the thing it was before)

But now I’ll put more glGetErrors() as you say… hoping I’ll get it. Thanks

acerb

I’ve put some glGetError and find out that it seems the problem come from the file selector (component or function)

I got an error when I put a glGetError on it :

void __fastcall TForm1::Open1Click(TObject *Sender) {
   if (glGetError()!= GL_NO_ERROR
      Application->MessageBoxA("4","Error",NULL);
   OpenDialog1->Filter = "Dicom Images (*.dcm)|*.dcm";
   if (OpenDialog1->Execute())
      file_name= OpenDialog1->FileName.c_str();
   Init();
   load_texture ();
   OpenGLPanel1->Repaint();
}

Got no ERROR before o_O (the initialisation is successfull, and the paint loop too).

Any idea? Thanks

[This message has been edited by acerb (edited 03-28-2003).]

It’s still not clear how you program works wrt. OpenGL code.
How can a fileselector produce an OpenGL error?
Are you sure the code works, there’s a brace missing?
Now ask yourself:
When do you init OpenGL?
Before you call glGetError() or in Init()?
If latter, of course glGetError won’t work at its current place, because there’s no rendering context.
What IS the error if it’s not GL_NO_ERROR.

Take a debugger and analyze step by step what your app does. Come back if you know what went wrong exactly.