/* * gcc -Wall -ansi -lGL -lGLU -lGLEW -lglut vbo.c -o vbo */ #include #include #include #include #include struct VN_t { GLfloat v[3]; /* position */ GLfloat n[3]; /* normal */ }; static struct VN_t cube[24] = { { { 0.0, 0.0, 0.0 }, { 0.0, 0.0, -1.0 } }, { { 0.0, 1.0, 0.0 }, { 0.0, 0.0, -1.0 } }, { { 1.0, 1.0, 0.0 }, { 0.0, 0.0, -1.0 } }, { { 1.0, 0.0, 0.0 }, { 0.0, 0.0, -1.0 } }, { { 0.0, 0.0, 1.0 }, { 0.0, 0.0, 1.0 } }, { { 1.0, 0.0, 1.0 }, { 0.0, 0.0, 1.0 } }, { { 1.0, 1.0, 1.0 }, { 0.0, 0.0, 1.0 } }, { { 0.0, 1.0, 1.0 }, { 0.0, 0.0, 1.0 } }, { { 1.0, 0.0, 1.0 }, { 1.0, 0.0, 0.0 } }, { { 1.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 } }, { { 1.0, 1.0, 0.0 }, { 1.0, 0.0, 0.0 } }, { { 1.0, 1.0, 1.0 }, { 1.0, 0.0, 0.0 } }, { { 0.0, 0.0, 1.0 }, { -1.0, 0.0, 0.0 } }, { { 0.0, 1.0, 1.0 }, { -1.0, 0.0, 0.0 } }, { { 0.0, 1.0, 0.0 }, { -1.0, 0.0, 0.0 } }, { { 0.0, 0.0, 0.0 }, { -1.0, 0.0, 0.0 } }, { { 0.0, 1.0, 1.0 }, { 0.0, 1.0, 0.0 } }, { { 1.0, 1.0, 1.0 }, { 0.0, 1.0, 0.0 } }, { { 1.0, 1.0, 0.0 }, { 0.0, 1.0, 0.0 } }, { { 0.0, 1.0, 0.0 }, { 0.0, 1.0, 0.0 } }, { { 0.0, 0.0, 1.0 }, { 0.0, -1.0, 0.0 } }, { { 0.0, 0.0, 0.0 }, { 0.0, -1.0, 0.0 } }, { { 1.0, 0.0, 0.0 }, { 0.0, -1.0, 0.0 } }, { { 1.0, 0.0, 1.0 }, { 0.0, -1.0, 0.0 } }, }; static GLushort indices[24] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 }; GLuint vboId = 0; GLuint iboId = 0; static void init () { GLenum err = glewInit (); if (GLEW_OK != err) { /* Problem: glewInit failed, something is seriously wrong. */ fprintf (stderr, "Error: %s\n", glewGetErrorString (err)); exit (EXIT_FAILURE); } if (!GLEW_ARB_vertex_buffer_object) { fprintf (stderr, "Error: missing ARB_vertex_buffer_object extension\n"); exit (EXIT_FAILURE); } /* OpenGL initialization */ glClearColor (0.1f, 0.1f, 0.1f, 0.0f); glShadeModel (GL_SMOOTH); glEnable (GL_CULL_FACE); glEnable (GL_DEPTH_TEST); glEnable (GL_LIGHTING); glEnable (GL_LIGHT0); /* Here we create the VBOs. The index buffer object is made static, because we just want to test the mapping of the vertex buffer object. */ glGenBuffersARB (1, &vboId); glGenBuffersARB (1, &iboId); /* Allocate and copy data for index buffer object */ glBindBufferARB (GL_ELEMENT_ARRAY_BUFFER, iboId); glBufferDataARB (GL_ELEMENT_ARRAY_BUFFER, 24 * sizeof (GLushort), &indices, GL_STATIC_DRAW); /* Allocate memory for vertex buffer object */ glBindBufferARB (GL_ARRAY_BUFFER, vboId); glBufferDataARB (GL_ARRAY_BUFFER, 24 * sizeof (struct VN_t), NULL, GL_STREAM_DRAW_ARB); glBindBufferARB (GL_ELEMENT_ARRAY_BUFFER, 0); glBindBufferARB (GL_ARRAY_BUFFER, 0); } static void reshape (int w, int h) { if (h == 0) h = 1; glViewport (0, 0, (GLsizei)w, (GLsizei)h); glMatrixMode (GL_PROJECTION); glLoadIdentity (); gluPerspective (45.0, (GLfloat)w/(GLfloat)h, 0.1, 1000.0); glMatrixMode (GL_MODELVIEW); glLoadIdentity (); glutPostRedisplay (); } static void printMappingState (const char *s) { GLint is_mapped = 0; glBindBufferARB (GL_ARRAY_BUFFER_ARB, vboId); glGetBufferParameterivARB (GL_ARRAY_BUFFER_ARB, GL_BUFFER_MAPPED_ARB, &is_mapped); printf ("%s, buffer is%s mapped\n", s, is_mapped ? "" : " not"); } static void display () { GLenum err; struct VN_t *v; static float angle = 25.0; static int frame = 1; glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* Camera setup */ glLoadIdentity (); glTranslated (0.0f, 0.0f, -3.0f); glRotated (35.0f, 1.0f, 0.0f, 0.0f); glRotated (angle, 0.0f, 1.0f, 0.0f); glTranslatef (-0.5f, -0.5f, -0.5f); angle += 0.2; glBindBufferARB (GL_ELEMENT_ARRAY_BUFFER, iboId); glBindBufferARB (GL_ARRAY_BUFFER, vboId); printMappingState ("Before copying data"); if (0) { /* This code path works */ glBufferDataARB (GL_ARRAY_BUFFER, 24 * sizeof (struct VN_t), &cube, GL_STREAM_DRAW_ARB); } else { /* This code path doesn't work, unless if we uncomment the following line: */ /*glBufferDataARB (GL_ARRAY_BUFFER, 24 * sizeof (struct vertex), NULL, GL_STREAM_DRAW_ARB);*/ printf ("Mapping frame %i\n", frame); /* Map the buffer, copy data into it, and unmap it */ v = (struct VN_t *)glMapBufferARB (GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); memcpy (v, &cube, sizeof (cube)); glUnmapBufferARB (GL_ARRAY_BUFFER_ARB); } glEnableClientState (GL_VERTEX_ARRAY); glEnableClientState (GL_NORMAL_ARRAY); printMappingState ("Before drawing"); glNormalPointer (GL_FLOAT, sizeof (struct VN_t), (char *)(sizeof (GLfloat) * 3)); glVertexPointer (3, GL_FLOAT, sizeof (struct VN_t), 0); glDrawElements (GL_QUADS, 24, GL_UNSIGNED_SHORT, 0); glBindBufferARB (GL_ELEMENT_ARRAY_BUFFER, 0); glBindBufferARB (GL_ARRAY_BUFFER, 0); glDisableClientState (GL_VERTEX_ARRAY); glDisableClientState (GL_NORMAL_ARRAY); printMappingState ("After drawing"); err = glGetError (); if (err != GL_NO_ERROR) fprintf (stderr, "OpenGL error: %s\n", gluErrorString (err)); printf ("Frame %i finished...\n----------\n", frame); frame++; glutSwapBuffers (); glutPostRedisplay (); } static void keyPress (unsigned char key, int x, int y) { /* Escape */ if (key == 27) exit (0); glutPostRedisplay (); } int main (int argc, char *argv[]) { glutInit (&argc, argv); glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); glutInitWindowSize (640, 480); glutCreateWindow ("VBO demo"); init (); glutReshapeFunc (reshape); glutDisplayFunc (display); glutKeyboardFunc (keyPress); glutMainLoop (); return 0; }