Для таких простых объектов я бы сделал один большой VBO, скажем, 200 Objects * NrVerticesPerCube, поместил бы все данные с чередованием Vertex, Normal, UV, Vertex, Normal, UV и т. Д.
Я делаю нечто подобное в анимации ключевых кадров бобра в моей игре, я начинаю с чего-то вроде этого:
glGenBuffers(1, &vboObjects[vboGroupBeaver]);
glBindBuffer(GL_ARRAY_BUFFER, vboObjects[vboGroupBeaver]);
glBufferData(GL_ARRAY_BUFFER, beaverVerts*8*sizeof(GLfloat), 0, GL_STATIC_DRAW);
vbo_buffer = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
NSString *path;
path = [[NSBundle mainBundle] pathForResource:@"beaver01" ofType:@"bin"];
NSFileHandle *model = [NSFileHandle fileHandleForReadingAtPath:path];
float vertice[8];
int counter = 0;
while (read([model fileDescriptor], &vertice, 8*sizeof(float))) {
memcpy(vbo_buffer, vertice, 8*sizeof(GLfloat)); // 0
vbo_buffer += 8*sizeof(GLfloat);
counter++;
}
glUnmapBufferOES(GL_ARRAY_BUFFER);
glBindBuffer(GL_ARRAY_BUFFER, 0);
Это создает мой буфер VBO с правильным размером (в данном случае 8 * sizeof (GLfloat) с 3 вертами, 3 нормалями и 2UV) и копирует первый ключевой кадр в буфер, вы можете сделать то же самое с исходным положение объекта, или просто оставьте это и вычислите последнее ...
Затем в каждом кадре я делаю интерполяцию между 2 ключевыми кадрами для каждой вершины моего бобра и просто выполняю один вызов отрисовки, это очень быстро для 4029 вершин, которые есть у моего бобра, и работает на скорости 60FPS на моем iPhone 3G.
Для вас, выполняющих только gltranslations, было бы еще проще, просто добавьте значения x, y, z к каждой вершине каждого куба.
Вы бы обновили его так:
glBindBuffer(GL_ARRAY_BUFFER, vboObjects[vboGroupBeaver]);
GLvoid* vbo_buffer = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
Свяжите буфер vbo и mapit с буфером var.
Рассчитайте, что вы хотите на временную переменную.
memcpy(vbo_buffer, currentVert, 6*sizeof(GLfloat)); // 0
vbo_buffer += 8*sizeof(GLfloat);
Скопируйте его и обновите буфер до следующего объекта, повторяйте, пока все объекты не обновятся ...
Вы также можете сделать все обновления в отдельном массиве и скопировать весь массив, но тогда вы будете копировать дополнительную информацию, которая обычно не меняется (нормали и УФ). Или вы не можете использовать чередующиеся данные и копировать это ...
glUnmapBufferOES(GL_ARRAY_BUFFER);
Отмена отображения буфера VBO
glVertexPointer(3, GL_FLOAT, 8*sizeof(GLfloat), (GLvoid*)((char*)NULL));
glNormalPointer(GL_FLOAT, 8*sizeof(GLfloat), (GLvoid*)((char*)NULL+3*sizeof(GLfloat)));
glTexCoordPointer(2, GL_FLOAT,8*sizeof(GLfloat), (GLvoid*)((char*)NULL+6*sizeof(GLfloat)));
glDrawArrays(GL_TRIANGLES, 0, beaverVerts);
Настройте свой вызов на отрисовку и нарисуйте все это ...
Если вам нужно вращать объекты, а не просто переводить их, вам нужно будет добавить некоторые умножения матриц по пути ...
РЕДАКТИРОВАТЬ **
хорошо, сделать gltranste вручную очень просто (вращение и т. Д. Немного сложнее).
Я использую чередующуюся плоскость, нарисованную с использованием TRIANGLE_STRIP вместо треугольников, но принцип тот же.
float beltInter[] = {
0.0, 0.0, 0.0, // vertices[0]
0.0, 0.0, 1.0, // Normals [0]
6.0, 1.0, // UV [0]
0.0, 480, 0.0, // vertices[1]
0.0, 0.0, 1.0, // Normals [1]
0.0, 1.0, // UV [1]
320.0, 0.0, 0.0, // vertices[2]
0.0, 0.0, 1.0, // Normals [2]
6.0, 0.0, // UV [2]
320.0, 480, 0.0, // vertices[3]
0.0, 0.0, 1.0, // Normals [3]
0.0, 0.0 // UV [3]
};
Так что это чередующаяся вершина, у вас есть вершина, затем нормаль, затем UV, если вы не используете текстуры, замените UV цветом.
Самый простой способ - иметь массив со всеми объектами внутри (это легко сделать, если все ваши объекты имеют одинаковый размер) и выполнять обновление положения после рисования (вместо в середине фрейма opengl), лучше сделать отдельный поток, создайте 2 VBO, обновите одно из них, одновременно рисуя из другого, что-то вроде этого:
- Тема 1 OpenGL DrawFrom VBO0
- Поток 2 Обновления игры, обновите позиции во внутреннем массиве и скопируйте в VBO1, установите Var, сказав VBO1 да готово (поэтому поток 1 изменяется только с рисования на VBO1, когда все обновления сделаны).
- Тема 1 OpenGL DrawFrom VBO1
- Тема 2 Обновление игры, тоже самое, но обновление VBO0
- продолжить с той же логикой
это называется двойной буферизацией, и вы используете ее для обеспечения стабильности, без этого иногда ваша игровая логика будет обновлять VBO, в то время как видеокарте это нужно, и графической карте придется ждать, что приведет к снижению FPS.
В любом случае, вернемся к теме
чтобы сделать эквивалент gltranslatef (10,20,30), просто сделайте:
int maxvertices = 4;
float x = 10;
float y = 20;
float z = 30;
int counter = 0;
int stride = 8; // stride is 8 = 3 x vertice + 3 x normal + 2 x UV change to 3 x color or 4 x color depending on your needs
glBindBuffer(GL_ARRAY_BUFFER, vboObjects[myObjects]);
GLvoid* vbo_buffer = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
while (counter < (maxVertices*8)) {
beltInter[counter] += x; // just sum the corresponding values to each
beltInter[counter+1] += y;
beltInter[counter+2] += z;
memcpy(vbo_buffer, currentVert, 3*sizeof(GLfloat)); // again only copy what you need, in this case only copying the vertices, if your're updating all the data, you can just do a single memcpy at the end instead of these partial ones
vbo_buffer += stride*sizeof(GLfloat); // forward the buffer
counter += stride; // only update the vertex, but you could update everything
}
glUnmapBufferOES(GL_ARRAY_BUFFER);
glVertexPointer(3, GL_FLOAT, stride*sizeof(GLfloat), (GLvoid*)((char*)NULL));
glNormalPointer(GL_FLOAT, stride*sizeof(GLfloat), (GLvoid*)((char*)NULL+3*sizeof(GLfloat)));
glTexCoordPointer(2, GL_FLOAT,stride*sizeof(GLfloat), (GLvoid*)((char*)NULL+6*sizeof(GLfloat)));
glDrawArrays(GL_TRIANGLE_STRIP, 0, maxVertices);
Конечно, значения обновления не обязательно должны быть одинаковыми для всех объектов, например, используя базовый массив, вы можете обновлять всю информацию по мере продвижения и просто иметь подпрограмму для копирования ее в VBO при необходимости. .
Все это было написано по памяти на лету, так что, возможно, драконы: -)
Надеюсь, это поможет.