VBOs and Vertex Arrays in OpenGL not working

Member
Posts: 215
Joined: 2008.06
Post: #1
Been working in OpenGL for a few weeks now and have gotten into some of the slightly more advanced aspects such as Vertex Arrays and Vertex Buffer Objects.

I found a few tutorials that explained how things work and what needs to be done to get these to work, but every time I attempt to use VBOs and VAs, my code explodes with the error: EXC_BAD_ACCESS and the debugger says it stops at a function known as gleLLVMLoadDataFromAryFloatInFloat.

I gave up on getting VBOs to work after getting this error several times; I figured that my video card did not support VBOs.

But then I read some info on VAs and found that they should be supported as long as glext.h was available to you. Inside of opengl.h is glext.h. Besides, my compiler has no issue with the code I have written, but it continues to crash with the above errors, even with Vertex Arrays. Here is my code:

Code:
#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#include <GLUT/GLUT.h>
#else
#include <GL/glut.h>
#endif
#include <stdlib.h>
#include <iostream>

#define BOX_SIZE    7.0f
#define BOX_HEIGHT    7.0f
#define FLOOR_SIZE    20.0f

using namespace std;

//Globals (ew I know) for our zoom and rotation angles.
float _angle;
float _vertAngle = 30.0f;
float _horzAngle;
float _planeAngle;
float _zZoom;

GLuint theCubesVBO;
GLuint theCubesColorBO;
GLuint theCubesNormalBO;

GLfloat cubeArray[] =
{
-BOX_SIZE / 2, BOX_SIZE / 2, -BOX_SIZE / 2,
-BOX_SIZE / 2, BOX_SIZE / 2, BOX_SIZE / 2,
BOX_SIZE / 2, BOX_SIZE / 2, BOX_SIZE / 2,
BOX_SIZE / 2, BOX_SIZE / 2, -BOX_SIZE / 2,

-BOX_SIZE / 2, -BOX_SIZE / 2, -BOX_SIZE / 2,
BOX_SIZE / 2 , -BOX_SIZE / 2, -BOX_SIZE / 2,
BOX_SIZE / 2, -BOX_SIZE / 2, BOX_SIZE / 2,
-BOX_SIZE / 2, -BOX_SIZE / 2, BOX_SIZE / 2,

-BOX_SIZE / 2, -BOX_SIZE / 2, -BOX_SIZE / 2,
-BOX_SIZE / 2, -BOX_SIZE / 2, BOX_SIZE / 2,
-BOX_SIZE / 2, BOX_SIZE / 2, BOX_SIZE / 2,
-BOX_SIZE / 2, BOX_SIZE / 2, -BOX_SIZE / 2,

BOX_SIZE / 2, -BOX_SIZE / 2, -BOX_SIZE / 2,
BOX_SIZE / 2, BOX_SIZE / 2, -BOX_SIZE / 2,
BOX_SIZE / 2, BOX_SIZE / 2, BOX_SIZE / 2,
BOX_SIZE / 2, -BOX_SIZE / 2, BOX_SIZE / 2,

-BOX_SIZE / 2, -BOX_SIZE / 2, -BOX_SIZE / 2,
BOX_SIZE / 2, -BOX_SIZE / 2, -BOX_SIZE / 2,
BOX_SIZE / 2, BOX_SIZE / 2, -BOX_SIZE / 2,
-BOX_SIZE / 2, BOX_SIZE / 2, -BOX_SIZE / 2,

-BOX_SIZE / 2, -BOX_SIZE / 2, BOX_SIZE / 2,
BOX_SIZE / 2, -BOX_SIZE / 2, BOX_SIZE / 2,
BOX_SIZE / 2, BOX_SIZE / 2, BOX_SIZE / 2,
-BOX_SIZE / 2, BOX_SIZE / 2, BOX_SIZE / 2
};

