Search code examples
ios5opengl-es-2.0glkitvertex-buffer

Handle multiple meshes in Open GL ES 2.0 (iOS GLKit)?


I've managed to create a single mesh in Open GL ES 2.0 using iOS's GLKit. What I can't figure out is how to create a second mesh that looks identical to the first except with a different position.

I think what would be most helpful would be if someone could simply provide some sample code that draws multiple meshes, as I think I'm going about this entirely wrong. Nonetheless, here's a list of what I've done to try make this work.

  • I created two C-arrays of vertex information. The first is my template (hardcoded coordinates centered at 0,0,0) and the second is what I'd like displayed (initially empty).
  • I created two C-arrays of indice information. Same deal as with the vertex information.
  • I have two global variable ints, vertexCount and indiceCount, both initially 0.
  • I have a c function, createAt(float x, float y, float z). This function copies my vertex template into my vertex display array and then applies the passed in offsets to each vertex. It also copies indices in and applies an offset so that they point at the new display vertexes.

This doesn't work though. Only one object gets drawn on screen.

Looking through other people's questions and answers, it sounds like maybe I should have multiple vertex buffers? I don't know; I'm horribly confused.


Solution

  • Rendering multiple meshes with the same geometry but different positions or orientations is quite easy with GLKit, thanks to the GLKBaseEffect class. Take a look at the "OpenGL Game" template provided by Xcode, which renders a cube with GLKit and another cube with OpenGL ES 2.0.

    Here's a modification of the OpenGL Game sample which adds a new cube above the two spinning ones:

    - (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
    {
        glClearColor(0.65f, 0.65f, 0.65f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
        glBindVertexArrayOES(_vertexArray);
    
        // Render the object with GLKit
        [self.effect prepareToDraw];
    
        glDrawArrays(GL_TRIANGLES, 0, 36);
    
        // Render another version of the object with GLKit
    
        // First put it in a different place (you would normally
        // do this in the update loop):
        GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f);
        baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f);    
        GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 1.5, -0.0f);
        modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix);
        self.effect.transform.modelviewMatrix = modelViewMatrix;
    
        // Now render it:
        [self.effect prepareToDraw];
        glDrawArrays(GL_TRIANGLES, 0, 36);
    
        // Render the object again with ES2
        glUseProgram(_program);
    
        glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
        glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m);
    
        glDrawArrays(GL_TRIANGLES, 0, 36);
    }
    

    The code in-between the "Render another version" and "Render the object again" comments is new. The first thing it needs to do is come up with a new modelview matrix for the additional cube; this is based on the code in update: (not shown). Normally I'd put the code up there but I wanted to keep the sample short.

    Next it renders the cube, which is pretty simple with GLKit. Yay GLKit!

    Screenshot of three cubes in Apple's GLKit / OpenGL Game sample

    I hope this helps. It sounds like you're barking up the wrong tree with additional vertex and index arrays; this is necessary if you want to render different geometries, but you said the same model in different places. That's something GLKit is ideal for.