Я разрабатываю 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
Я так растерялся.
Кто-нибудь знает, что вызывает это? И если да, то как это решить?