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();
}
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 callingglDrawElements
orglDrawArrays
. You don't do that properly.