CSC3224_Computer_Games_Development / nclgl / Mesh.cpp
Mesh.cpp
Raw
#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;
}