access violatoin when my program has two different QGLWidgets

90 views Asked by At

I have two different QGLWidgets(GLViwer and TextureViwer),and I add them into two QHboxLayout

glviewer = GLViewer::getInstance(); //QGLWidget singleton, display 3d model
texViewer = TextureViewer::getInstance();//display selected texture
ui.modelViewer->addWidget(glviewer); //add it to QHboxLayout
ui.textureViewer->addWidget(texViewer);

I render model with glDrawArrays() because it is fast.I have no problems when I only have GLViewer to display 3d model. but when I have two QGLWidget. it will cause a problem.

access violation reading location 0x00000000...

I try to render model step by step(draw a triangle and another...), it works but without texture even though I call glTexCoord2f().

I have no idea why it happens. help me please:)

following is my init data code

glGenBuffers(3, this->buffers);

glBindBuffer(GL_ARRAY_BUFFER, this->buffers[VERTEXBUFFER]);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*9*objInfo->faces.size(), this->vertexs, GL_STATIC_DRAW);
glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0));

glBindBuffer(GL_ARRAY_BUFFER, this->buffers[NORMALBUFFER]);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*9*objInfo->faces.size(), this->normals, GL_STATIC_DRAW);
glNormalPointer(GL_FLOAT, 0, BUFFER_OFFSET(0));

glBindBuffer(GL_ARRAY_BUFFER, this->buffers[TEXCOORDBUFFER]);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*objInfo->faces.size(), this->texCoord, GL_STATIC_DRAW);
glTexCoordPointer(2, GL_FLOAT, 0, BUFFER_OFFSET(0));

BUFFER_OFFSET(0) just like red book

#define BUFFER_OFFSET(bytes) ((GLubytes*) NULL+(bytes))

GLViewer.h

class GLViewer : public QGLWidget
{
    Q_OBJECT
public:
    ~GLViewer();
    GLViewer(QWidget *parent = 0);
    void drawModelWithTexArrayBuffer();
protected:
    void initializeGL();
    void paintGL();
    void resizeGL(int w, int h);
};

GLViewer.cpp

void GLViewer::initializeGL()
{
glewInit();
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 
glEnable(GL_CULL_FACE); 
glEnable(GL_DEPTH_TEST);
glCullFace(GL_BACK); 
glFrontFace(GL_CCW);
glShadeModel(GL_SMOOTH);
}

void GLViewer::paintGL()
{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

if (isLoaded)
{
    timeCount.start();
    glLoadIdentity();

    glTranslated(modelCenter[0]+offsetX-(maxX+minX)/2,modelCenter[1]+ offsetY-(maxY+minY)/2 ,modelCenter[2]+zoomRate+minZ-3*(maxZ - minZ));
    glMultMatrixf(this->arcBall->Transform.M);
    glTranslated(-modelCenter[0], -modelCenter[1], -modelCenter[2]);
    if (this->modelWithtTex)
    {
        setLight(this->lightOn);
        if (showMesh)
        {
            drawModelLineArrayBuffer();
        }
        else
        {
            drawModelWithTexArrayBuffer();
            //drawModelWithTex();
        }
    }
    else
    {
        drawModelWithoutTexArrayBuffer();
    }
    int elapseTime = timeCount.elapsed();
}
} 

void GLViewer::resizeGL( int w, int h )
{
if (h == 0)
{
    h = 1;
}

    this->curWidth = w;
    this->curHeight = h;
    glViewport(0, 0, (GLsizei) w, (GLsizei) h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1, 2000.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    this->arcBall->setBounds((GLfloat)w, (GLfloat)h);
}
void GLViewer::drawModelWithTexArrayBuffer()
{
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    glEnable(GL_TEXTURE_2D);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    for (int i = 0 ; i < objInfo->tex_filenames.size(); i++)
    {
        if (indRange[i].length == 0)
            continue;
        else
        {
            glBindTexture(GL_TEXTURE_2D, texName[indRange[i].texId]);
            glDrawArrays(GL_TRIANGLES, indRange[i].start, indRange[i].length);
        }
    }
    glDisable(GL_TEXTURE_2D);
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY); 
}   

TextureViewer.h

class TextureViewer : public QGLWidget
{
Q_OBJECT

public:

~TextureViewer();
TextureViewer(QWidget *parent = 0);
protected:
    void initializeGL();
    void paintGL();
    void resizeGL(int w, int h);
};

TextureViewer.cpp

void TextureViewer::initializeGL()
{
std::cout << "ddd" << std::endl;
glewInit();
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 
glEnable(GL_CULL_FACE); 
glEnable(GL_DEPTH_TEST);
glCullFace(GL_BACK); 
glFrontFace(GL_CCW);
glShadeModel(GL_SMOOTH);
}

void TextureViewer::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslated(0, 0, -1);
glColor4f(1, 0, 1, 1);
glRectd(0,0,1,1);
}

void TextureViewer::resizeGL( int w, int h )
{
if (h == 0)
{
    h = 1;
}
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1, 2000.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

}
1

There are 1 answers

4
datenwolf On

Each QGLWidget has its own OpenGL context and hence state, even if you create them as shared context, things like Vertex Array pointer locations are not covered by this sharing. Hence you must make the proper gl…Pointer calls just before calling glDrawElements or glDrawArrays. You don't do that properly.