Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>For such simple objects I would make one big VBO say 200 Objects * NrVerticesPerCube, put all the data interleaved Vertex,Normal,UV,Vertex,Normal,UV, etc.</p> <p>I do something similar in a keyframe animation of a beaver in my game, I start with something like this:</p> <pre><code>glGenBuffers(1, &amp;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], &amp;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); </code></pre> <p>This creates my VBO buffer with the correct size (in this case 8 * sizeof(GLfloat) wich is 3 Verts, 3 Normals and 2UV), and copies the first keyframe to the buffer, you could do the same with you initial object positions, or just leave that and compute latter...</p> <p>Then in each frame I do interpolation between 2 keyframes for each vertex of my beaver, and just make one draw call, this is very fast for the 4029 vertices my beaver has, and works at 60FPS on my iPhone 3G.</p> <p>For you doing only gltranslates it would be even simpler, just add the values of x,y,z to each vertice of each cube.</p> <p>You would update it like this:</p> <pre><code> glBindBuffer(GL_ARRAY_BUFFER, vboObjects[vboGroupBeaver]); GLvoid* vbo_buffer = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES); </code></pre> <p>Bind the vbo buffer and mapit to a buffer var. Calculate the stuff you want on a temp var.</p> <pre><code> memcpy(vbo_buffer, currentVert, 6*sizeof(GLfloat)); // 0 vbo_buffer += 8*sizeof(GLfloat); </code></pre> <p>Copy it and update buffer to next object, repeat until all objects updated... You could also do all the updates in a seperate array and copy the whole array, but then you would be copying extra info that usually doesn't change (normals and UV). Or you could not use interleaved data and copy that...</p> <pre><code> glUnmapBufferOES(GL_ARRAY_BUFFER); </code></pre> <p>Unmap the VBO buffer</p> <pre><code> 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); </code></pre> <p>Setup your draw call, and draw it all...</p> <p>If you need to rotate objects and not just gltranslate them, you will need to add some matrix multiplications along the way...</p> <p><em><strong></em> EDIT **</strong></p> <p>ok, making a gltranste by hand is actually very easy (rotation, etc is a bit trickier).</p> <p>I'm using a an interleaved plane drawed using TRIANGLE_STRIP instead of triangles, but the principle is the same.</p> <pre><code> 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] }; </code></pre> <p>So this is interleaved vertex, you got vertex then Normals then UV, if you're not using textures substitute UV for color.</p> <p>The easiest way is to have an array with all the objects inside (made easy if all your objects are the same size) and make the position updates after draw (instead of in the middle of the opengl frame), better still make a seperate thread, create 2 VBOs update one of them while drawing from the other, something like this:</p> <ul> <li>Thread 1 OpenGL DrawFrom VBO0</li> <li>Thread 2 Game Updates, update positions on internal array and copy to VBO1, set Var saying VBO1 yes ready (so thread 1 only changes from drawing to VBO1 when all the updates are done).</li> <li>Thread 1 OpenGL DrawFrom VBO1</li> <li>Thread 2 Game update, same thing but update VBO0</li> <li>continue with same logic</li> </ul> <p>this is called double buffering and you use it to garanty stability, without this sometimes your game logic will be updating the VBO while the graphics card needs it and the graphics card will have to wait, resulting in lower FPS.</p> <p>Anyway, back on topic</p> <p>to make the equivalent to gltranslatef(10,20,30) just do:</p> <pre><code> 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 &lt; (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); </code></pre> <p>Of course the update values doesn't have to be the same for all the objects, infact using a base array like this you can update all the info as you go along and just have the routine to copy it to VBO when needed.</p> <p>All this was written from memory on the fly, so there maybe dragons :-)</p> <p>Hope that helps.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload