Элемент вектора C ++ отличается при обращении в разное время - PullRequest
1 голос
/ 14 июля 2009

Я разрабатываю 3D-игру с использованием SDL и OpenGL на Ubuntu 9.04 с использованием Eclipse CDT. У меня есть класс для хранения данных меша в векторах для каждого типа. Такие как Vertex, Normal, UVcoord (координаты текстуры), а также вектор граней. Каждое лицо имеет 3 вектора типа int, которые содержат индексы для других данных. До сих пор моя игра работала довольно хорошо при рендеринге с хорошими показателями. Но опять же, у меня было всего менее ста вершин среди двух объектов для целей тестирования.

Цикл доступа к этим данным выглядит следующим образом:

void RenderFace(oFace face)
{
    /*
    * More Stuff
    */

    oVertice gvert;
    oUVcoord tvert;
    oNormal nvert;

    for (unsigned int fvIndex = 0; fvIndex < face.GeoVerts.size(); fvIndex++)
    {
        gvert = obj.TheMesh.GetVertice(face.GeoVerts[fvIndex] - 1);
        tvert = obj.TheMesh.GetUVcoord(face.UV_Verts[fvIndex] - 1);
        nvert = obj.TheMesh.GetNormal(face.NrmVerts[fvIndex] - 1);

        glNormal3f(nvert.X, nvert.Y, nvert.Z);
        glTexCoord2f(tvert.U, tvert.V);
        glVertex3f(scale * gvert.X, scale * gvert.Y, scale * gvert.Z);
    }

    /*
    *  More Stuff
    */
} 

Существует цикл, который вызывает функцию renderFace(), которая включает в себя вышеуказанный цикл for. Минус один, потому что файлы Wavefront .obj индексируются 1 (вместо индекса c ++ 0). Как бы то ни было, я обнаружил, что если у вас около 30 тысяч или около того лиц, все эти вызовы на glVertex3f() и т.п. замедляют игру до 10 FPS. Это я не могу допустить. Итак, я узнал о массивах вершин, которые требуют указателей на массивы. Следуя примеру учебника NeHe, я продолжал использовать свой класс oVertice и другие. У которых просто есть floats x, y, z или u, v. Поэтому я добавил ту же самую функцию выше к моей OnLoad() функции для построения массивов, которые просто "oVertice*" и похожи.

Вот код:

bool oEntity::OnLoad(std::string FileName)
{
    if (!obj.OnLoad(FileName))
    {
        return false;
    }

    unsigned int flsize = obj.TheMesh.GetFaceListSize();

    obj.TheMesh.VertListPointer = new oVertice[flsize];
    obj.TheMesh.UVlistPointer = new oUVcoord[flsize];
    obj.TheMesh.NormListPointer = new oNormal[flsize];

    oFace face = obj.TheMesh.GetFace(0);
    oVertice gvert;
    oUVcoord tvert;
    oNormal nvert;
    unsigned int counter = 0;
    unsigned int temp = 0;

    for (unsigned int flIndex = 0; flIndex < obj.TheMesh.GetFaceListSize(); flIndex++)
    {
        face = obj.TheMesh.GetFace(flIndex);

        for (unsigned int fvIndex = 0; fvIndex < face.GeoVerts.size(); fvIndex++)
        {
            temp = face.GeoVerts[fvIndex];
            gvert = obj.TheMesh.GetVertice(face.GeoVerts[fvIndex] - 1);

            temp = face.UV_Verts[fvIndex];
            tvert = obj.TheMesh.GetUVcoord(face.UV_Verts[fvIndex] - 1);

            temp = face.NrmVerts[fvIndex];
            nvert = obj.TheMesh.GetNormal(face.NrmVerts[fvIndex] - 1);

            obj.TheMesh.VertListPointer[counter].X = gvert.X;
            obj.TheMesh.VertListPointer[counter].Y = gvert.Y;
            obj.TheMesh.VertListPointer[counter].Z = gvert.Z;

            obj.TheMesh.UVlistPointer[counter].U = tvert.U;
            obj.TheMesh.UVlistPointer[counter].V = tvert.V;

            obj.TheMesh.NormListPointer[counter].X = nvert.X;
            obj.TheMesh.NormListPointer[counter].Y = nvert.Y;
            obj.TheMesh.NormListPointer[counter].Z = nvert.Z;

            counter++;
        }
    }

    return true;
}

Переменная unsigned int temp предназначена для целей отладки. Очевидно, у меня нет конструктора по умолчанию для oFace, у которого нет чего-то для инициализации. В любом случае, как вы можете видеть, это почти та же самая рутина. Только вместо вызова функции gl я добавляю данные в три массива.

Вот кикер:

Я загружаю типичный куб из треугольников.

Когда я получаю доступ к элементу 16 (индексированному 0) вектора UV_Verts из функции RenderFace(), я получаю 12.

Но когда я получаю доступ к элементу 16 (проиндексированному 0) того же UV_Verts вектора из функции OnLoad(), я получаю что-то вроде 3045472189

Я так растерялся.

Кто-нибудь знает, что вызывает это? И если да, то как это решить?

1 Ответ

3 голосов
/ 14 июля 2009

Одной из возможных причин может быть создание массивов размером flsize:

obj.TheMesh.VertListPointer = new oVertice[flsize];
obj.TheMesh.UVlistPointer = new oUVcoord[flsize];
obj.TheMesh.NormListPointer = new oNormal[flsize];

но используйте массивы с индексами до flsize * face.GeoVerts.size

for (...; flIndex < obj.TheMesh.GetFaceListSize(); ...) { // flsize = GetFaceListSize
  for (...; fvIndex < face.GeoVerts.size(); ...) {
    ...
    obj.TheMesh.UVlistPointer[counter].U = ...;
    ...
    counter++;
  }
}

так что ваш код создания массива должен быть больше похож на

obj.TheMesh.VertListPointer = new oVertice[flsize * face.GeoVerts.size()];
obj.TheMesh.UVlistPointer = new oUVcoord[flsize * face.GeoVerts.size()];
obj.TheMesh.NormListPointer = new oNormal[flsize * face.GeoVerts.size()];
...