#include "Sphere.h" #include #include #include #include #include #include Sphere::Sphere() { } Sphere::~Sphere() { } Sphere::Sphere(float rad, GLuint sl, GLuint st) : radius(rad), slices(sl), stacks(st) { nVerts = (slices + 1) * (stacks + 1); elements = (slices * 2 * (stacks - 1)) * 3; // Verts float * v = new float[3 * nVerts]; // Normals float * n = new float[3 * nVerts]; // Tex coords float * tex = new float[2 * nVerts]; //we don't use it now // Index unsigned int * el = new unsigned int[elements]; //index // Generate the vertex data generateVerts(v, n, tex, el); //create vao, vbo and ibo here... (We didn't use std::vector here...) glGenVertexArrays(1, &VAO); glBindVertexArray(VAO); glGenBuffers(1, &VBO_position); glBindBuffer(GL_ARRAY_BUFFER, VBO_position); glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * nVerts, v, GL_STATIC_DRAW); glVertexAttribPointer( 0, //attr number = 0 3, GL_FLOAT, GL_FALSE, 0, (void*)0); glEnableVertexAttribArray(0); //attr number = 0 glGenBuffers(1, &VBO_normal); glBindBuffer(GL_ARRAY_BUFFER, VBO_normal); glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * nVerts, n, GL_STATIC_DRAW); glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); glEnableVertexAttribArray(1); glGenBuffers(1, &VBO_tex); glBindBuffer(GL_ARRAY_BUFFER, VBO_tex); glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 2 * nVerts, tex, GL_STATIC_DRAW); glVertexAttribPointer( 2, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); glEnableVertexAttribArray(2); glGenBuffers(1, &IBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, elements * sizeof(GLuint), el, GL_STATIC_DRAW); glBindVertexArray(0); delete[] v; delete[] n; delete[] el; delete[] tex; } void Sphere::draw(ShaderProgram *shader, glm::mat4x4 proj_matrix, glm::mat4x4 view_matrix) { _model.glPushMatrix(); effectTransformations(); glBindVertexArray(VAO); glm::mat4 mvpMatrix = proj_matrix * view_matrix * _model.getMatrix(); glUniformMatrix4fv(shader->uniform("mvp"), 1, GL_FALSE, glm::value_ptr(mvpMatrix)); glm::mat4 modelview = view_matrix * _model.getMatrix(); glUniform4fv(shader->uniform("LightLocation"), 1, glm::value_ptr(view_matrix * glm::vec4(50, 50, 50, 1))); glUniformMatrix4fv(shader->uniform("ModelViewMatrix"), 1, GL_FALSE, glm::value_ptr(modelview)); glm::mat4 inverseModelView = glm::inverse(modelview); glm::mat3 normalMatrix = glm::mat3(glm::transpose(inverseModelView)); glUniformMatrix3fv(shader->uniform("NormalMatrix"), 1, GL_FALSE, glm::value_ptr(normalMatrix)); int size; glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &size); glDrawElements(GL_TRIANGLES, size / sizeof(GLuint), GL_UNSIGNED_INT, 0); _model.glPopMatrix(); } void Sphere::generateVerts(float * verts, float * norms, float * tex, unsigned int * el) { // Generate positions and normals GLfloat theta, phi; GLfloat thetaFac = glm::two_pi() / slices; GLfloat phiFac = glm::pi() / stacks; GLfloat nx, ny, nz, s, t; GLuint idx = 0, tIdx = 0; for (GLuint i = 0; i <= slices; i++) { theta = i * thetaFac; s = (GLfloat)i / slices; for (GLuint j = 0; j <= stacks; j++) { phi = j * phiFac; t = (GLfloat)j / stacks; nx = sinf(phi) * cosf(theta); ny = sinf(phi) * sinf(theta); nz = cosf(phi); verts[idx] = radius * nx; verts[idx + 1] = radius * ny; verts[idx + 2] = radius * nz; norms[idx] = nx; norms[idx + 1] = ny; norms[idx + 2] = nz; idx += 3; tex[tIdx] = s; tex[tIdx + 1] = t; tIdx += 2; } } // Generate the element list idx = 0; for (GLuint i = 0; i < slices; i++) { GLuint stackStart = i * (stacks + 1); GLuint nextStackStart = (i + 1) * (stacks + 1); for (GLuint j = 0; j < stacks; j++) { if (j == 0) { el[idx] = stackStart; el[idx + 1] = stackStart + 1; el[idx + 2] = nextStackStart + 1; idx += 3; } else if (j == stacks - 1) { el[idx] = stackStart + j; el[idx + 1] = stackStart + j + 1; el[idx + 2] = nextStackStart + j; idx += 3; } else { el[idx] = stackStart + j; el[idx + 1] = stackStart + j + 1; el[idx + 2] = nextStackStart + j + 1; el[idx + 3] = nextStackStart + j; el[idx + 4] = stackStart + j; el[idx + 5] = nextStackStart + j + 1; idx += 6; } } } } DrawableType Sphere::getType() { return DrawableType::SPHERE; } int Sphere::getVertexArrayHandle() { return this->VAO; }