GLfloat cubeColor[] =
{
0.7f, 0.7f, 0.7f, 0.4f,
0.2f, 0.2f, 0.2f, 0.4f,
0.9f, 0.6f, 0.3f, 0.4f,
0.0f, 0.0f, 0.1f, 0.4f,
0.0f, 1.0f, 0.0f, 0.4f,
1.0f, 0.0f, 0.0f, 0.4f
};


/**  Ignore this as it is currently not called. */
void generateCubeVBO()
{
    GLfloat cubeNormal[] =
    {
        0.0f, 1.0f, 0.0f,
        0.0f, -1.0f, 0.0f,
        -1.0f, 0.0f, 0.0f,
        1.0f, 0.0f, 0.0f,
        0.0f, 0.0f, -1.0f,
        0.0f, 0.0f, 1.0f
    };
    
    glGenBuffersARB(1, &theCubesVBO);
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, theCubesVBO);
    glBufferData(GL_ARRAY_BUFFER_ARB, sizeof(cubeArray), cubeArray, GL_STATIC_DRAW);
    
    glGenBuffersARB(1, &theCubesColorBO);
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, theCubesColorBO);
    glBufferData(GL_ARRAY_BUFFER_ARB, sizeof(cubeColor), cubeColor, GL_STATIC_DRAW);
    
    glGenBuffersARB(1, &theCubesNormalBO);
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, theCubesNormalBO);
    glBufferData(GL_ARRAY_BUFFER_ARB, sizeof(cubeNormal), cubeNormal, GL_STATIC_DRAW);
}

/** Draws a cube, with faces built for alpha blending (counter-clockwise)
*
*    @parameter angle The angle at which to draw the cube.
*/
void drawCube(float angle)
{
    glPushMatrix();                                    //Save the current render context.
    
    glRotatef(-angle, 0.9f, 0.6f, 0.3f);            //Rotate to our supplied angle.
    
    //Begin drawing the cube.
    glBegin(GL_QUADS);
    {
        //top face
        glColor4f(0.7f, 0.7f, 0.7f, 0.4f);            //Light grey color.
        glNormal3f(0.0f, 1.0f, 0.0f);                //Upward normal.
        glVertex3f(-BOX_SIZE / 2, BOX_SIZE / 2, -BOX_SIZE / 2);        //closest left corner
        glVertex3f(-BOX_SIZE / 2, BOX_SIZE / 2, BOX_SIZE / 2);        //furthest left corner
        glVertex3f(BOX_SIZE / 2, BOX_SIZE / 2, BOX_SIZE / 2);        //furthest right corner
        glVertex3f(BOX_SIZE / 2, BOX_SIZE / 2, -BOX_SIZE / 2);        //closest right corner
        
        //bottom face
        glColor4f(0.2f, 0.2f, 0.2f, 0.4f);            //dark grey color.
        glNormal3f(0.0f, -1.0f, 0.0f);                //Downward pointing normal.
        glVertex3f(-BOX_SIZE / 2, -BOX_SIZE / 2, -BOX_SIZE / 2);    //closest left corner
        glVertex3f(BOX_SIZE / 2, -BOX_SIZE / 2, -BOX_SIZE / 2);        //closest right corner
        glVertex3f(BOX_SIZE / 2, -BOX_SIZE / 2, BOX_SIZE / 2);        //furthest right corner
        glVertex3f(-BOX_SIZE / 2, -BOX_SIZE / 2, BOX_SIZE / 2);        //furthest left corner
        
        //left face
        glColor4f(0.9f, 0.6f, 0.3f, 0.4f);            //Yellowish color.
        glNormal3f(-1.0f, 0.0f, 0.0f);                //Left pointing normal.
        glVertex3f(-BOX_SIZE / 2, -BOX_SIZE / 2, -BOX_SIZE / 2);    //closest bottom corner
        glVertex3f(-BOX_SIZE / 2, -BOX_SIZE / 2, BOX_SIZE / 2);        //furthest bottom corner
        glVertex3f(-BOX_SIZE / 2, BOX_SIZE / 2, BOX_SIZE / 2);        //closest top corner
        glVertex3f(-BOX_SIZE / 2, BOX_SIZE / 2, -BOX_SIZE / 2);        //furthest top corner
        
        //right face
        glColor4f(0.0f, 0.0f, 1.0f, 0.4f);            //Blue color.
        glNormal3f(1.0f, 0.0f, 0.0f);                //Right normal.
        glVertex3f(BOX_SIZE / 2, -BOX_SIZE / 2, -BOX_SIZE / 2);        //closest bottom corner
        glVertex3f(BOX_SIZE / 2, BOX_SIZE / 2, -BOX_SIZE / 2);        //furthest bottom corner
        glVertex3f(BOX_SIZE / 2, BOX_SIZE / 2, BOX_SIZE / 2);        //closest top corner
        glVertex3f(BOX_SIZE / 2, -BOX_SIZE / 2, BOX_SIZE / 2);        //furthest top corner
        
        //front face
        glColor4f(0.0f, 1.0f, 0.0f, 0.4f);            //Green color.
        glNormal3f(0.0f, 0.0f, -1.0f);                //outward pointing normal.
        glVertex3f(-BOX_SIZE / 2, -BOX_SIZE / 2, -BOX_SIZE / 2);    //bottom left corner
        glVertex3f(BOX_SIZE / 2, -BOX_SIZE / 2, -BOX_SIZE / 2);        //bottom right corner
        glVertex3f(BOX_SIZE / 2, BOX_SIZE / 2, -BOX_SIZE / 2);        //top left corner
        glVertex3f(-BOX_SIZE / 2, BOX_SIZE / 2, -BOX_SIZE / 2);        //top right corner
        
        //back face
        glColor4f(1.0f, 0.0f, 0.0f, 0.4f);            //Red color.
        glNormal3f(0.0f, 0.0f, 1.0f);                //Inward pointing normal.
        glVertex3f(-BOX_SIZE / 2, -BOX_SIZE / 2, BOX_SIZE / 2);//bottom left corner
        glVertex3f(BOX_SIZE / 2, -BOX_SIZE / 2, BOX_SIZE / 2);//bottom right corner
        glVertex3f(BOX_SIZE / 2, BOX_SIZE / 2, BOX_SIZE / 2);//top left corner
        glVertex3f(-BOX_SIZE / 2, BOX_SIZE / 2, BOX_SIZE / 2);//top right corner
    }
    glEnd();
    
    glPopMatrix();                                //Restore previous render setup.
}

/** Draws the floor quad with alpha reduction. */
void drawFloor()
{
    /** Reflections using colored (non-textured) polygons require the use of
     * the Color4f call to specify a color AND transparency for that vertex.
     * OpenGL will interpolate alpha values between points with different alpha
     * values, allowing for some cool gradient effects.
     **/
    
    //Begin drawing the floor quad with an opacity of 0.7
    glBegin(GL_QUADS);
    {
        glNormal3f(0.0f, 1.0f, 0.0f);                    //Upward pointing normal.
        glColor4f(1.0f, 0.0f, 0.0f, 0.7f);                //Red transparent color.
        glVertex3f(-FLOOR_SIZE / 2, 0.0f, FLOOR_SIZE / 2);        //closest left corner
        glColor4f(0.0f, 1.0f, 0.0f, 0.7f);                //Green transparent color.
        glVertex3f(FLOOR_SIZE / 2, 0.0f, FLOOR_SIZE / 2);        //closest right corner
        glColor4f(0.0f, 0.0f, 1.0f, 0.7f);                //Blue transparent color.
        glVertex3f(FLOOR_SIZE / 2, 0.0f, -FLOOR_SIZE / 2);        //furthest right corner
        glColor4f(0.8f, 0.4f, 0.2f, 0.7f);                //Dark Orange transparent color.
        glVertex3f(-FLOOR_SIZE / 2, 0.0f, -FLOOR_SIZE / 2);        //furthest left corner
    }
    glEnd();
}

