#include #include "TriangleSoup.hpp" /* Constructor: initialize a TriangleSoup object to all zeros */ TriangleSoup::TriangleSoup() { vao = 0; vertexbuffer = 0; indexbuffer = 0; vertexarray = NULL; indexarray = NULL; nverts = 0; ntris = 0; } /* Destructor: clean up allocated data in a TriangleSoup object */ TriangleSoup::~TriangleSoup() { clean(); }; void TriangleSoup::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 TriangleSoup::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 TriangleSoup::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 TriangleSoup 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 TriangleSoup::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 TriangleSoup 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 TriangleSoup object */ void TriangleSoup::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 TriangleSoup::printError(const char *errtype, const char *errmsg) { fprintf(stderr, "%s: %s\n", errtype, errmsg); };