Ошибка чтения нечетного нарушения доступа / использование glDrawArrays - PullRequest
3 голосов
/ 23 ноября 2011

Я не уверен, принадлежит ли это здесь или в графическом программировании ..... Я получаю действительно досадную ошибку чтения нарушения доступа, и я не могу понять, почему. То, что я пытаюсь сделать, это реорганизовать функцию ключевых кадров (вычислить среднее положение между двумя положениями вершин). Эта функция компилируется и отлично работает

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

    }

Я получаю ошибку нарушения доступа «Необработанное исключение в 0x01455626 в Graphics_template_1.exe: 0xC0000005: Место чтения нарушения доступа 0xed5243c0», указывающее на строку 7

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

где два V, кажется, не имеют значения в отладчике .... До этого момента функция ведет себя точно так же, как и выше, я не понимаю, почему это происходит?

РЕДАКТИРОВАТЬ ---------------------------------------------- --------------------------------------

Спасибо, Вернер, за то, что обнаружили, что проблема заключалась в инициализации массива! Согласно вашему совету, я реорганизовал функцию, используя контейнеры 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 (), верно?

Спасибо за ваше время и помощь!

1 Ответ

1 голос
/ 23 ноября 2011

ОК, давайте сделаем ответ.Предположение было:

Сбои, если вы не пишете в индексы?Вы проверяли, что не пишете после конца индексов (перезаписываете другие структуры данных)?

Ваш ответ был, что вы создали массив индексов GLfloat [], поскольку вы не знаете массивsize заранее.

Лучшим (эффективным) решением было бы заранее рассчитать размер массива и создать массив произвольно.

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

Еще лучше, если вы можете создать std :: vector:

std::vector<GLfloat> indices(calculated_number_of_elements);

Преимущество вектора также заключается в том, что его можно динамически изменять.

...