Сбой при попытке визуализировать треугольную сетку (С++)

Я пытаюсь визуализировать треугольную сетку с затенением Фонга, используя GLSL, вот мой метод назначения нормалей.

void renderWireframe(Mesh *mesh) 
{
    glDepthMask(GL_TRUE);
    glBegin(GL_TRIANGLES);
    for(int i=0; i<mesh->nt; i++) { //nv is the mesh's number of triangles

    int i0 = mesh->triangles[i].vInds[0];
    int i1 = mesh->triangles[i].vInds[1];
    int i2 = mesh->triangles[i].vInds[2];

    //Calculate normals for each vertex
    Vector fv0 = getvertexnormal(mesh, i0);
    Vector fv1 = getvertexnormal(mesh, i1);
    Vector fv2 = getvertexnormal(mesh, i2);

    glNormal3dv((double *)&fv0);
    glVertex3dv((double *)&mesh->vertices[i0]);
    glNormal3dv((double *)&fv1);
    glVertex3dv((double *)&mesh->vertices[i1]);
    glNormal3dv((double *)&fv2);
    glVertex3dv((double *)&mesh->vertices[i2]);
    }
glEnd();
}

Код getvertexnormal выглядит следующим образом:

Vector getvertexnormal(Mesh *mesh, int vertex){
    int i = mesh->nt; //nt is the mesh's number of triangles
    int *adjface;
    adjface = new int[i]; //array to store adjacent faces

    //Store each triangle which has an intersection with the vertex'th vertex
    int nadjface = 0; 
    Triangle *t = mesh->triangles;
    for (int ix = 0; ix < mesh->nt; ix++){
        if(t[ix].vInds[0] == vertex){
            adjface[nadjface++] = ix;
        }
        else
            if (t[ix].vInds[1] == vertex)
                adjface[nadjface++] = ix;
            else
                if (t[ix].vInds[2] == vertex)
                    adjface[nadjface++] = ix;
    }

    // Average all adjacent triangles normals to get the vertex normal
    Vector norm = {0.0, 0.0, 0.0};
    for (int jx = 0; jx < nadjface; jx++){
        int ixFace = adjface[jx];
        norm.x += mesh->triangles[ixFace].vInds[0];
        norm.y += mesh->triangles[ixFace].vInds[1];
        norm.z += mesh->triangles[ixFace].vInds[2];
    }
    norm.x /= nadjface;
    norm.y /= nadjface;
    norm.z /= nadjface;
    return Normalize(norm);
}

Каждый раз, когда я запускаю это, похоже, что он начинает рендеринг, а затем через одну секунду он падает и дает мне исключение:

«Необработанное исключение по адресу 0x7562B727 в файле glutglsl.exe: исключение Microsoft C++: std::bad_alloc в ячейке памяти 0x0028F1C8».

Программа работает нормально, если я закомментирую части getvertexnomral() и вместо

glNormal3dv((double *)&fv0);
glVertex3dv((double *)&mesh->vertices[i0]);
glNormal3dv((double *)&fv1);
glVertex3dv((double *)&mesh->vertices[i1]);
glNormal3dv((double *)&fv2);
glVertex3dv((double *)&mesh->vertices[i2]);

Я пишу

glNormal3dv((double *)&Normalize(mesh->vertices[i0]));
glVertex3dv((double *)&mesh->vertices[i2]);
glNormal3dv((double *)&Normalize(mesh->vertices[i1]));
glVertex3dv((double *)&mesh->vertices[i1]);
glNormal3dv((double *)&Normalize(mesh->vertices[i2]));
glVertex3dv((double *)&mesh->vertices[i2]); 

но тогда это выглядит неправильно (http://imgur.com/lxSUMAq)

поэтому я думаю, что есть проблема с getvertexnormal().

Я, кстати, в этом деле полный новичок. У меня есть все мои вычисления фонга в моем фрагментном шейдере (GLSL). Чтобы добиться затенения Фонга на большой треугольной сетке, это правильный путь?


person user2527567    schedule 27.06.2013    source источник
comment
std::bad_alloc означает, что у вас закончилась память. каково значение mesh->nt ?   -  person Elazar    schedule 27.06.2013
comment
Значение mesh-›nt равно 5660.   -  person user2527567    schedule 27.06.2013


Ответы (1)


Ваша проблема - утечка памяти.

Вы выделяете память

adjface = new int[i];

Но вы никогда не удаляете его. Значение, возвращаемое из new, хранится в локальной переменной и никогда никуда не копируется и не возвращается из функции. Итак, у вас есть утечка памяти, которая приводит к исчерпанию памяти и ошибке распределения - поэтому new выдает std::bad_alloc.

Это С++. Не используйте массивы; вместо этого используйте std::vector. Или delete[] его.


Но я думаю, что вам действительно не нужен массив здесь:

Vector getvertexnormal(Mesh *mesh, int vertex) {
    int nadjface = 0; 
    Triangle *t = mesh->triangles;
    Triangle *last = t + (mesh->nt - 1);
    Vector norm = {0.0, 0.0, 0.0};
    for (; t <= last; t++) {
        for (int i = 0; i < 3; i++) {
            if (t->vInds[i] == vertex) {
                nadjface++;
                norm.x += t->vInds[0];
                norm.y += t->vInds[1];
                norm.z += t->vInds[2];
                break;
            }
        }
    }
    return Normalize(norm / nadjface);
}

И если я не ошибаюсь, вы можете просто сделать

norm += t->vInds;

или делать что-то в этом роде. Это может сделать ваш код короче, читабельнее и, возможно, даже быстрее.

person Elazar    schedule 27.06.2013
comment
Большое спасибо, я давно пользуюсь С# и довольно плохо знаком с С++, так что, вероятно, причина в этом. - person user2527567; 27.06.2013
comment
ХОРОШО. Итак: используйте new с осторожностью. - person Elazar; 27.06.2013