在OSX上使用OpenGL和SDL - 在glDrawElements()中出现EXC_BAD_ACCESS错误 - 在GLUT上工作,但不适用于SDL。

3
我写了一个简单的使用GLUT的应用程序,现在将其改为SDL以制作游戏。但是我在使用glDrawElements和顶点缓冲区对象(VBO)时遇到了问题,只有在不使用VBO时程序才能正常运行,一旦使用VBO就会出现“EXC_BAD_ACCESS”错误。更加诡异的是,在GLUT中程序可以完全正常运行。可能是我的初始化过程中漏掉了某些东西导致的。以下是绘制代码:
if (glewGetExtension("GL_ARB_vertex_buffer_object"))
{
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);        

    //Load vertices
    glBindBuffer(GL_ARRAY_BUFFER, this->mesh->vbo_vertices);
    glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0));

    //Load normals
    glBindBuffer(GL_ARRAY_BUFFER, this->mesh->vbo_normals);
    glNormalPointer(GL_FLOAT, 0, BUFFER_OFFSET(0));

    //Load UVs
    glBindBuffer(GL_ARRAY_BUFFER, this->mesh->vbo_uvs);
    glTexCoordPointer(2, GL_FLOAT, 0, BUFFER_OFFSET(0));

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->mesh->vbo_index);
    App dies here -----> glDrawElements(GL_TRIANGLES, 3*this->mesh->numFaces, GL_UNSIGNED_INT, BUFFER_OFFSET(0));

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);

} else {

    //BTW: If I run this block of code instead of the above, everything renders fine. App doesn't die. 

    //Drawing with vertex arrays
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    glVertexPointer(3, GL_FLOAT, 0, this->mesh->vertexArray);
    glNormalPointer(GL_FLOAT, 0, this->mesh->normalsArray);
    glTexCoordPointer(2, GL_FLOAT, 0, this->mesh->uvArray);

    glDrawElements(GL_TRIANGLES, 3*this->mesh->numFaces, GL_UNSIGNED_INT, this->mesh->indexArray);

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}

以下是调试信息:

Program received signal:  “EXC_BAD_ACCESS”.

Thread-1-<com.apple.main-thread>
#0  0x17747a93 in gleRunVertexSubmitImmediate
#1  0x1774772c in gleLLVMArrayFunc
#2  0x177476e4 in gleSetVertexArrayFunc
#3  0x1773073c in gleDrawArraysOrElements_ExecCore
#4  0x176baa7b in glDrawElements_Exec
#5  0x97524050 in glDrawElements

asm gleRunVertexSubmitImmediate

0x17747a93  <+0771>  mov    (%eax,%ecx,4),%eax      <-- the app dies on this.

这是我的SDL初始化代码:
//Initialize SDL
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
    cout << "Could not initialize SDL" << endl << SDL_GetError();
    exit(2);
}

//Set window
SDL_WM_SetCaption("Hello World!", "Hello World!");

//Set openGL window
if ( SDL_SetVideoMode(width, height, 32, SDL_OPENGL | SDL_RESIZABLE) == NULL ) {
    cout << "Unable to create OpenGL context: %s\n" << endl << SDL_GetError();
    SDL_Quit();
    exit(2);
}

//Set up event handling
SDL_Event event;
bool quit = false;

//Initialize GLEW
GLenum err = glewInit();
if (GLEW_OK != err)
{
    //Problem: glewInit failed, something is seriously wrong. 
    fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
    exit(1);
}
fprintf(stdout, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));

你把VBO ID分配在哪里了(我猜是在this->mesh->vbo_vertices等地方)? - genpfault
是的,分配似乎没问题,正如我所提到的,在使用GLUT时可以工作。只有在SDL下才会出现错误。 - Leonard Teo
2个回答

1
如果在你的模型(obj)文件中没有vn,那么你应该将以下行注释掉:
//glEnableClientState(GL_NORMAL_ARRAY);
//glDisableClientState(GL_NORMAL_ARRAY);

那个对我有效。


1

我认为你的代码没有问题。

当出现“EXC_BAD_ACCESS”时,通常是因为试图访问未分配或已释放的对象。

你可以通过启用“NSZombieEnabled”环境变量来获取有关相关对象的更详细的调试信息。这篇博客文章简要介绍了如何启用此环境变量(我不是作者)。

这样做有望在调试控制台中获取更多有关崩溃原因的信息。


我已经启用了僵尸模式,但不幸的是它并没有实际改变我的调试输出。 - Leonard Teo
在使用缓冲区和绘制调用之前,我会先打印出网格的属性,例如mesh->vbo_vertices、mesh->numFaces等。 - Error 454

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接