From 708b6e523d7f57f4eb4eb8395530be9ddf67986a Mon Sep 17 00:00:00 2001 From: talha Date: Thu, 25 Apr 2024 03:19:05 +0500 Subject: Added freetype, started refactoring --- source/main.cpp | 704 +++++++++-------------------------- source/model.h | 370 ++++++++++++++++++ source/shaders/textured_quad.fs.glsl | 9 + source/shaders/textured_quad.vs.glsl | 14 + 4 files changed, 560 insertions(+), 537 deletions(-) create mode 100644 source/model.h create mode 100644 source/shaders/textured_quad.fs.glsl create mode 100644 source/shaders/textured_quad.vs.glsl (limited to 'source') diff --git a/source/main.cpp b/source/main.cpp index a9e5c81..7deb893 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -2,14 +2,14 @@ #include #include #include -#include -#include -#include #include #define STB_IMAGE_IMPLEMENTATION #include "stb_image.h" +#include +#include FT_FREETYPE_H + /* @lookup: * - understand kernals, how they work and how they affect post processing * - Check to see why it is necessary to do glBindTexture() @@ -50,6 +50,31 @@ typedef u8 b8; // =========== Shader Loading ============= +enum Texture_Filtering { TF_NEAREST, TF_LINEAR }; + +struct GlTexturedQuad { + u32 vao; + u32 vbo; + u32 texture_id; +}; + +struct GlShader { + u32 id; + s32 model_loc; + s32 view_loc; + s32 proj_loc; +}; + +void gl_shader_load_locations(GlShader *shader) +{ + glUseProgram(shader->id); + shader->model_loc = glGetUniformLocation(shader->id, "Model"); + shader->view_loc = glGetUniformLocation(shader->id, "View"); + shader->proj_loc = glGetUniformLocation(shader->id, "Projection"); + + return; +} + unsigned int gl_create_vertex_shader(char* vertex_shader_source) { unsigned int vertex_shader = glCreateShader(GL_VERTEX_SHADER); @@ -121,36 +146,25 @@ unsigned int gl_shader_program(char* vertex_shader_source, char* fragment_shader return shader_program; } -Mat4 camera_create4m(Vec3 camera_pos, Vec3 camera_look, Vec3 camera_up) +u32 gl_shader_program_from_path(char* vs_path, char* fs_path) { - // @note: We do this because this allows the camera to have the axis it looks at - // inwards be the +z axis. - // If we did not do this, then the inward axis the camera looks at would be negative. - // I am still learning from learnopengl.com but I imagine that this was done for conveniences' sake. - Vec3 camera_forward_dir = normalize3v(subtract3v(camera_pos, camera_look)); - Vec3 camera_right_dir = normalize3v(cross_multiply3v(camera_up, camera_forward_dir)); - Vec3 camera_up_dir = normalize3v(cross_multiply3v(camera_forward_dir, camera_right_dir)); - - Mat4 res = lookat4m(camera_up_dir, camera_forward_dir, camera_right_dir, camera_pos); - - return res; -} + // @todo: add failure handling here + // what to do if we fail to read the shaders + size_t read_count; + char* vs = (char*)SDL_LoadFile(vs_path, &read_count); + char* fs = (char*)SDL_LoadFile(fs_path, &read_count); -Vec3 camera_look_around(r32 angle_pitch, r32 angle_yaw) -{ - Vec3 camera_look = {0.0}; - camera_look.x = cosf(angle_yaw) * cosf(angle_pitch); - camera_look.y = sinf(angle_pitch); - camera_look.z = sinf(angle_yaw) * cosf(angle_pitch); - camera_look = normalize3v(camera_look); - - return camera_look; + u32 shader_program = gl_shader_program(vs, fs); + + return shader_program; } -s32 gl_load_texture(u32 texture_id, const char* path) +s32 gl_load_texture(u32 texture_id, char *path, enum Texture_Filtering filter) { s32 width, height, nrChannels; + stbi_set_flip_vertically_on_load(1); unsigned char *data = stbi_load(path, &width, &height, &nrChannels, 0); + stbi_set_flip_vertically_on_load(0); if (data) { GLenum format; @@ -167,431 +181,137 @@ s32 gl_load_texture(u32 texture_id, const char* path) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - stbi_image_free(data); - } - else - { - printf("failed to load image texture at path: %s", path); - stbi_image_free(data); - } - - return texture_id; -} - -// =================== Model Loading ======================== -// This section contains a whole host of things: -// 1. classes -// 2. std::vectors -// 3. std::strings -// that I have only used as a glue for I did not know if I had the model loading setup properly. -// @todo: replace these things eventually. For now the goal is to complete learnopengl - -s32 TextureFromFile(const char* filepath, std::string directory) -{ - // @note: this function is stupid as it already became outdated as I needed to tweak the parameters - // for wrapping. Either those become function parameters (Which makes sense I guess) or I look at - // exactly what steps I am reusing and just make that a function so the function is called fewer times. - // - // I am guessing this won't look good from a design point of view for all those jobs and postings, even if - // this may be the simpler and faster thing to do, albeit at the cost of typing. - std::string filename = std::string(filepath); - filename = directory + '/' + filename; - - u32 texid; - glGenTextures(1, &texid); - - s32 width, height, nrChannels; - unsigned char *data = stbi_load(filename.c_str(), &width, &height, &nrChannels, 0); - if (data) - { - GLenum format; - if (nrChannels == 1) - format = GL_RED; - else if (nrChannels == 3) - format = GL_RGB; - else if (nrChannels == 4) - format = GL_RGBA; - - glBindTexture(GL_TEXTURE_2D, texid); - glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data); - glGenerateMipmap(GL_TEXTURE_2D); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - stbi_image_free(data); - } - else - { - printf("failed to load image texture at path: %s", filepath); - stbi_image_free(data); - } - - return texid; -} - -enum TextureType { TextureDiffuse=0, TextureSpecular }; -struct Vertex { - Vec3 position; - Vec3 normal; - Vec2 texture; -}; - -struct Texture { - u32 id; - enum TextureType type; - std::string fname; -}; - -class Mesh { - public: - std::vector vertices; - std::vector indices; - std::vector textures; - - u32 vao; - u32 vbo; - u32 ebo; - - Mesh(std::vector vertices, std::vector indices, std::vector textures) - { - this->vertices = vertices; - this->indices = indices; - this->textures = textures; - - // setup mesh shader stuff - glGenVertexArrays(1, &vao); - glGenBuffers(1, &vbo); - glGenBuffers(1, &ebo); - - glBindVertexArray(vao); - - glBindBuffer(GL_ARRAY_BUFFER, vbo); - glBufferData(GL_ARRAY_BUFFER, this->vertices.size() * sizeof(struct Vertex), &(this->vertices[0]), GL_STATIC_DRAW); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->indices.size() * sizeof(u32), &(this->indices[0]), GL_STATIC_DRAW); - - // position - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0); - // normal - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, normal)); - // texture - glEnableVertexAttribArray(2); - glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, texture)); - - glBindVertexArray(0); - } - - void draw(u32 shader_program) - { - glUseProgram(shader_program); + u32 min_filter; + u32 max_filter; - u32 diffuse_num = 1; - u32 specular_num = 1; - char tex_unit_name[64]; - // set shininess - s32 mat_shine_loc = glGetUniformLocation(shader_program, "material.shininess"); - glUniform1f(mat_shine_loc, 32.0f); - - for (u32 i=0; i loaded_textures; - std::vector meshes; - std::string directory; - - Model(std::string path) - { - load_model(path); - } - void instance_mesh(); - void draw(u32 shader_program); - void draw_instanced(u32 shader_program, u32 instance_count); - private: - void load_model(std::string path); - void process_node(aiNode *node, const aiScene *scene); - Mesh process_mesh(aiMesh *mesh, const aiScene *scene); - std::vector load_material_textures(aiMaterial *mat, aiTextureType type, TextureType type_name); -}; - -void Model::instance_mesh() -{ - for (u32 i=0; i < meshes.size(); i++) + else { - Mesh curr_mesh = meshes[i]; - glBindVertexArray(curr_mesh.vao); - glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, 16 * sizeof(u32), (void*)0); - glEnableVertexAttribArray(3); - - glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, 16 * sizeof(u32), (void*)(4*sizeof(u32))); - glEnableVertexAttribArray(4); - - glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, 16 * sizeof(u32), (void*)(8*sizeof(u32))); - glEnableVertexAttribArray(5); - - glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, 16 * sizeof(u32), (void*)(12*sizeof(u32))); - glEnableVertexAttribArray(6); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glVertexAttribDivisor(3, 1); - glVertexAttribDivisor(4, 1); - glVertexAttribDivisor(5, 1); - glVertexAttribDivisor(6, 1); - - glBindVertexArray(0); + // @todo: logging + printf("failed to load image texture at path: %s", path); + stbi_image_free(data); + return -1; } + + return 0; } -void Model::draw(u32 shader_program) +GlTexturedQuad gl_setup_textured_quad(char* texture_path, enum Texture_Filtering filter) { - for (int i=0; i < meshes.size(); i++) - { - meshes[i].draw(shader_program); - } + // rendering is clock-wise + r32 quad_vertices[] = { + -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom-left + 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom-right + 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top-right + 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top-right + -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top-left + -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom-left + }; + u32 vao, vbo, tex_id; + glGenVertexArrays(1, &vao); + glGenBuffers(1, &vbo); + + glBindVertexArray(vao); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(quad_vertices), &quad_vertices, GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(r32), (void*)0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(r32), (void*)(3*sizeof(r32))); + glBindVertexArray(0); + + glGenTextures(1, &tex_id); + glActiveTexture(GL_TEXTURE0); + gl_load_texture(tex_id, texture_path, filter); + + GlTexturedQuad tex_quad; + tex_quad.vao = vao; + tex_quad.vbo = vbo; + tex_quad.texture_id = tex_id; + + return tex_quad; } -void Model::draw_instanced(u32 shader_program, u32 instance_count) +void gl_draw_tex_quad(u32 shader_program, GlTexturedQuad tex_quad) { - for (int i=0; i < meshes.size(); i++) - { - meshes[i].draw_instanced(shader_program, instance_count); - } + glUseProgram(shader_program); + s32 tex_id_loc = glGetUniformLocation(shader_program, "Texture"); + glUniform1i(tex_id_loc, 0); + glBindVertexArray(tex_quad.vao); + glBindTexture(GL_TEXTURE_2D, tex_quad.texture_id); + glDrawArrays(GL_TRIANGLES, 0, 6); } -void Model::load_model(std::string path) +// =============== CAMERA STUFF ================= +// @note: Be sure to update and refactor the camera +Mat4 camera_create4m(Vec3 camera_pos, Vec3 camera_look, Vec3 camera_up) { - Assimp::Importer import; - const aiScene *scene = import.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs); - - if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) - { - printf("error loading model :%s\n", import.GetErrorString()); - return; - } - - directory = path.substr(0, path.find_last_of('/')); - process_node(scene->mRootNode, scene); + // @note: We do this because this allows the camera to have the axis it looks at + // inwards be the +z axis. + // If we did not do this, then the inward axis the camera looks at would be negative. + // I am still learning from learnopengl.com but I imagine that this was done for conveniences' sake. + Vec3 camera_forward_dir = normalize3v(subtract3v(camera_pos, camera_look)); + Vec3 camera_right_dir = normalize3v(cross_multiply3v(camera_up, camera_forward_dir)); + Vec3 camera_up_dir = normalize3v(cross_multiply3v(camera_forward_dir, camera_right_dir)); + + Mat4 res = lookat4m(camera_up_dir, camera_forward_dir, camera_right_dir, camera_pos); + + return res; } -void Model::process_node(aiNode *node, const aiScene *scene) +Vec3 camera_look_around(r32 angle_pitch, r32 angle_yaw) { - for (int i=0; i < node->mNumMeshes; i++) - { - aiMesh *mesh = scene->mMeshes[node->mMeshes[i]]; - meshes.push_back(process_mesh(mesh, scene)); - } - - for (int i=0; imNumChildren; i++) - { - process_node(node->mChildren[i], scene); - } + Vec3 camera_look = {0.0}; + camera_look.x = cosf(angle_yaw) * cosf(angle_pitch); + camera_look.y = sinf(angle_pitch); + camera_look.z = sinf(angle_yaw) * cosf(angle_pitch); + camera_look = normalize3v(camera_look); + + return camera_look; } -Mesh Model::process_mesh(aiMesh *mesh, const aiScene *scene) +int main(int argc, char* argv[]) { - std::vector vertices; - std::vector indices; - std::vector textures; - - for (u32 i=0; i < mesh->mNumVertices; i++) - { - Vec3 position; - position.x = mesh->mVertices[i].x; - position.y = mesh->mVertices[i].y; - position.z = mesh->mVertices[i].z; - - Vec3 normal; - normal.x = mesh->mNormals[i].x; - normal.y = mesh->mNormals[i].y; - normal.z = mesh->mNormals[i].z; - - Vec2 texture = {0, 0}; - if (mesh->mTextureCoords[0]) - { - texture.x = mesh->mTextureCoords[0][i].x; - texture.y = mesh->mTextureCoords[0][i].y; - } - struct Vertex vertex; - vertex.position = position; - vertex.normal = normal; - vertex.texture = texture; + // Load freetype + FT_Library library; + FT_Face face; - vertices.push_back(vertex); - } - // process indices - for (u32 i = 0; i < mesh->mNumFaces; i++) + if (FT_Init_FreeType(&library)) { - aiFace face = mesh->mFaces[i]; - for(u32 j = 0; j < face.mNumIndices; j++) - { - indices.push_back(face.mIndices[j]); - } + printf("Error: Could not init freetype library\n"); + return -1; } - // process material - if (mesh->mMaterialIndex >= 0) + + FT_Error error = FT_New_Face(library, "assets/fonts/Arial.ttf", 0, &face); + if (error == FT_Err_Unknown_File_Format) { - aiMaterial *material = scene->mMaterials[mesh->mMaterialIndex]; - std::vector diffuse_maps = load_material_textures(material, aiTextureType_DIFFUSE, TextureDiffuse); - textures.insert(textures.end(), diffuse_maps.begin(), diffuse_maps.end()); - std::vector specular_maps = load_material_textures(material, aiTextureType_SPECULAR, TextureSpecular); - textures.insert(textures.end(), specular_maps.begin(), specular_maps.end()); + printf("Error: Font Loading Failed. The font format is unsupported.\n"); + return -1; } - - return Mesh(vertices, indices, textures); -} - -std::vector Model::load_material_textures(aiMaterial *mat, aiTextureType type, TextureType tex_type) -{ - std::vector textures; - for(u32 i=0; iGetTextureCount(type); i++) + else if (error) { - bool load_texture = true; - aiString str; - mat->GetTexture(type, i, &str); - const char* fname = str.C_Str(); - - for (s32 j=0; j +#include +#include + +// =================== Model Loading ======================== +// Piss Poor Model Loading +// This section contains a whole host of things: +// 1. classes +// 2. std::vectors +// 3. std::strings +// that I have only used as a glue for I did not know if I had the model loading setup properly. +// @todo: replace these things eventually. For now the goal is to complete learnopengl + +#include + +s32 TextureFromFile(const char* filepath, std::string directory) +{ + // @note: this function is stupid as it already became outdated as I needed to tweak the parameters + // for wrapping. Either those become function parameters (Which makes sense I guess) or I look at + // exactly what steps I am reusing and just make that a function so the function is called fewer times. + // + // I am guessing this won't look good from a design point of view for all those jobs and postings, even if + // this may be the simpler and faster thing to do, albeit at the cost of typing. + std::string filename = std::string(filepath); + filename = directory + '/' + filename; + + u32 texid; + glGenTextures(1, &texid); + + s32 width, height, nrChannels; + unsigned char *data = stbi_load(filename.c_str(), &width, &height, &nrChannels, 0); + if (data) + { + GLenum format; + if (nrChannels == 1) + format = GL_RED; + else if (nrChannels == 3) + format = GL_RGB; + else if (nrChannels == 4) + format = GL_RGBA; + + glBindTexture(GL_TEXTURE_2D, texid); + glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data); + glGenerateMipmap(GL_TEXTURE_2D); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + stbi_image_free(data); + } + else + { + printf("failed to load image texture at path: %s", filepath); + stbi_image_free(data); + } + + return texid; +} + +enum TextureType { TextureDiffuse=0, TextureSpecular }; + +struct Vertex { + Vec3 position; + Vec3 normal; + Vec2 texture; +}; + +struct Texture { + u32 id; + enum TextureType type; + std::string fname; +}; + +class Mesh { + public: + std::vector vertices; + std::vector indices; + std::vector textures; + + u32 vao; + u32 vbo; + u32 ebo; + + Mesh(std::vector vertices, std::vector indices, std::vector textures) + { + this->vertices = vertices; + this->indices = indices; + this->textures = textures; + + // setup mesh shader stuff + glGenVertexArrays(1, &vao); + glGenBuffers(1, &vbo); + glGenBuffers(1, &ebo); + + glBindVertexArray(vao); + + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, this->vertices.size() * sizeof(struct Vertex), &(this->vertices[0]), GL_STATIC_DRAW); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->indices.size() * sizeof(u32), &(this->indices[0]), GL_STATIC_DRAW); + + // position + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0); + // normal + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, normal)); + // texture + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, texture)); + + glBindVertexArray(0); + } + + void draw(u32 shader_program) + { + glUseProgram(shader_program); + + u32 diffuse_num = 1; + u32 specular_num = 1; + char tex_unit_name[64]; + // set shininess + s32 mat_shine_loc = glGetUniformLocation(shader_program, "material.shininess"); + glUniform1f(mat_shine_loc, 32.0f); + + for (u32 i=0; i loaded_textures; + std::vector meshes; + std::string directory; + + Model(std::string path) + { + load_model(path); + } + void instance_mesh(); + void draw(u32 shader_program); + void draw_instanced(u32 shader_program, u32 instance_count); + private: + void load_model(std::string path); + void process_node(aiNode *node, const aiScene *scene); + Mesh process_mesh(aiMesh *mesh, const aiScene *scene); + std::vector load_material_textures(aiMaterial *mat, aiTextureType type, TextureType type_name); +}; + +void Model::instance_mesh() +{ + for (u32 i=0; i < meshes.size(); i++) + { + Mesh curr_mesh = meshes[i]; + glBindVertexArray(curr_mesh.vao); + glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, 16 * sizeof(u32), (void*)0); + glEnableVertexAttribArray(3); + + glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, 16 * sizeof(u32), (void*)(4*sizeof(u32))); + glEnableVertexAttribArray(4); + + glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, 16 * sizeof(u32), (void*)(8*sizeof(u32))); + glEnableVertexAttribArray(5); + + glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, 16 * sizeof(u32), (void*)(12*sizeof(u32))); + glEnableVertexAttribArray(6); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glVertexAttribDivisor(3, 1);123 + glVertexAttribDivisor(4, 1); + glVertexAttribDivisor(5, 1); + glVertexAttribDivisor(6, 1); + + glBindVertexArray(0); + } +} + +void Model::draw(u32 shader_program) +{ + for (int i=0; i < meshes.size(); i++) + { + meshes[i].draw(shader_program); + } +} + +void Model::draw_instanced(u32 shader_program, u32 instance_count) +{ + for (int i=0; i < meshes.size(); i++) + { + meshes[i].draw_instanced(shader_program, instance_count); + } +} + +void Model::load_model(std::string path) +{ + Assimp::Importer import; + const aiScene *scene = import.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs); + + if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) + { + printf("error loading model :%s\n", import.GetErrorString()); + return; + } + + directory = path.substr(0, path.find_last_of('/')); + process_node(scene->mRootNode, scene); +} + +void Model::process_node(aiNode *node, const aiScene *scene) +{ + for (int i=0; i < node->mNumMeshes; i++) + { + aiMesh *mesh = scene->mMeshes[node->mMeshes[i]]; + meshes.push_back(process_mesh(mesh, scene)); + } + + for (int i=0; imNumChildren; i++) + { + process_node(node->mChildren[i], scene); + } +} + +Mesh Model::process_mesh(aiMesh *mesh, const aiScene *scene) +{ + std::vector vertices; + std::vector indices; + std::vector textures; + + for (u32 i=0; i < mesh->mNumVertices; i++) + { + Vec3 position; + position.x = mesh->mVertices[i].x; + position.y = mesh->mVertices[i].y; + position.z = mesh->mVertices[i].z; + + Vec3 normal; + normal.x = mesh->mNormals[i].x; + normal.y = mesh->mNormals[i].y; + normal.z = mesh->mNormals[i].z; + + Vec2 texture = {0, 0}; + if (mesh->mTextureCoords[0]) + { + texture.x = mesh->mTextureCoords[0][i].x; + texture.y = mesh->mTextureCoords[0][i].y; + } + + struct Vertex vertex; + vertex.position = position; + vertex.normal = normal; + vertex.texture = texture; + + vertices.push_back(vertex); + } + // process indices + for (u32 i = 0; i < mesh->mNumFaces; i++) + { + aiFace face = mesh->mFaces[i]; + for(u32 j = 0; j < face.mNumIndices; j++) + { + indices.push_back(face.mIndices[j]); + } + } + // process material + if (mesh->mMaterialIndex >= 0) + { + aiMaterial *material = scene->mMaterials[mesh->mMaterialIndex]; + std::vector diffuse_maps = load_material_textures(material, aiTextureType_DIFFUSE, TextureDiffuse); + textures.insert(textures.end(), diffuse_maps.begin(), diffuse_maps.end()); + std::vector specular_maps = load_material_textures(material, aiTextureType_SPECULAR, TextureSpecular); + textures.insert(textures.end(), specular_maps.begin(), specular_maps.end()); + } + + return Mesh(vertices, indices, textures); +} + +std::vector Model::load_material_textures(aiMaterial *mat, aiTextureType type, TextureType tex_type) +{ + std::vector textures; + for(u32 i=0; iGetTextureCount(type); i++) + { + bool load_texture = true; + aiString str; + mat->GetTexture(type, i, &str); + const char* fname = str.C_Str(); + + for (s32 j=0; j