#include "../nclgl/Mesh.h" Mesh::Mesh(void) { glGenVertexArrays(1, &arrayObject); for (int i = 0; i < MAX_BUFFER; ++i) { bufferObject[i] = 0; } numVertices = 0; type = GL_TRIANGLES; numIndices = 0; vertices = NULL; textureCoords = NULL; normals = NULL; tangents = NULL; indices = NULL; colours = NULL; texture = 0; bumpTexture = 0; } Mesh ::~Mesh(void) { glDeleteVertexArrays(1, &arrayObject); glDeleteBuffers(MAX_BUFFER, bufferObject); delete[] vertices; delete[] colours; glDeleteTextures(1, &texture); delete[] textureCoords; delete[] indices; delete[] normals; delete[] tangents; glDeleteTextures(1, &bumpTexture); } void Mesh::Draw() { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, bumpTexture); glBindVertexArray(arrayObject); if (bufferObject[INDEX_BUFFER]) { glDrawElements(type, numIndices, GL_UNSIGNED_INT, 0); } else { glDrawArrays(type, 0, numVertices); } glBindVertexArray(0); } //Added to load cube Mesh* Mesh::loadMeshFile(const string& filename) { ifstream f(filename); if (!f) { return NULL; } Mesh*m = new Mesh(); f >> m->numVertices; int hasTex = 0; int hasColour = 0; f >> hasTex; f >> hasColour; m->vertices = new Vector3[m->numVertices]; if (hasTex) { m->textureCoords = new Vector2[m->numVertices]; m->colours = new Vector4[m->numVertices]; } for (unsigned int i = 0; i < m->numVertices; ++i) { f >> m->vertices[i].x; f >> m->vertices[i].y; f >> m->vertices[i].z; } if (hasColour) { for (unsigned int i = 0; i < m->numVertices; ++i) { unsigned char r, g, b, a; f >> r; f >> g; f >> b; f >> a; //OpenGL can use floats for colours directly - this will take up 4x as //much space, but could avoid any byte / float conversions happening //behind the scenes in our shader executions m->colours[i] = Vector4(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f); } } if (hasTex) { for (unsigned int i = 0; i < m->numVertices; ++i) { f >> m->textureCoords[i].x; f >> m->textureCoords[i].y; } } m->BufferData(); return m; } Mesh * Mesh::GenerateTriangle() { Mesh *m = new Mesh(); m->numVertices = 3; m->vertices = new Vector3[m->numVertices]; m->vertices[0] = Vector3(0.0f, 0.5f, 0.0f); m->vertices[1] = Vector3(0.5f, -0.5f, 0.0f); m->vertices[2] = Vector3(-0.5f, -0.5f, 0.0f); m->textureCoords = new Vector2[m->numVertices]; m->textureCoords[0] = Vector2(0.5f, 0.0f); m->textureCoords[1] = Vector2(1.0f, 1.0f); m->textureCoords[2] = Vector2(0.0f, 1.0f); m->colours = new Vector4[m->numVertices]; m->colours[0] = Vector4(1.0f, 0.0f, 0.0f, 1.0f); m->colours[1] = Vector4(0.0f, 1.0f, 0.0f, 1.0f); m->colours[2] = Vector4(0.0f, 0.0f, 1.0f, 1.0f); m->BufferData(); return m; } Mesh * Mesh::GenerateTrianglePyramid() { Mesh *m = new Mesh(); m->numVertices = 12; //m->type = GL_TRIANGLES; // GL_TRIAMNGLE_STRIP m->type = GL_TRIANGLE_STRIP; m->vertices = new Vector3[m->numVertices]; // Front m->vertices[0] = Vector3(0.0f, 1.0f, 0.0f); m->vertices[1] = Vector3(-1.0f, -1.0f, 1.0f); m->vertices[2] = Vector3(1.0f, -1.0f, 1.0f); // Right m->vertices[3] = Vector3(0.0f, 1.0f, 0.0f); m->vertices[4] = Vector3(1.0f, -1.0f, 1.0f); m->vertices[5] = Vector3(1.0f, -1.0f, -1.0f); // Back m->vertices[1] = Vector3(0.0f, 1.0f, 0.0f); m->vertices[7] = Vector3(1.0f, -1.0f, -1.0f); m->vertices[8] = Vector3(-1.0f, -1.0f, -1.0f); // Left m->vertices[9] = Vector3(0.0f, 1.0f, 0.0f); m->vertices[10] = Vector3(-1.0f, -1.0f, -1.0f); m->vertices[11] = Vector3(-1.0f, -1.0f, 1.0f); // m->textureCoords = new Vector2[m->numVertices]; m->textureCoords[0] = Vector2(0.5f, 0.0f); m->textureCoords[1] = Vector2(1.0f, 1.0f); m->textureCoords[2] = Vector2(0.0f, 1.0f); m->textureCoords[3] = Vector2(0.5f, 0.0f); m->textureCoords[4] = Vector2(1.0f, 1.0f); m->textureCoords[5] = Vector2(0.0f, 1.0f); m->textureCoords[6] = Vector2(0.5f, 0.0f); m->textureCoords[7] = Vector2(1.0f, 1.0f); m->textureCoords[8] = Vector2(0.0f, 1.0f); m->textureCoords[9] = Vector2(0.5f, 0.0f); m->textureCoords[10] = Vector2(1.0f, 1.0f); m->textureCoords[11] = Vector2(0.0f, 1.0f); // m->colours = new Vector4[m->numVertices]; m->colours[0] = Vector4(0.0f, 1.0f, 0.0f, 1.0f); m->colours[1] = Vector4(1.0f, 0.5f, 0.0f, 1.0f); m->colours[2] = Vector4(1.0f, 0.0f, 0.0f, 1.0f); m->colours[3] = Vector4(1.0f, 1.0f, 0.0f, 1.0f); m->colours[4] = Vector4(0.0f, 0.0f, 1.0f, 1.0f); m->colours[5] = Vector4(1.0f, 0.0f, 1.0f, 1.0f); m->colours[6] = Vector4(1.0f, 1.0f, 0.0f, 1.0f); m->colours[7] = Vector4(0.0f, 0.0f, 1.0f, 1.0f); m->colours[8] = Vector4(1.0f, 0.0f, 1.0f, 1.0f); m->colours[9] = Vector4(1.0f, 1.0f, 0.0f, 1.0f); m->colours[10] = Vector4(0.0f, 0.0f, 1.0f, 1.0f); m->colours[11] = Vector4(1.0f, 0.0f, 1.0f, 1.0f); //m->GenerateNormals(); //m->GenerateTangents(); m->BufferData(); return m; } Mesh * Mesh::GenerateQuadCube() { Mesh * m = new Mesh(); m->numVertices = 36; m->type = GL_TRIANGLE_STRIP; m->vertices = new Vector3[m->numVertices]; m->textureCoords = new Vector2[m->numVertices]; m->colours = new Vector4[m->numVertices]; m->vertices[0] = Vector3(1, 1, -1); m->vertices[1] = Vector3(1, -1, -1); m->vertices[2] = Vector3(-1, -1, -1); m->vertices[3] = Vector3(-1, -1, -1); m->vertices[4] = Vector3(-1, 1, -1); m->vertices[5] = Vector3(1, 1, -1); m->vertices[6] = Vector3(-1, 1, -1); m->vertices[7] = Vector3(-1, -1, -1); m->vertices[8] = Vector3(-1, -1, 1); m->vertices[9] = Vector3(-1, -1, 1); m->vertices[10] = Vector3(-1, 1, 1); m->vertices[11] = Vector3(-1, 1, -1); m->vertices[12] = Vector3(-1, 1, 1); m->vertices[13] = Vector3(-1, -1, 1); m->vertices[14] = Vector3(1, -1, 1); m->vertices[15] = Vector3(1, -1, 1); m->vertices[16] = Vector3(1, 1, 1); m->vertices[17] = Vector3(-1, 1, 1); m->vertices[18] = Vector3(1, 1, 1); m->vertices[19] = Vector3(1, -1, 1); m->vertices[20] = Vector3(1, -1, -1); m->vertices[21] = Vector3(1, -1, -1); m->vertices[22] = Vector3(1, 1, -1); m->vertices[23] = Vector3(1, 1, 1); m->vertices[24] = Vector3(1, 1, 1); m->vertices[25] = Vector3(1, 1, -1); m->vertices[26] = Vector3(-1, 1, -1); m->vertices[27] = Vector3(-1, 1, -1); m->vertices[28] = Vector3(-1, 1, 1); m->vertices[29] = Vector3(1, 1, 1); m->vertices[30] = Vector3(1, -1, -1); m->vertices[31] = Vector3(1, -1, 1); m->vertices[32] = Vector3(-1, -1, 1); m->vertices[33] = Vector3(-1, -1, 1); m->vertices[34] = Vector3(-1, -1, -1); m->vertices[35] = Vector3(1, -1, -1); m->textureCoords[0] = Vector2(0, 0); m->textureCoords[1] = Vector2(0, 1); m->textureCoords[2] = Vector2(1, 1); m->textureCoords[3] = Vector2(1, 1); m->textureCoords[4] = Vector2(1, 0); m->textureCoords[5] = Vector2(0, 0); m->textureCoords[6] = Vector2(0, 0); m->textureCoords[7] = Vector2(0, 1); m->textureCoords[8] = Vector2(1, 1); m->textureCoords[9] = Vector2(1, 1); m->textureCoords[10] = Vector2(1, 0); m->textureCoords[11] = Vector2(0, 0); m->textureCoords[12] = Vector2(0, 0); m->textureCoords[13] = Vector2(0, 1); m->textureCoords[14] = Vector2(1, 1); m->textureCoords[15] = Vector2(1, 1); m->textureCoords[16] = Vector2(1, 0); m->textureCoords[17] = Vector2(0, 0); m->textureCoords[18] = Vector2(0, 0); m->textureCoords[19] = Vector2(0, 1); m->textureCoords[20] = Vector2(1, 1); m->textureCoords[21] = Vector2(1, 1); m->textureCoords[22] = Vector2(1, 0); m->textureCoords[23] = Vector2(0, 0); m->textureCoords[24] = Vector2(0, 0); m->textureCoords[25] = Vector2(0, 1); m->textureCoords[26] = Vector2(1, 1); m->textureCoords[27] = Vector2(1, 1); m->textureCoords[28] = Vector2(1, 0); m->textureCoords[29] = Vector2(0, 0); m->textureCoords[30] = Vector2(0, 0); m->textureCoords[31] = Vector2(0, 1); m->textureCoords[32] = Vector2(1, 1); m->textureCoords[33] = Vector2(1, 1); m->textureCoords[34] = Vector2(1, 0); m->textureCoords[35] = Vector2(0, 0); for (int i = 0; i < 36; ++i) { m->colours[i] = Vector4(1.0f, 1.0f, 1.0f, 1.0f); } //m->GenerateNormals(); //m->GenerateTangents(); m->BufferData(); return m; } void Mesh::BufferData() { glBindVertexArray(arrayObject); glGenBuffers(1, &bufferObject[VERTEX_BUFFER]); glBindBuffer(GL_ARRAY_BUFFER, bufferObject[VERTEX_BUFFER]); glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(Vector3), vertices, GL_STATIC_DRAW); glVertexAttribPointer(VERTEX_BUFFER, 3, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(VERTEX_BUFFER); if (textureCoords) { glGenBuffers(1, &bufferObject[TEXTURE_BUFFER]); glBindBuffer(GL_ARRAY_BUFFER, bufferObject[TEXTURE_BUFFER]); glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(Vector2), textureCoords, GL_STATIC_DRAW); glVertexAttribPointer(TEXTURE_BUFFER, 2, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(TEXTURE_BUFFER); } if (colours) { glGenBuffers(1, &bufferObject[COLOUR_BUFFER]); glBindBuffer(GL_ARRAY_BUFFER, bufferObject[COLOUR_BUFFER]); glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(Vector4), colours, GL_STATIC_DRAW); glVertexAttribPointer(COLOUR_BUFFER, 4, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(COLOUR_BUFFER); } if (indices) { glGenBuffers(1, &bufferObject[INDEX_BUFFER]); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferObject[INDEX_BUFFER]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices * sizeof(GLuint), indices, GL_STATIC_DRAW); } if (normals) { glGenBuffers(1, &bufferObject[NORMAL_BUFFER]); glBindBuffer(GL_ARRAY_BUFFER, bufferObject[NORMAL_BUFFER]); glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(Vector3), normals, GL_STATIC_DRAW); glVertexAttribPointer(NORMAL_BUFFER, 3, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(NORMAL_BUFFER); } if (tangents) { glGenBuffers(1, &bufferObject[TANGENT_BUFFER]); glBindBuffer(GL_ARRAY_BUFFER, bufferObject[TANGENT_BUFFER]); glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(Vector3), tangents, GL_STATIC_DRAW); glVertexAttribPointer(TANGENT_BUFFER, 3, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(TANGENT_BUFFER); } glBindVertexArray(0); } Mesh * Mesh::GenerateQuad() { Mesh * m = new Mesh(); m->numVertices = 4; m->type = GL_TRIANGLE_STRIP; m->vertices = new Vector3[m->numVertices]; m->textureCoords = new Vector2[m->numVertices]; m->colours = new Vector4[m->numVertices]; m->vertices[0] = Vector3(-1.0f, -1.0f, 0.0f); m->vertices[1] = Vector3(-1.0f, 1.0f, 0.0f); m->vertices[2] = Vector3(1.0f, -1.0f, 0.0f); m->vertices[3] = Vector3(1.0f, 1.0f, 0.0f); m->textureCoords[0] = Vector2(0.0f, 1.0f); m->textureCoords[1] = Vector2(0.0f, 0.0f); m->textureCoords[2] = Vector2(1.0f, 1.0f); m->textureCoords[3] = Vector2(1.0f, 0.0f); for (int i = 0; i < 4; ++i) { m->colours[i] = Vector4(1.0f, 1.0f, 1.0f, 1.0f); } m->BufferData(); return m; } void Mesh::GenerateNormals() { if (!normals) { normals = new Vector3[numVertices]; } for (GLuint i = 0; i < numVertices; ++i) { normals[i] = Vector3(); } if (indices) { for (GLuint i = 0; i < numIndices; i += 3) { unsigned int a = indices[i]; unsigned int b = indices[i + 1]; unsigned int c = indices[i + 2]; Vector3 normal = Vector3::Cross((vertices[b] - vertices[a]), (vertices[c] - vertices[a])); normals[a] += normal; normals[b] += normal; normals[c] += normal; } } else { for (GLuint i = 0; i < numVertices; i += 3) { Vector3 &a = vertices[i]; Vector3 &b = vertices[i + 1]; Vector3 &c = vertices[i + 2]; Vector3 normal = Vector3::Cross(b - a, c - a); normals[i] = normal; normals[i + 1] = normal; normals[i + 2] = normal; } } for (GLuint i = 0; i < numVertices; ++i) { normals[i].Normalise(); } } void Mesh::GenerateTangents() { if (!tangents) { tangents = new Vector3[numVertices]; } if(indices) { for (GLuint i = 0; i < numIndices; i += 3) { int a = indices[i]; int b = indices[i + 1]; int c = indices[i + 2]; Vector3 tangent = GenerateTangent(vertices[a], vertices[b], vertices[c], textureCoords[a], textureCoords[b], textureCoords[c]); tangents[a] += tangent; tangents[b] += tangent; tangents[c] += tangent; } } else { for (GLuint i = 0; i < numVertices; i += 3) { Vector3 tangent = GenerateTangent(vertices[i], vertices[i + 1], vertices[i + 2], textureCoords[i], textureCoords[i + 1], textureCoords[i + 2]); tangents[i] += tangent; tangents[i + 1] += tangent; tangents[i + 2] += tangent; } } for (GLuint i = 0; i < numVertices; ++i) { tangents[i].Normalise(); } } Vector3 Mesh::GenerateTangent(const Vector3 &a, const Vector3 &b, const Vector3 &c, const Vector2 &ta, const Vector2 &tb, const Vector2 &tc) { Vector2 coord1 = tb - ta; Vector2 coord2 = tc - ta; Vector3 vertex1 = b - a; Vector3 vertex2 = c - a; Vector3 axis = Vector3(vertex1*coord2.y - vertex2*coord1.y); float factor = 1.0f / (coord1.x * coord2.y - coord2.x * coord1.y); return axis * factor; }