/* * varray-cube.c * This program demonstrates vertex arrays for a cube. * Originally based on the redbook varray.c example. * $Id: varray-cube.c,v 1.12 2018/07/26 02:07:16 gl Exp gl $ */ #define DEBUG #define GL_GLEXT_PROTOTYPES #include #include #include #include #include #include #include enum RenderMode { IMMEDIATE_MODE = 0, VERTEX_ARRAY } renMode = VERTEX_ARRAY; enum DerefMethods { DRAWARRAYS = 0, ARRAYELEMENT, DRAWELEMENTS, DRAWELEMENTSALL, MULTIDRAWELEMENTS, NUMDEREFMETHODS } derefMethod = DRAWARRAYS; GLfloat vertices[] = { -1.0, -1.0, -1.0, // 0 1.0, -1.0, -1.0, // 1 1.0, 1.0, -1.0, // 2 -1.0, 1.0, -1.0, // 3 -1.0, -1.0, 1.0, // 4 1.0, -1.0, 1.0, // 5 1.0, 1.0, 1.0, // 6 -1.0, 1.0, 1.0 // 7 }; GLfloat colors[] = { 0.0, 0.0, 0.0, // 0 1.0, 0.0, 0.0, // 1 0.0, 1.0, 0.0, // 2 0.0, 0.0, 1.0, // 3 1.0, 1.0, 0.0, // 4 1.0, 0.0, 1.0, // 5 0.0, 1.0, 1.0, // 6 1.0, 1.0, 1.0, // 7 }; GLfloat verticesQuads[] = { // Front -1.0, -1.0, 1.0, // 4 1.0, -1.0, 1.0, // 5 1.0, 1.0, 1.0, // 6 -1.0, 1.0, 1.0, // 7 // Back -1.0, -1.0, -1.0, // 0 -1.0, 1.0, -1.0, // 3 1.0, 1.0, -1.0, // 2 1.0, -1.0, -1.0, // 1 // Left -1.0, -1.0, -1.0, // 0 -1.0, -1.0, 1.0, // 4 -1.0, 1.0, 1.0, // 7 -1.0, 1.0, -1.0, // 3 // Right 1.0, -1.0, -1.0, // 1 1.0, 1.0, -1.0, // 2 1.0, 1.0, 1.0, // 6 1.0, -1.0, 1.0, // 5 // Bottom -1.0, -1.0, -1.0, // 0 1.0, -1.0, -1.0, // 1 1.0, -1.0, 1.0, // 5 -1.0, -1.0, 1.0, // 4 // Top 1.0, 1.0, -1.0, // 2 -1.0, 1.0, -1.0, // 3 -1.0, 1.0, 1.0, // 7 1.0, 1.0, 1.0, // 6 }; GLfloat colorsQuads[] = { // Front 1.0, 1.0, 0.0, // 4 1.0, 0.0, 1.0, // 5 0.0, 1.0, 1.0, // 6 1.0, 1.0, 1.0, // 7 // Back 0.0, 0.0, 0.0, // 0 0.0, 0.0, 1.0, // 3 0.0, 1.0, 0.0, // 2 1.0, 0.0, 0.0, // 1 // Left 0.0, 0.0, 0.0, // 0 1.0, 1.0, 0.0, // 4 1.0, 1.0, 1.0, // 7 0.0, 0.0, 1.0, // 3 // Right 1.0, 0.0, 0.0, // 1 0.0, 1.0, 0.0, // 2 0.0, 1.0, 1.0, // 6 1.0, 0.0, 1.0, // 5 // Bottom 0.0, 0.0, 0.0, // 0 1.0, 0.0, 0.0, // 1 1.0, 0.0, 1.0, // 5 1.0, 1.0, 0.0, // 4 // Top 0.0, 1.0, 0.0, // 2 0.0, 0.0, 1.0, // 3 1.0, 1.0, 1.0, // 7 0.0, 1.0, 1.0, // 6 }; GLuint indices1DArray[] = { 4, 5, 6, 7, // Front 0, 3, 2, 1, // Back 0, 4, 7, 3, // Left 1, 2, 6, 5, // Right 0, 1, 5, 4, // Bottom 2, 3, 7, 6 // Top }; GLuint indices2DArray[][4] = { { 4, 5, 6, 7 }, // Front { 0, 3, 2, 1 }, // Back { 0, 4, 7, 3 }, // Left { 1, 2, 6, 5 }, // Right { 0, 1, 5, 4 }, // Bottom { 2, 3, 7, 6 } // Top }; GLuint frontIndices[] = { 4, 5, 6, 7 }; GLuint backIndices[] = { 0, 3, 2, 1 }; GLuint leftIndices[] = { 0, 4, 7, 3 }; GLuint rightIndices[] = { 1, 2, 6, 5 }; GLuint bottomIndices[] = { 0, 1, 5, 4 }; GLuint topIndices[] = { 2, 3, 7, 6 }; const GLvoid* indices1DArrayOfArray[] = { frontIndices, backIndices, leftIndices, rightIndices, bottomIndices, topIndices }; GLint indicesFirsts[] = { 0, 4, 8, 12, 16, 20 }; GLsizei indicesCounts[] = { 4, 4, 4, 4, 4, 4 }; GLsizei numQuads = 6; #define VERTICES 0 #define COLORS 1 #define INDICES 2 void enableVertexArrays(void) { glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_COLOR_ARRAY); } void disableVertexArrays(void) { glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_COLOR_ARRAY); } void init(void) { glClearColor(0.0, 0.0, 0.0, 0.0); glShadeModel(GL_FLAT); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); enableVertexArrays(); } /* Immediate mode, vertex at a time */ void renderCubeIM() { int i, j; glBegin(GL_QUADS); for (i = 0; i < numQuads; i++) for (j = 0; j < 4; j++) { glColor3fv(&colors[indices1DArray[i*4+j]*3]); glVertex3fv(&vertices[indices1DArray[i*4+j]*3]); } glEnd(); } /* Vertex array, whole arrays */ void renderCubeVA() { int i, j; /* Set array pointers */ if (derefMethod == DRAWARRAYS) { glVertexPointer(3, GL_FLOAT, 0, verticesQuads); glColorPointer(3, GL_FLOAT, 0, colorsQuads); } else { glVertexPointer(3, GL_FLOAT, 0, vertices); glColorPointer(3, GL_FLOAT, 0, colors); } /* Render cube using chosen dereferencing method */ switch (derefMethod) { case DRAWARRAYS: /* No indexing, i.e. elements. Vertex data repeated */ glDrawArrays(GL_QUADS, 0, 24); break; case ARRAYELEMENT: /* Single elements */ glBegin(GL_QUADS); for (i = 0; i < numQuads; i++) for (j = 0; j < 4; j++) /* Can also use indices1DArray, indices2DArray or indices1DArrayofArray */ glArrayElement(indices1DArray[i*4+j]); glEnd(); break; case DRAWELEMENTS: /* One list of elements per quad */ glDrawElements(GL_QUADS, 4, GL_UNSIGNED_INT, frontIndices); glDrawElements(GL_QUADS, 4, GL_UNSIGNED_INT, backIndices); glDrawElements(GL_QUADS, 4, GL_UNSIGNED_INT, leftIndices); glDrawElements(GL_QUADS, 4, GL_UNSIGNED_INT, rightIndices); glDrawElements(GL_QUADS, 4, GL_UNSIGNED_INT, bottomIndices); glDrawElements(GL_QUADS, 4, GL_UNSIGNED_INT, topIndices); #if 0 for (i = 0; i < numQuads; i++) /* Can also use indices1DArray, indices2DArray or indices1DArrayofArray */ glDrawElements(GL_QUADS, 4, GL_UNSIGNED_INT, indices1DArrayOfArray[i]); #endif break; case DRAWELEMENTSALL: /* One list of elements for all quads */ /* Can also use indices1DArray or indices2DArray but not indices1DArrayofArray */ glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, indices1DArray); break; case MULTIDRAWELEMENTS: /* One list of lists of elements for all quads */ /* Allows for faces/polygons of different numbers of vertices. No advantage for a cube where all faces as quads are same. */ glMultiDrawElements(GL_QUADS, indicesCounts, GL_UNSIGNED_INT, indices1DArrayOfArray, 6); } } void display(void) { GLenum error; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); #ifdef DEBUG printf("rendering mode: %d\n", renMode); if (renMode == VERTEX_ARRAY) printf("derefence method: %d\n", derefMethod); #endif glLoadIdentity(); /* Oblique view, scale cube */ glRotatef(15.0, 1.0, 0.0, 0.0); glRotatef(-30.0, 0.0, 1.0, 0.0); glScalef(0.5, 0.5, 0.5); if (renMode == IMMEDIATE_MODE) renderCubeIM(); else if (renMode == VERTEX_ARRAY) renderCubeVA(); if ((error = glGetError()) != GL_NO_ERROR) { printf("%s\n", gluErrorString(error)); } glutSwapBuffers(); } void reshape (int w, int h) { glViewport(0, 0, (GLsizei) w, (GLsizei) h); } void mouse (int button, int state, int x, int y) { switch (button) { case GLUT_RIGHT_BUTTON: if (state == GLUT_DOWN) { derefMethod++; if (derefMethod >= NUMDEREFMETHODS) derefMethod = 0; glutPostRedisplay(); } break; default: break; } } void keyboard(unsigned char key, int x, int y) { switch (key) { case 'l': glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glutPostRedisplay(); break; case 'f': glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glutPostRedisplay(); break; case 'c': glShadeModel(GL_FLAT); glutPostRedisplay(); break; case 's': glShadeModel(GL_SMOOTH); glutPostRedisplay(); break; case 'i': renMode = IMMEDIATE_MODE; break; case 'v': renMode = VERTEX_ARRAY; break; case 27: exit(0); break; } } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(350, 350); glutInitWindowPosition(100, 100); glutCreateWindow(argv[0]); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutMouseFunc(mouse); glutKeyboardFunc(keyboard); glutMainLoop(); return 0; }