/** Set up OpenGL with the preferences we need. */
void initRendering()
{
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHTING);            //For directional lighting and ambient lighting.
    glEnable(GL_LIGHT0);            //Directional light.
    glEnable(GL_NORMALIZE);            //Correct for augmented normals.
    glEnable(GL_COLOR_MATERIAL);
    
    glEnable(GL_BLEND);                //Allow alpha channel blending for textures.
    
    //glEnable(GL_CULL_FACE);
    
    //How to blend our texture alphas, using the source alpha.
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}

/** Handle the reshaping of the window.
*
*    @parameter width The new width of the window.
*    @parameter height The new height of the window.
*/
void handleReshape(int width, int height)
{
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0, (float)width / (float)height, 1.0, 200.0);
}

/** Draw our objects, lights, etc. */
void drawScene()
{
    //Clear everything.
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
    //Make sure we are in model view and at the origin to begin with.
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    
    glEnable(GL_VERTEX_ARRAY);
    //glEnable(GL_COLOR_ARRAY);
    
    //Translate to our starting position and rotate a little so we can see the floor.
    glTranslatef(0.0f, 0.0f, -40.0f + _zZoom);
    glRotatef(_vertAngle, 1, 0, 0);
    glRotatef(_horzAngle, 0, 1, 0);
    glRotatef(_planeAngle, 0, 0, 1);
    
    //Lighting stuff...
    GLfloat ambientColor[] = {0.2f, 0.2f, 0.2f, 1.0f};        //Dim white light.
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientColor);
    
    GLfloat lightColor[] = {0.7, 0.7, 0.7, 1.0f};            //Semi-bright white light.
    GLfloat lightPosition[] = {-2 * BOX_SIZE, BOX_SIZE, 4 * BOX_SIZE, 1.0f};
    
    glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor);
    glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
    //...End lighting stuff.
    
    glPushMatrix();                                            //Save current render setup.
    glTranslatef(0, BOX_HEIGHT, 0);                            //Translate to draw the cube.
    
    glColor3f(0.0f, 0.0f, 1.0f);                            //Blue color.
    glutSolidSphere(BOX_SIZE / 3, 14, 14);                    //Draw the central sphere.
    
    //Advanced face-culling alpha blending technique...
    glCullFace(GL_FRONT);        //Cull the front faces
    //drawCube(_angle);            //Draw the remaining faces (just the back faces.)
    
    glVertexPointer(3, GL_FLOAT, 0, cubeArray);
    //glColorPointer(4, GL_FLOAT, 0, cubeColor);
    glDrawArrays(GL_QUADS, 0, 24);
    
    glCullFace(GL_BACK);        //Cull the back faces (replaces front faces.)
    drawCube(_angle);            //Draw the remaining faces (just the front faces.)
    glPopMatrix();                                            //Restore the previous rendering setup
    
    //Reflection...
    glEnable(GL_STENCIL_TEST);                        //Begins a stencil buffer operation.
    glColorMask(0, 0, 0, 0);                        //Makes the next actions invisible.
    glDisable(GL_DEPTH_TEST);                        //Don't need depth testing, so turn it off.
    glStencilFunc(GL_ALWAYS, 1, 1);                    //Forces the bit changes in the stencil buffer to always pass.
    glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);        //Replaces the current bits in the stencil buffer if they pass.
    drawFloor();                                    //Put the floor's mapping into the stencil buffer.
    
    glColorMask(1, 1, 1, 1);                        //Allow the following actions to be visible.
    glEnable(GL_DEPTH_TEST);                        //Reenable depth testing - We are done using the stencil buffer.
    glStencilFunc(GL_EQUAL, 1, 1);                    //Draw only where the stencil buffer bits are equal to 1.
    glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);            //Stop modifying the stencil buffer.
    
    glPushMatrix();                                    //Save current render context.
    glScalef(1, -1, 1);                                //Flip upside down.  This is where our normals get messed up...
    glTranslatef(0, BOX_HEIGHT, 0);                    //Move DOWN by the box height.
    
    glColor3f(1.0f, 1.0f, 1.0f);                    //White Color-This is to show some interesting possibilities for renderer-induced illusions.
    glutSolidSphere(BOX_SIZE / 2, 64, 64);            //The central sphere larger than above...
    
    //Draw the transparent cube again, as a reflection.
    glCullFace(GL_FRONT);
    drawCube(_angle);
    glCullFace(GL_BACK);
    drawCube(_angle);
    glPopMatrix();
    
    glDisable(GL_STENCIL_TEST);                        //Stop using the stencil buffer.
    
    drawFloor();                                    //Draw the floor, we must do this last, because it is in front of the "reflected" objects.
    
    glutSwapBuffers();                                //Display.
}

