Почему мой объект OpenGL отображается с такой же текстурой? - PullRequest
0 голосов
/ 02 мая 2011

ОБНОВЛЕНИЕ : С помощью @datenwolf я знаю, что возвращаемое значение gluBuild2DMipmaps - это не указатель на текстуру, а всего лишь код ошибки. Я забыл вызвать glGenTextures и glBindTexture. Посмотрите в методе LoadTextureRaw в этом ответе

У меня проблема при рендеринге нескольких объектов, каждый из которых имеет свое определение файла текстуры, то есть все они рисуют одну и ту же текстуру. Я создаю иерархию классов, CDrawObject->CBall. В CDrawObject я определяю это:

public ref class CDrawObject
{
protected:
BYTE * dataTexture;
GLuint * texture;

public:
String ^ filename;  
CDrawObject(void);
virtual void draw();
void LoadTextureRaw();
};

В LoadTextureDraw () я определяю это:

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);

}

И как CBall: нарисовать сам, я определяю это:

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);
 }

Проблема в том, что когда я рисую два (или более) объекта шара, все они нарисованы с использованием одной и той же текстуры. Я уже отлаживал код, и для каждого объекта все они имеют разные texture переменные. Вот снимок моего кода, который рисует эти шары:

    ...
    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);
    ...

Этот код был вызван из метода чтения XML-файла.

Что я сделал не так с этим кодом OpenGL?

1 Ответ

4 голосов
/ 02 мая 2011

Ваша проблема в том, что gluBuild2DMipmaps возвращает не имя текстуры, а код ошибки.Вам нужно создать имя текстуры отдельно.

Попробуйте это:

public ref class CDrawObject
{
protected:
    GLuint texture; // just a GLuint, not a pointer!

public:
    String ^ filename;  
    CDrawObject(void);
    virtual void draw();
    void LoadTextureRaw();
};

Немного измените LoadTextureRaw:

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); 
}

Наконец, рисуйте (что я немного переставил)

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);

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...