lupidan
lupidan

Reputation: 563

OpenGL, glDrawArrays and IOS, Bad Access?

I'm starting to work with OpenGL in iOS. I have always learned to draw stuff in OpenGL using glBegin() and glEnd() so this is kind of new to me.

I am trying to draw a simple triangle. I can draw a white triangle nicely, I even can draw an entire colored triangle using glColor. But whenever I try to assign a color to each vertex using this code below, I get a EXC_BAD_ACCESS when drawing the array. I am using iOS 4.3 simulator for this. What am I doing wrong?

- (void) render:(CADisplayLink*)displayLink {
    glClearColor(0, 104.0/255.0, 55.0/255.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    GLfloat vertices [] = {0,0,0, 0,100,0, 100,0,0};
    GLfloat colours [] = {1.0,1.0,1.0, 1.0,1.0,1.0, 1.0,1.0,1.0};
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    glVertexPointer(3, GL_FLOAT, 0, vertices);
    glColorPointer(3, GL_FLOAT, 0, colours);
    glDrawArrays(GL_TRIANGLES, 0, 3);   <-- CRASHES HERE
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_COLOR_ARRAY);

    [self.context presentRenderbuffer:GL_RENDERBUFFER];
}    

Upvotes: 4

Views: 3457

Answers (2)

Sam
Sam

Reputation: 7868

Your OpenGL code looks correct so far. Does the call to glDrawArrays cause bad access, or happens bad access within it? I just can imagine, that the glDrawArrays func pointer is not initialized, vertex arrays should be available though.

You may call this function after glEnableClientState(GL_COLOR_ARRAY); as a test to reset any other stale array pointers, which could cause bad access:

///@brief Emulation of call glClientAttribDefaultEXT(GL_CLIENT_VERTEX_ARRAY_BIT) according to GL_EXT_direct_state_access.

static void ClientAttribDefaultVertexArray(void) {
    int i;
    GLint max;

    glBindBufferARB(GL_ARRAY_BUFFER, 0);
    glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0);

    glDisableClientState(GL_EDGE_FLAG_ARRAY);
    glEdgeFlagPointer(0, 0);

    glDisableClientState(GL_INDEX_ARRAY);
    glIndexPointer(GL_FLOAT, 0, 0);

    glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
    glSecondaryColorPointer(4, GL_FLOAT, 0, 0);

    glDisableClientState(GL_FOG_COORD_ARRAY);
    glFogCoordPointer(GL_FLOAT, 0, 0);

    glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max);
    for (i = 0; i < max; ++i) {
        glClientActiveTextureARB(GL_TEXTURE0 + i);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
        glTexCoordPointer(4, GL_FLOAT, 0, 0);
    }

    glDisableClientState(GL_COLOR_ARRAY);
    glColorPointer(4, GL_FLOAT, 0, 0);

    glDisableClientState(GL_NORMAL_ARRAY);
    glNormalPointer(GL_FLOAT, 0, 0);

    glDisableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(4, GL_FLOAT, 0, 0);

    glDisableClientState(GL_WEIGHT_ARRAY_ARB);
    glWeightPointerARB(0, GL_FLOAT, 0, 0);

    glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &max);
    for (i = 0; i < max; ++i) {
        glDisableVertexAttribArrayARB(i);
        glVertexAttribPointerARB(i, 4, GL_FLOAT, GL_FALSE, 0, 0);
    }

    glClientActiveTextureARB(GL_TEXTURE0);
}

Additionally, you can push and pop the vertex array state on the client attrib stack:

glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);

///vertex array init and usage

glPopClientAttrib();

Upvotes: 1

iHunter
iHunter

Reputation: 6205

The line glColorPointer(3, GL_FLOAT, 0, colours) generates the GL_INVALID_VALUE error (you can see that doing po glGetError right after executing that line, it will print 1281).

The reason is that OpenGL ES doesn't support 3 color components, the documentation states:

GL_INVALID_VALUE is generated if size is not 4.

You code will be ok if you change the number of color components to 4 by adding alpha.

Upvotes: 5

Related Questions