diff --git a/CMakeLists.txt b/CMakeLists.txt index 6934676..9b8ce25 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,7 @@ add_executable(Fall-Fever Texture.cpp Camera.cpp Mesh.cpp + Model.cpp ) target_link_libraries( diff --git a/Controller.cpp b/Controller.cpp index 6aba4e4..e0ed82f 100644 --- a/Controller.cpp +++ b/Controller.cpp @@ -14,7 +14,8 @@ #include "Controller.h" #include "Texture.h" -#include "Mesh.h" +#include "Model.h" +//#include "Mesh.h" Controller::Controller() { if(!glfwInit()) exit(-1); @@ -81,12 +82,14 @@ void Controller::run() { 1, 2, 3 }; - std::vector textures { - new Texture("res/tex2.png", texture_diffuse), - new Texture("res/tex1.png", texture_diffuse) + std::vector textures { + Texture("res/textures/tex2.png", texture_diffuse), + Texture("res/textures/tex1.png", texture_diffuse) }; - Mesh mesh1(vertices, indices, textures); + Model model1("res/models/cube.obj"); + + //Mesh mesh1(vertices, indices, textures); glm::mat4 model = glm::mat4(1.0f); @@ -120,13 +123,14 @@ void Controller::run() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); for(int i=0;i<20;i++) { - mesh1.draw(&shaderProgram); - model = glm::translate(model, glm::vec3(0.0f, 0.0f, -1.0f)); + //mesh1.draw(&shaderProgram); + model1.draw(&shaderProgram); + //model = glm::translate(model, glm::vec3(0.0f, 0.0f, -1.0f)); camera->updateVPM(); glm::mat4 modelViewProj = camera->getViewProj() * model; shaderProgram.setUniform("u_modelViewProj", modelViewProj); } - model = glm::translate(model, glm::vec3(0.0f, 0.0f, 20.0f)); + //model = glm::translate(model, glm::vec3(0.0f, 0.0f, 20.0f)); glfwSwapBuffers(gameWindow->getGLFWwindow()); @@ -141,8 +145,6 @@ void Controller::run() { camera->updateDirectionFromMouseInput(gameEventHandler->getCursorDeltaX(), gameEventHandler->getCursorDeltaY()); } - delete textures[0]; - } void Controller::limit_framerate() { diff --git a/Mesh.cpp b/Mesh.cpp index c28a777..1e5ed3e 100644 --- a/Mesh.cpp +++ b/Mesh.cpp @@ -1,6 +1,6 @@ #include "Mesh.h" -Mesh::Mesh(std::vector vertices, std::vector indices, std::vector textures) +Mesh::Mesh(std::vector vertices, std::vector indices, std::vector textures) : vertices(vertices), indices(indices), textures(textures), @@ -17,9 +17,9 @@ void Mesh::draw(ShaderProgram *shaderProgram) { for(auto it = textures.begin(); it != textures.end(); it++) { int i = it - textures.begin(); - uint8_t currentTextureType = (*it)->getTextureType(); + uint8_t currentTextureType = (*it).getTextureType(); - (*it)->bind(i, shaderProgram, typeNumberCount[currentTextureType]); + (*it).bind(i, shaderProgram, typeNumberCount[currentTextureType]); typeNumberCount[currentTextureType] += 1; } @@ -31,7 +31,7 @@ void Mesh::draw(ShaderProgram *shaderProgram) { // Unbind all textures for(auto it = textures.begin(); it != textures.end(); it++) { - (**it).unbind(); + (*it).unbind(); } diff --git a/Mesh.h b/Mesh.h index c3506c4..9b40bde 100644 --- a/Mesh.h +++ b/Mesh.h @@ -11,7 +11,7 @@ class Mesh { public: - Mesh(std::vector vertices, std::vector indices, std::vector textures); + Mesh(std::vector vertices, std::vector indices, std::vector textures); ~Mesh() = default; void draw(ShaderProgram *shaderProgram); @@ -20,10 +20,9 @@ private: std::vector vertices; std::vector indices; - std::vector textures; + std::vector textures; VertexBuffer vertexBuffer; - //ShaderProgram *shaderProgram; void setupMesh(); diff --git a/Model.cpp b/Model.cpp new file mode 100644 index 0000000..493bc5d --- /dev/null +++ b/Model.cpp @@ -0,0 +1,128 @@ +#include "Model.h" + +#include + +Model::Model(const char* pathToModel) { + loadModel(pathToModel); +} + +void Model::draw(ShaderProgram *shaderProgram) { + + // Iterate through every mesh and call the draw function + for(auto it = meshes.begin(); it != meshes.end(); it++) { + it->draw(shaderProgram); + } + +} + +void Model::loadModel(std::string pathToModel) { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(pathToModel, aiProcess_Triangulate | aiProcess_FlipUVs); //aiProcess_OptimizeMeshes ? + + if(!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) { + std::cout << "ERROR::ASSIMP::" << importer.GetErrorString() << std::endl; + return; + } + + directory = pathToModel.substr(0, pathToModel.find_last_of('/')); + + processNode(scene->mRootNode, scene); +} + +void Model::processNode(aiNode *node, const aiScene *scene) { + + // Push the node's meshes into the mesh vector + for(uint i = 0; i < node->mNumMeshes; i++) { + aiMesh *mesh = scene->mMeshes[node->mMeshes[i]]; + meshes.push_back(processMesh(mesh, scene)); + } + + // Process child nodes too + for(uint i = 0; i < node->mNumChildren; i++) { + processNode(node->mChildren[i], scene); + } + +} + +Mesh Model::processMesh(aiMesh *mesh, const aiScene *scene) { + std::vector vertices; + std::vector indices; + std::vector textures; + + for(uint i = 0; i < mesh->mNumVertices; i++) { + Vertex vertex; + + // Position + glm::vec3 vector; + vector.x = mesh->mVertices[i].x; + vector.y = mesh->mVertices[i].y; + vector.z = mesh->mVertices[i].z; + vertex.position = vector; + + // Normals + vector.x = mesh->mNormals[i].x; + vector.y = mesh->mNormals[i].y; + vector.z = mesh->mNormals[i].z; + vertex.normalVec = vector; + + // Texture + if(mesh->mTextureCoords[0]) { + glm::vec2 vec; + vec.x = mesh->mTextureCoords[0][i].x; + vec.y = mesh->mTextureCoords[0][i].y; + vertex.textureCoords = vec; + } else { + vertex.textureCoords = glm::vec2(0.0f, 0.0f); + } + + vertices.push_back(vertex); + } + + // Indices + for(uint i = 0; i < mesh->mNumFaces; i++) { + aiFace face = mesh->mFaces[i]; + for(uint j = 0; j < face.mNumIndices; j++) { + indices.push_back(face.mIndices[j]); + } + } + + // Material + if(mesh->mMaterialIndex >= 0) { + aiMaterial *material = scene->mMaterials[mesh->mMaterialIndex]; + std::vector diffuseMaps = loadMaterialTextures(material, aiTextureType_DIFFUSE, texture_diffuse); + textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end()); + + std::vector specularMaps = loadMaterialTextures(material, aiTextureType_SPECULAR, texture_specular); + textures.insert(textures.end(), specularMaps.begin(), specularMaps.end()); + } + + return Mesh(vertices, indices, textures); +} + +std::vector Model::loadMaterialTextures(aiMaterial *mat, aiTextureType type, uint8_t textureType) { + + std::vector textures; + for(uint i = 0; i < mat->GetTextureCount(type); i++) { + aiString filename; + mat->GetTexture(type, i, &filename); + + bool skip = 0; + for(uint j = 0; j < loadedTextures.size(); j++) { + if(std::strcmp(loadedTextures[j].getPath().data(), filename.C_Str()) == 0) { + textures.push_back(loadedTextures[j]); + skip = 1; + break; + } + } + + if(!skip) { + std::string path = directory + '/' + filename.C_Str(); + Texture texture(path.c_str(), textureType); + textures.push_back(texture); + } + } + + loadedTextures.clear(); + + return textures; +} diff --git a/Model.h b/Model.h new file mode 100644 index 0000000..75fd4ef --- /dev/null +++ b/Model.h @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include + +#include + +#include "Mesh.h" + +class Model { + +public: + + Model(const char* pathToModel); + ~Model() = default; + + void draw(ShaderProgram *shaderProgram); + + +private: + + void loadModel(std::string pathToModel); + + void processNode(aiNode *node, const aiScene *scene); + Mesh processMesh(aiMesh *mesh, const aiScene *scene); + + std::vector loadMaterialTextures(aiMaterial *mat, aiTextureType type, uint8_t textureType); + + + std::vector meshes; + + std::vector loadedTextures; + + void textureFromFile(aiMaterial *mat, aiTextureType type); + + std::string directory; +}; \ No newline at end of file diff --git a/Texture.cpp b/Texture.cpp index f2288f0..0c4b6cb 100644 --- a/Texture.cpp +++ b/Texture.cpp @@ -41,7 +41,7 @@ Texture::Texture(const char* texturePath, uint8_t textureType) { } Texture::~Texture() { - glDeleteTextures(1, &textureId); + //glDeleteTextures(1, &textureId); } void Texture::bind(uint8_t textureUnit, ShaderProgram* shaderProgram, uint8_t textureTypeNum) { @@ -63,6 +63,9 @@ void Texture::bind(uint8_t textureUnit, ShaderProgram* shaderProgram, uint8_t te break; } + // Add material. as we store textures in a struct + uniformName = "material." + uniformName; + shaderProgram->setUniform(uniformName.c_str(), textureTypeNum); glActiveTexture(GL_TEXTURE0 + textureUnit); diff --git a/Texture.h b/Texture.h index 1df0f93..556abac 100644 --- a/Texture.h +++ b/Texture.h @@ -19,6 +19,7 @@ public: void unbind(); uint8_t getTextureType() { return textureType; } + std::string getPath() { return texturePath; } private: diff --git a/res/shaders/basic.fs b/res/shaders/basic.fs index 8ae3cfa..bd518c3 100644 --- a/res/shaders/basic.fs +++ b/res/shaders/basic.fs @@ -1,18 +1,22 @@ #version 330 core +struct Material { + sampler2D u_texture_diffuse0; + sampler2D u_texture_diffuse1; +}; + layout(location = 0) out vec4 f_color; in vec4 v_color; in vec2 v_texCoord; -uniform sampler2D u_texture_diffuse0; -uniform sampler2D u_texture_diffuse1; +uniform Material material; uniform float mix_val; void main() { //f_color = v_color; - vec4 texColor1 = texture(u_texture_diffuse0, v_texCoord); - vec4 texColor2 = texture(u_texture_diffuse1, v_texCoord); + vec4 texColor1 = texture(material.u_texture_diffuse0, v_texCoord); + vec4 texColor2 = texture(material.u_texture_diffuse1, v_texCoord); f_color = mix(texColor1, texColor2, mix_val); } diff --git a/res/tex1.png b/res/textures/tex1.png similarity index 100% rename from res/tex1.png rename to res/textures/tex1.png diff --git a/res/tex2.png b/res/textures/tex2.png similarity index 100% rename from res/tex2.png rename to res/textures/tex2.png