Ответ 1
То, что вы делаете, выглядит правильно, за исключением sizeof (vertices) дает размер адреса, а не размер массива. Таким образом, когда вы вызываете glBufferData, вы выделяете 8 байтов, и когда вы вызываете glBufferSubData, вы заполняете эти 8 байтов с помощью первых четырех байтов массива вершин, а затем первых четырех байтов массива нормалей. Затем, когда вы переходите на вызов glDrawArrays, первый индекс вызывает исключение индекса массива из пределов (следовательно, EXC_BAD_ACCESS).
// Data
GLuint geometry_array = 0;
GLuint indice_array = 0;
GLfloat *geometry;
GLuint *indices;
Вы можете сделать эту инициализацию по-разному, но я перемещаю все свои данные в 32 байта на массив вершин. Любой способ, которым вы хотите настроить свой массив, работает до тех пор, пока вы правильно используете glVertexPointer, glNormalPointer и glTexCoordPointer.
// Initialize
geometry = new GLfloat[8*num_geometry];
indices = new GLuint[num_indices];
/* Fill geometry: 0, 1, 2 = vertex_xyz
* 3, 4, 5 = normal_xyz
* 6, 7 = tex_coord_uv
*/
glGenBuffers(1, &geometry_array);
glBindBuffer(GL_ARRAY_BUFFER, geometry_array);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*8*num_geometry, NULL, GL_DYNAMIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLfloat)*8*num_geometry, geometry);
glGenBuffers(1, &indice_array);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indice_array);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*num_indices, NULL, GL_STATIC_DRAW);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(GLuint)*num_indices, indices);
Функция рендеринга - пять шагов. Во-первых, привяжите буферы так, чтобы OpenGL знал, где найти данные геометрии и индексов. Во-вторых, Включите различные состояния клиента для каждого типа данных. Если вы оставите один из них, этот тип данных не будет отображаться, и если оставить их все, весь ваш объект не будет отображаться. В-третьих, вы должны указать OpenGL, где каждый тип данных содержится в вашем массиве. В этом случае данные геометрии 32 байта начинаются с 12 байтов данных вершин, поэтому начальное смещение должно быть нулевым или NULL. Так как каждая вершина-нормальная-texcoord комбо составляет 32 байта, то есть размер шага. "sizeof (GLfloat) 8" говорит 32 байта от NULL смещения, будет другая группа xyz вершины. В случае нормалей каждая нормальная xyz-группа составляет 12 байтов после смещения для группы xyz вершин, поэтому "(float) (sizeof (GLfloat) * 3)" в качестве начального смещения. Опять же, размер шага составляет 32 байта. В-четвертых, вы должны сказать, чтобы рисовать все треугольники, связанные с массивом индексов. Наконец, вы должны отключить состояния клиента, если вы хотите использовать другой метод рендеринга.
//Render
// Step 1
glBindBuffer(GL_ARRAY_BUFFER, geometry_array);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indice_array);
// Step 2
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
// Step 3
glTexCoordPointer(3, GL_FLOAT, sizeof(GLfloat)*8, (float*)(sizeof(GLfloat)*5));
glNormalPointer(GL_FLOAT, sizeof(GLfloat)*8, (float*)(sizeof(GLfloat)*3));
glVertexPointer(3, GL_FLOAT, sizeof(GLfloat)*8, NULL);
// Step 4
glDrawElements(GL_TRIANGLES, num_indices, GL_UNSIGNED_INT, NULL);
// Step 5
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);