+ GLuint vbo_coords = 0, vbo_normals = 0, ibo_elements = 0;
+ GLsizei numVertIdxs = numParts * numVertIdxsPerPart;
+ int i;
+
+ if (numVertices > 0 && attribute_v_coord != -1) {
+ fghGenBuffers(1, &vbo_coords);
+ fghBindBuffer(FGH_ARRAY_BUFFER, vbo_coords);
+ fghBufferData(FGH_ARRAY_BUFFER, numVertices * 3 * sizeof(vertices[0]),
+ vertices, FGH_STATIC_DRAW);
+ fghBindBuffer(FGH_ARRAY_BUFFER, 0);
+ }
+
+ if (numVertices > 0 && attribute_v_normal != -1) {
+ fghGenBuffers(1, &vbo_normals);
+ fghBindBuffer(FGH_ARRAY_BUFFER, vbo_normals);
+ fghBufferData(FGH_ARRAY_BUFFER, numVertices * 3 * sizeof(normals[0]),
+ normals, FGH_STATIC_DRAW);
+ fghBindBuffer(FGH_ARRAY_BUFFER, 0);
+ }
+
+ if (vertIdxs != NULL) {
+ fghGenBuffers(1, &ibo_elements);
+ fghBindBuffer(FGH_ELEMENT_ARRAY_BUFFER, ibo_elements);
+ fghBufferData(FGH_ELEMENT_ARRAY_BUFFER, numVertIdxs * sizeof(vertIdxs[0]),
+ vertIdxs, FGH_STATIC_DRAW);
+ fghBindBuffer(FGH_ELEMENT_ARRAY_BUFFER, 0);
+ }
+
+ if (vbo_coords) {
+ fghEnableVertexAttribArray(attribute_v_coord);
+ fghBindBuffer(FGH_ARRAY_BUFFER, vbo_coords);
+ fghVertexAttribPointer(
+ attribute_v_coord, /* attribute */
+ 3, /* number of elements per vertex, here (x,y,z) */
+ GL_FLOAT, /* the type of each element */
+ GL_FALSE, /* take our values as-is */
+ 0, /* no extra data between each position */
+ 0 /* offset of first element */
+ );
+ fghBindBuffer(FGH_ARRAY_BUFFER, 0);
+ };
+
+ if (vbo_normals) {
+ fghEnableVertexAttribArray(attribute_v_normal);
+ fghBindBuffer(FGH_ARRAY_BUFFER, vbo_normals);
+ fghVertexAttribPointer(
+ attribute_v_normal, /* attribute */
+ 3, /* number of elements per vertex, here (x,y,z) */
+ GL_FLOAT, /* the type of each element */
+ GL_FALSE, /* take our values as-is */
+ 0, /* no extra data between each position */
+ 0 /* offset of first element */
+ );
+ fghBindBuffer(FGH_ARRAY_BUFFER, 0);
+ };
+
+ if (vertIdxs == NULL) {
+ glDrawArrays(GL_TRIANGLES, 0, numVertices);
+ } else {
+ fghBindBuffer(FGH_ELEMENT_ARRAY_BUFFER, ibo_elements);
+ if (numParts>1) {
+ for (i=0; i<numParts; i++) {
+ glDrawElements(GL_TRIANGLE_STRIP, numVertIdxsPerPart, GL_UNSIGNED_SHORT, (GLvoid*)(sizeof(vertIdxs[0])*i*numVertIdxsPerPart));
+ }
+ } else {
+ glDrawElements(GL_TRIANGLES, numVertIdxsPerPart, GL_UNSIGNED_SHORT, 0);
+ }
+ /* Clean existing bindings before clean-up */
+ /* Android showed instability otherwise */
+ fghBindBuffer(FGH_ELEMENT_ARRAY_BUFFER, 0);
+ }
+
+ if (vbo_coords != 0)
+ fghDisableVertexAttribArray(attribute_v_coord);
+ if (vbo_normals != 0)
+ fghDisableVertexAttribArray(attribute_v_normal);
+
+ if (vbo_coords != 0)
+ fghDeleteBuffers(1, &vbo_coords);
+ if (vbo_normals != 0)
+ fghDeleteBuffers(1, &vbo_normals);
+ if (ibo_elements != 0)
+ fghDeleteBuffers(1, &ibo_elements);
+}
+
+
+
+/**
+ * Generate all combinations of vertices and normals needed to draw object.
+ * Optional shape decomposition to triangles:
+ * We'll use glDrawElements to draw all shapes that are not naturally
+ * composed of triangles, so generate an index vector here, using the
+ * below sampling scheme.
+ * Be careful to keep winding of all triangles counter-clockwise,
+ * assuming that input has correct winding...
+ */
+static GLubyte vert4Decomp[6] = {0,1,2, 0,2,3}; /* quad : 4 input vertices, 6 output (2 triangles) */
+static GLubyte vert5Decomp[9] = {0,1,2, 0,2,4, 4,2,3}; /* pentagon: 5 input vertices, 9 output (3 triangles) */
+
+static void fghGenerateGeometryWithIndexArray(int numFaces, int numEdgePerFace, GLfloat *vertices, GLubyte *vertIndices, GLfloat *normals, GLfloat *vertOut, GLfloat *normOut, GLushort *vertIdxOut)
+{
+ int i,j,numEdgeIdxPerFace;
+ GLubyte *vertSamps = NULL;
+ switch (numEdgePerFace)
+ {
+ case 3:
+ /* nothing to do here, we'll draw with glDrawArrays */
+ break;
+ case 4:
+ vertSamps = vert4Decomp;
+ numEdgeIdxPerFace = 6; /* 6 output vertices for each face */
+ break;
+ case 5:
+ vertSamps = vert5Decomp;
+ numEdgeIdxPerFace = 9; /* 9 output vertices for each face */
+ break;
+ }