#include "Objects.h" Objects::Objects() { vao = 0; vertexbuffer = 0; indexbuffer = 0; vertexarray = NULL; indexarray = NULL; nverts = 0; ntris = 0; } /* Destructor: clean up allocated data in a Objects object */ Objects::~Objects() { clean(); }; void Objects::clean() { if (glIsVertexArray(vao)) { glDeleteVertexArrays(1, &vao); } vao = 0; if (glIsBuffer(vertexbuffer)) { glDeleteBuffers(1, &vertexbuffer); } vertexbuffer = 0; if (glIsBuffer(indexbuffer)) { glDeleteBuffers(1, &indexbuffer); } indexbuffer = 0; if (vertexarray) { delete[] vertexarray; vertexarray = NULL; } if (indexarray) { delete[] indexarray; indexarray = NULL; } nverts = 0; ntris = 0; } /* Create a demo object with a single triangle */ void Objects::createTriangle() { // Constant data arrays for this simple test. // Note, however, that they need to be copied to dynamic arrays // in the class. These local variables are not persistent. // // The data array contains 8 floats per vertex: // coordinate xyz, normal xyz, texcoords st const GLfloat vertex_array_data[] = { -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // Vertex 0 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, // Vertex 1 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.5f, 1.0f // Vertex 2 }; const GLuint index_array_data[] = { 0, 1, 2 }; nverts = 3; ntris = 1; vertexarray = new GLfloat[8 * nverts]; indexarray = new GLuint[3 * ntris]; for (int i = 0; i<8 * nverts; i++) { vertexarray[i] = vertex_array_data[i]; } for (int i = 0; i<3 * ntris; i++) { indexarray[i] = index_array_data[i]; } // Generate one vertex array object (VAO) and bind it glGenVertexArrays(1, &(vao)); glBindVertexArray(vao); // Generate two buffer IDs glGenBuffers(1, &vertexbuffer); glGenBuffers(1, &indexbuffer); // Activate the vertex buffer glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); // Present our vertex coordinates to OpenGL glBufferData(GL_ARRAY_BUFFER, 8 * nverts * sizeof(GLfloat), vertexarray, GL_STATIC_DRAW); // Specify how many attribute arrays we have in our VAO glEnableVertexAttribArray(0); // Vertex coordinates glEnableVertexAttribArray(1); // Normals glEnableVertexAttribArray(2); // Texture coordinates // Specify how OpenGL should interpret the vertex buffer data: // Attributes 0, 1, 2 (must match the lines above and the layout in the shader) // Number of dimensions (3 means vec3 in the shader, 2 means vec2) // Type GL_FLOAT // Not normalized (GL_FALSE) // Stride 8 floats (interleaved array with 8 floats per vertex) // Array buffer offset 0, 3 or 6 floats (offset into first vertex) glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)0); // xyz coordinates glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat))); // normals glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(6 * sizeof(GLfloat))); // texcoords // Activate the index buffer glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexbuffer); // Present our vertex indices to OpenGL glBufferData(GL_ELEMENT_ARRAY_BUFFER, 3 * ntris*sizeof(GLuint), indexarray, GL_STATIC_DRAW); // Deactivate (unbind) the VAO and the buffers again. // Do NOT unbind the index buffer while the VAO is still bound. // The index buffer is an essential part of the VAO state. glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); }; /* Create a simple box geometry */ /* TODO: Split to 24 vertices, get the normals and texcoords right. */ void Objects::createBox(float xsize, float ysize, float zsize) { // The data array contains 8 floats per vertex: // coordinate xyz, normal xyz, texcoords st const GLfloat vertex_array_data[] = { -xsize, -ysize, -zsize, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // Vertex 0 xsize, -ysize, -zsize, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // Vertex 1 -xsize, ysize, -zsize, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // Vertex 2 xsize, ysize, -zsize, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // Vertex 3 -xsize, -ysize, zsize, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // Vertex 0 xsize, -ysize, zsize, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // Vertex 1 -xsize, ysize, zsize, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // Vertex 2 xsize, ysize, zsize, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f // Vertex 3 }; const GLuint index_array_data[] = { 0, 3, 1, 0, 2, 3, 1, 4, 0, 1, 5, 4, 4, 2, 0, 4, 6, 2, 1, 3, 7, 1, 7, 5, 7, 2, 6, 7, 3, 2, 4, 5, 7, 4, 7, 6 }; nverts = 8; ntris = 12; vertexarray = new GLfloat[8 * nverts]; indexarray = new GLuint[3 * ntris]; for (int i = 0; i<8 * nverts; i++) { vertexarray[i] = vertex_array_data[i]; } for (int i = 0; i<3 * ntris; i++) { indexarray[i] = index_array_data[i]; } // Generate one vertex array object (VAO) and bind it glGenVertexArrays(1, &(vao)); glBindVertexArray(vao); // Generate two buffer IDs glGenBuffers(1, &vertexbuffer); glGenBuffers(1, &indexbuffer); // Activate the vertex buffer glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); // Present our vertex coordinates to OpenGL glBufferData(GL_ARRAY_BUFFER, 8 * nverts * sizeof(GLfloat), vertexarray, GL_STATIC_DRAW); // Specify how many attribute arrays we have in our VAO glEnableVertexAttribArray(0); // Vertex coordinates glEnableVertexAttribArray(1); // Normals glEnableVertexAttribArray(2); // Texture coordinates // Specify how OpenGL should interpret the vertex buffer data: // Attributes 0, 1, 2 (must match the lines above and the layout in the shader) // Number of dimensions (3 means vec3 in the shader, 2 means vec2) // Type GL_FLOAT // Not normalized (GL_FALSE) // Stride 8 floats (interleaved array with 8 floats per vertex) // Array buffer offset 0, 3 or 6 floats (offset into first vertex) glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)0); // xyz coordinates glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat))); // normals glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(6 * sizeof(GLfloat))); // texcoords // Activate the index buffer glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexbuffer); // Present our vertex indices to OpenGL glBufferData(GL_ELEMENT_ARRAY_BUFFER, 3 * ntris*sizeof(GLuint), indexarray, GL_STATIC_DRAW); // Deactivate (unbind) the VAO and the buffers again. // Do NOT unbind the index buffer while the VAO is still bound. // The index buffer is an essential part of the VAO state. glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); }; /* * createSphere(float radius, int segments) * * Create a Objects objectwith vertex and index arrays * to draw a textured sphere with normals. * Increasing the parameter 'segments' yields more triangles. * The vertex array is on interleaved format. For each vertex, there * are 8 floats: three for the vertex coordinates (x, y, z), three * for the normal vector (n_x, n_y, n_z) and finally two for texture * coordinates (s, t). The arrays are allocated by malloc() inside the * function and should be disposed of using free() when they are no longer * needed, e.g with the function soupDelete(). * * Author: Stefan Gustavson (stegu@itn.liu.se) 2014. * This code is in the public domain. */ void Objects::createSphere(float radius, int segments) { int i, j, base, i0; float x, y, z, R; double theta, phi; int vsegs, hsegs; int stride = 8; // Delete any previous content in the Objects object clean(); vsegs = segments; if (vsegs < 2) vsegs = 2; hsegs = vsegs * 2; nverts = 1 + (vsegs - 1) * (hsegs + 1) + 1; // top + middle + bottom ntris = hsegs + (vsegs - 2) * hsegs * 2 + hsegs; // top + middle + bottom vertexarray = new float[nverts * 8]; indexarray = new GLuint[ntris * 3]; // The vertex array: 3D xyz, 3D normal, 2D st (8 floats per vertex) // First vertex: top pole (+z is "up" in object local coords) vertexarray[0] = 0.0f; vertexarray[1] = 0.0f; vertexarray[2] = radius; vertexarray[3] = 0.0f; vertexarray[4] = 0.0f; vertexarray[5] = 1.0f; vertexarray[6] = 0.5f; vertexarray[7] = 1.0f; // Last vertex: bottom pole base = (nverts - 1)*stride; vertexarray[base] = 0.0f; vertexarray[base + 1] = 0.0f; vertexarray[base + 2] = -radius; vertexarray[base + 3] = 0.0f; vertexarray[base + 4] = 0.0f; vertexarray[base + 5] = -1.0f; vertexarray[base + 6] = 0.5f; vertexarray[base + 7] = 0.0f; // All other vertices: // vsegs-1 latitude rings of hsegs+1 vertices each // (duplicates at texture seam s=0 / s=1) #ifndef M_PI #define M_PI 3.1415926536 #endif // M_PI for (j = 0; jxmax) xmax = x; if (yymax) ymax = y; if (zzmax) zmax = z; } printf("xmin: %8.2f\n", xmin); printf("xmax: %8.2f\n", xmax); printf("ymin: %8.2f\n", ymin); printf("ymax: %8.2f\n", ymax); printf("zmin: %8.2f\n", zmin); printf("zmax: %8.2f\n", zmax); }; /* Render the geometry in a Objects object */ void Objects::render() { glBindVertexArray(vao); glDrawElements(GL_TRIANGLES, 3 * ntris, GL_UNSIGNED_INT, (void*)0); // (mode, vertex count, type, element array buffer offset) glBindVertexArray(0); }; /* * private * printError() - Signal an error. * Simple printf() to console for portability. */ void Objects::printError(const char *errtype, const char *errmsg) { fprintf(stderr, "%s: %s\n", errtype, errmsg); };