/** This is called every 25 milliseconds, increments our angle for the cube. */
void update(int value)
{
    _angle += 1.0f;
    
    if (_angle > 360)
    {
        _angle -= 360;
    }
    
    glutPostRedisplay();                            //A display value is changed, so we need to prompt for a redisplay.
    glutTimerFunc(25, update, 0);                    //Reset the timer with this function for it's call.
}

/** Handles inputs from the keyboard.
*
*    @parameter key The key that has been pressed.
*    @parameter x The x-coord of the mouse I think.
*    @parameter y The y-coord of the mouse I think.
*/
void handleKeypress(unsigned char key, int x, int y)
{
    switch (key)
    {
        case 27:            //ESC key.
            exit(0);
            break;
            
        case 'w':
            _vertAngle += 5.0f;
            if (_vertAngle > 360)
            {
                _vertAngle -= 360;
            }
            break;
        case 's':
            _vertAngle -= 5.0f;
            if (_vertAngle < -360)
            {
                _vertAngle += 0;
            }
            break;

        case 'q':
            _horzAngle += 5.0f;
            if (_horzAngle > 360)
            {
                _horzAngle -= 360;
            }
            break;
        case 'e':
            _horzAngle -= 5.0f;
            if (_horzAngle < -360)
            {
                _horzAngle += 360;
            }
            break;
            
        case 'a':
            _planeAngle += 5.0f;
            if (_planeAngle > 360)
            {
                _planeAngle -= 360;
            }
            break;
        case 'd':
            _planeAngle -= 5.0f;
            if (_planeAngle < -360)
            {
                _planeAngle += 360;
            }
            break;
            
        case 'z':
            _zZoom += 5.0f;
            if (_zZoom > 30.0f)
            {
                //_zZoom -= 30.0f;
            }
            break;
        case 'x':
            _zZoom -= 5.0f;
            if (_zZoom < 0)
            {
                _zZoom = 0;
            }
            break;
            
        default:
            break;
    }
}

/** Entry point, sets up the glut stuff we need. */
int main(int argc, char** argv)
{
    glutInit(&argc, argv);                                                        //Sets up GLUT
    //We need to use RGBA color space, depth testing, and stencil testing.  We also allow for double precision in the depth buffer.
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
    glutInitWindowSize(1440, 900);                                                //Create a window that is 400 by 400.
    glutInitWindowPosition(0, 0);                                                //Create a window at position 50, 50.
    glutCreateWindow("Kyle Roucs - Contest 2 Entry");                            //Create a window with this title..
    
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);
    
    initRendering();                                                            //Initialize our prefs.
    generateCubeVBO();
    
    //Set our utility functions.
    glutDisplayFunc(drawScene);
    glutKeyboardFunc(handleKeypress);
    glutReshapeFunc(handleReshape);
    
    glutTimerFunc(25, update, 0);                                                //Set the timer and it's corresponding function.
    
    glutMainLoop();                                                                //Move to the GLUT main loop.
    return 0;
}

Any insight or solutions would be great, thanks.

