Reputation: 5157
UPDATE : By the help of @datenwolf I know that the return value of gluBuild2DMipmaps is not the pointer to the texture, instead it's only an error code. I forgot to call glGenTextures and glBindTexture. Look in the method LoadTextureRaw in this answer
I have a problem when rendering multiple object, which each having their own Texture file definition, that is, they all draw the same texture. I create a class hierarchy, CDrawObject->CBall
. In the CDrawObject, I define this :
public ref class CDrawObject
{
protected:
BYTE * dataTexture;
GLuint * texture;
public:
String ^ filename;
CDrawObject(void);
virtual void draw();
void LoadTextureRaw();
};
In the LoadTextureDraw(), I define this:
void CDrawObject::LoadTextureRaw()
{
//GLuint texture;
if(!filename) return;
if(filename->Equals("")) return;
texture = new GLuint;
System::Drawing::Bitmap ^ bitmap = gcnew Bitmap(filename);
int h = bitmap->Height;
int w = bitmap->Width;
int s = w * h;
dataTexture = new BYTE[s * 3];
System::Drawing::Rectangle rect = System::Drawing::Rectangle(0,0,w,h);
System::Drawing::Imaging::BitmapData ^ bitmapData =
bitmap->LockBits(rect,System::Drawing::Imaging::ImageLockMode::ReadWrite , System::Drawing::Imaging::PixelFormat::Format24bppRgb);
::memcpy(dataTexture,bitmapData->Scan0.ToPointer(),s*3);
/* old code
bitmap->UnlockBits(bitmapData);
pin_ptr<GLuint*> pt = &texture;//pin managed pointer, to be unmanaged
**pt = gluBuild2DMipmaps(GL_TEXTURE_2D, 3, w,h,GL_BGR_EXT, GL_UNSIGNED_BYTE, dataTexture);
*/
//new code : working fine this way. I forgot to call glGenTextures and glBindTexture
bitmap->UnlockBits(bitmapData);
pin_ptr<GLuint*> pt = &texture;//pin managed pointer, to be unmanaged... a must here :)
glEnable(GL_TEXTURE_2D);
glGenTextures(1,*pt);
glBindTexture(GL_TEXTURE_2D,**pt);
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, w,h,GL_BGR_EXT, GL_UNSIGNED_BYTE, dataTexture);
}
And as the CBall:draw itself, I define this :
void CBall::draw(){
glLoadIdentity();
if(texture!=NULL && !filename->Equals(""))
{
glEnable(GL_TEXTURE_2D);
pin_ptr<GLuint*> pt = &texture;
glBindTexture(GL_TEXTURE_2D,**pt);
}
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glEnable(GL_NORMALIZE);
glTranslatef(this->x,this->y,this->z);
glRotatef(this->sudut_rotasi_x,1,0,0);
glRotatef(this->sudut_rotasi_y,0,1,0);
glRotatef(this->sudut_rotasi_z,0,0,1);
glScalef(this->x_scale,this->y_scale,this->z_scale);
GLUquadricObj *q = gluNewQuadric();
gluQuadricNormals(q, GL_SMOOTH);
gluQuadricTexture(q, GL_TRUE);
gluSphere(q, r, 32, 16);
glFlush();
glDisable(GL_TEXTURE_2D);
}
The problem is, when I draw two (or more) ball object, they all drawn using the same texture. I already debug the code, and for each object, they all have different texture
variable. Here is a snapshot of my code that draw those balls :
...
CBall ^ ball = gcnew CBall();
ball->x=Convert::ToSingle(r->GetAttribute("x"));
ball->y=Convert::ToSingle(r->GetAttribute("y"));
ball->z=Convert::ToSingle(r->GetAttribute("z"));
ball->r=Convert::ToSingle(r->GetAttribute("r"));
ball->filename=r->GetAttribute("filename");
ball->LoadTextureRaw();
addGraphic(id, ball);
...
Those code were called from a read XML file method.
What did I do wrong with this OpenGL Code?
Upvotes: 0
Views: 521
Reputation: 162327
Your problem is, that gluBuild2DMipmaps doesn't return the texture name, but a error code. You need to create a texture name separately.
Try this:
public ref class CDrawObject
{
protected:
GLuint texture; // just a GLuint, not a pointer!
public:
String ^ filename;
CDrawObject(void);
virtual void draw();
void LoadTextureRaw();
};
Change LoadTextureRaw a bit:
void CDrawObject::LoadTextureRaw()
{
if(!filename)
return;
if(filename->Equals(""))
return;
System::Drawing::Bitmap ^ bitmap = gcnew Bitmap(filename);
int h = bitmap->Height;
int w = bitmap->Width;
int s = w * h;
System::Drawing::Rectangle rect = System::Drawing::Rectangle(0,0,w,h);
System::Drawing::Imaging::BitmapData ^ bitmapData =
bitmap->LockBits( rect,
System::Drawing::Imaging::ImageLockMode::ReadWrite,
System::Drawing::Imaging::PixelFormat::Format24bppRgb );
// This is the important part: We generate a texture name and...
glGenTextures(1, &texture); // this should not require a pin_ptr, after all were in the middle of a member function of the class, so the garbage collector will not kick in.
// ...bind it, causing creation of a (yet uninitialized) texture object
glBindTexture(GL_TEXTURE_2D, texture);
GLint error = gluBuild2DMipmaps(
GL_TEXTURE_2D,
GL_RGB, // this should be a valid OpenGL token, not the number of components!
w, h,
GL_BGR_EXT, GL_UNSIGNED_BYTE,
bitmapData->Scan0.ToPointer() );
bitmap->UnlockBits(bitmapData);
}
Finally draw (which I rearranged a little)
void CBall::draw(){
glLoadIdentity();
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glEnable(GL_NORMALIZE);
glTranslatef(this->x,this->y,this->z);
glRotatef(this->sudut_rotasi_x,1,0,0);
glRotatef(this->sudut_rotasi_y,0,1,0);
glRotatef(this->sudut_rotasi_z,0,0,1);
glScalef(this->x_scale,this->y_scale,this->z_scale);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);
GLUquadricObj *q = gluNewQuadric();
gluQuadricNormals(q, GL_SMOOTH);
gluQuadricTexture(q, GL_TRUE);
gluSphere(q, r, 32, 16);
// glFlush is not required
glDisable(GL_TEXTURE_2D);
}
Upvotes: 4