奇怪的访问冲突读取错误 / glDrawArrays用法

3

我不确定这个问题应该放在这里还是图形编程中......我遇到了一个非常烦人的访问冲突读取错误,而且我无法找出原因。我正在尝试重构一个关键帧函数(计算两个顶点位置之间的中间位置)。这个函数可以编译并正常工作。

glBegin(GL_TRIANGLES);
    for(int i = 0; i < numTriangles; i++) {
        MD2Triangle* triangle = triangles + i;
        for(int j = 0; j < 3; j++) {
            MD2Vertex* v1 = frame1->vertices + triangle->vertices[j];
            MD2Vertex* v2 = frame2->vertices + triangle->vertices[j];
            Vec3f pos = v1->pos * (1 - frac) + v2->pos * frac;
            Vec3f normal = v1->normal * (1 - frac) + v2->normal * frac;
            if (normal[0] == 0 && normal[1] == 0 && normal[2] == 0) {
                normal = Vec3f(0, 0, 1);
            }
            glNormal3f(normal[0], normal[1], normal[2]);

            MD2TexCoord* texCoord = texCoords + triangle->texCoords[j];
            glTexCoord2f(texCoord->texCoordX, texCoord->texCoordY);
            glVertex3f(pos[0], pos[1], pos[2]);
        }
    }
glEnd();

这里的函数计算位置并进行绘制。我想要做的是预先计算所有位置,将它们存储在Vertex数组中,然后绘制它们。 如果我尝试删除它,并在程序完全相同的部分用以下代码块替换它:

int vCount = 0;
    for(int i = 0; i < numTriangles; i++) {
        MD2Triangle* triangle = triangles + i;
        for(int j = 0; j < 3; j++) {
            MD2Vertex* v1 = frame1->vertices + triangle->vertices[j];
            MD2Vertex* v2 = frame2->vertices + triangle->vertices[j];
            Vec3f pos = v1->pos * (1 - frac) + v2->pos * frac;
            Vec3f normal = v1->normal * (1 - frac) + v2->normal * frac;
            if (normal[0] == 0 && normal[1] == 0 && normal[2] == 0) {
                normal = Vec3f(0, 0, 1);
            }

            indices[vCount] = normal[0];
            vCount++;
            indices[vCount] = normal[1];
            vCount++;
            indices[vCount] = normal[2];
            vCount++;

            MD2TexCoord* texCoord = texCoords + triangle->texCoords[j];
            indices[vCount] = texCoord->texCoordX;
            vCount++;
            indices[vCount] = texCoord->texCoordY;
            vCount++;

            indices[vCount] = pos[0];
            vCount++;
            indices[vCount] = pos[1];
            vCount++;
            indices[vCount] = pos[2];
            vCount++;
        }

    }

我在第7行遇到了访问冲突错误,错误信息为“Unhandled exception at 0x01455626 in Graphics_template_1.exe: 0xC0000005: Access violation reading location 0xed5243c0”。

Vec3f pos = v1->pos * (1 - frac) + v2->pos * frac;

在调试器中,两个 V 似乎没有任何值... 直到这一点,该函数的行为与上面的函数完全相同,我不明白为什么会出现这种情况?
编辑------------------------------------------------------------------------------------
感谢 Werner 发现问题是数组初始化!根据您的建议,我使用 std:vector 容器重构了函数,并使用 glDrawArrays 而不是立即模式进行绘图... 但是,性能并没有得到改善,帧率比以前低很多!我是否正确/有效地使用了此函数?这是重构后的绘制函数:
    for(int i = 0; i < numTriangles; i++) {
        MD2Triangle* triangle = triangles + i;
        for(int j = 0; j < 3; j++) {
            MD2Vertex* v1 = frame1->vertices + triangle->vertices[j];
            MD2Vertex* v2 = frame2->vertices + triangle->vertices[j];
            Vec3f pos = v1->pos * (1 - frac) + v2->pos * frac;
            Vec3f normal = v1->normal * (1 - frac) + v2->normal * frac;
            if (normal[0] == 0 && normal[1] == 0 && normal[2] == 0) {
                normal = Vec3f(0, 0, 1);
            }


            normals.push_back(normal[0]);
            normals.push_back(normal[1]);
            normals.push_back(normal[2]);

            MD2TexCoord* texCoord = texCoords + triangle->texCoords[j];
            textCoords.push_back(texCoord->texCoordX);
            textCoords.push_back(texCoord->texCoordY);

            vertices.push_back(pos[0]);
            vertices.push_back(pos[1]);
            vertices.push_back(pos[2]);
        }

    }


    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glEnableClientState(GL_VERTEX_ARRAY);

    glNormalPointer(GL_FLOAT, 0, &normals[0]);
    glTexCoordPointer(2, GL_FLOAT, 0, &textCoords[0]); 
    glVertexPointer(3, GL_FLOAT, 0, &vertices[0]);



    glDrawArrays(GL_TRIANGLES, 0, vertices.size()/3);


    glDisableClientState(GL_VERTEX_ARRAY);  // disable vertex arrays
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);

    vertices.clear();
    textCoords.clear();
    normals.clear();

我这里做了额外的操作吗?因为这个方法应该比glBegin()/End()更高效,是这样吗?

谢谢你的时间和帮助!


2
由于我们看不到任何自包含的示例,我们只能猜测,这导致 MD2Vertex* v1 = frame1->vertices + triangle->vertices[j]; 可能(或v2)导致错误指针。由于我们看不到这行中使用的值是如何产生的,所以我们无法猜测太多,只能说可能有些未初始化。 - PlasmaHH
1
你是否尝试使用所有警告和调试信息启用的方式编译你的代码(在Linux上,这意味着g++ -Wall -g),并且使用调试器(在Linux上,可以使用gdb调试器,或者可能还有ddd作为其前端)来调试你的程序? - Basile Starynkevitch
@LiMuBei 这是无稽之谈。glBegin和glEnd用于界定定义基元或一组类似基元的顶点。 - BЈовић
endFramestartFrame中有哪些值? - BЈовић
1
当您不写入索引时,它是否会崩溃?您是否检查过没有超出索引的范围(覆盖其他数据结构)? - Werner Henze
显示剩余7条评论
1个回答

1

好的,让我们把它变成一个答案。猜想是:

如果不写入索引时是否会崩溃?您是否检查过您没有超出索引末尾(覆盖其他数据结构)?

您的回复是,您创建了一个数组 GLfloat indices[],因为您不知道数组大小。

最佳(性能)解决方案将是预先计算数组大小并适当地创建数组。

GLfloat *indices = new GLfloat[calculated_number_of_elements];
...use array...;
delete [] indices;

更好的方法是创建一个std::vector:
std::vector<GLfloat> indices(calculated_number_of_elements);

向量还有一个优点,就是可以动态地调整其大小。


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