[edit]
I should say that I have an Intel iMac with 2GB RAM and an ATI Radeon X1600 graphics card. Not sure if this helps with figuring out if my system is able to use VBOs and VAs or not.

Mac users swear by their computers, PC users swear at their computers. ~Unknown

iSayz
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #2
When you are crashing using vertex arrays or VBOs, there is a 99.9% chance that your app has a bug. Here is what you should look for:

1) you've got a valid pointer set for all of the attributes you're submitting (a pointer to client address, if using VAs, or a valid offset, if using VBOs)
2) you've got all of the attributes you're submitting enabled, and don't have any other attributes enabled.
3) if you're using VBOs, you had a BO bound at the time you set each pointer as an offset, and not bound for pointers you set as a client address.

Failing any of those three things results in GL trying to read from memory that you don't own, or the GL didn't allocate for you, and you crash.

The other 0.01% of the time, it's a driver bug.



In the code you posted, you've enabled VERTEX, COLOR, and NORMAL. But you've only ever set the pointers for Vertex. So the GL may try to load color and normal data from the default null pointer, and crash.
Quote this message in a reply
Member
Posts: 567
Joined: 2004.07
Post: #3
...and that other 0.09% is the compiler's fault. Wink

It's not magic, it's Ruby.
Quote this message in a reply
Member
Posts: 215
Joined: 2008.06
Post: #4
Arekkusu,

You were correct in the fact that removing GL_COLOR_ARRAY and GL_NORMAL_ARRAY allowed it to run just fine...

Until I tried back face and front face culling with it. With the new code, it doesn't even draw the cube. Any draw that uses either of the VAs does not draw. Compiler works fine, it doesn't crash anymore... I don't know what to think.

BTW I reenabled GL_COLOR_ARRAY and it seems to work OK now.

[EDIT]
Nevermind! I fixed it! I still had calls to my generateCubeVBO() function which was disrupting my settings! Thanks still.

[Second Edit]
I also found that normals are declared PER VERTEX in VA usage, so that is probably why I was getting errors when trying to associate normals with my vertexes. Should have guessed...

[Final Edit]
Well, I can't get a glNormalPointer(3, GL_FLOAT, cubeNormals) call to not crash. It gives me my original crash and message. Any new insight?

Mac users swear by their computers, PC users swear at their computers. ~Unknown

iSayz
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #5
Try passing the correct arguments:

glNormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer )

"GL_FLOAT" is a really big stride.
Quote this message in a reply
Member
Posts: 215
Joined: 2008.06
Post: #6
arekkusu Wrote:Try passing the correct arguments:

glNormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer )

"GL_FLOAT" is a really big stride.

AWW! You were totally right. I wasn't paying attention! Thank you!

Mac users swear by their computers, PC users swear at their computers. ~Unknown

iSayz
Quote this message in a reply
Oldtimer
Posts: 834
Joined: 2002.09
Post: #7
Quote:When you are crashing using vertex arrays or VBOs, there is a 99.9% chance that your app has a bug. ... The other 0.1% of the time, it's a driver bug.
That differs from my experience and what I've heard: there's a 99.9% chance that my code is buggy, and in the other 0.1%, it's still my code that is buggy.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  OpenGL glDrawArrays not working dotbianry 12 11,474 Dec 21, 2012 09:21 AM
Last Post: Skorche
  Combining OpenGL vertex data into 1 object Jmcclane 0 3,277 Jun 17, 2011 12:03 PM
Last Post: Jmcclane
  ? Export Vertex Arrays from Gfx App ? Elphaba 2 2,902 Jun 11, 2009 12:39 PM
Last Post: Elphaba
  Text rendering problem with VBOs on myfeng 9 5,951 Feb 29, 2008 04:54 PM
Last Post: OneSadCookie
  GL_SELECT mode in VBOs myfeng 0 2,345 Feb 28, 2008 10:38 AM
Last Post: myfeng