#include #include #include #include #include #include #include #include "dumbLog.h" #include "mesh.h" // forward declarations void assimpLogCB(const char* message, char* user); meMeshInfo* allocateMeshInfo(uint num_vertices, uint num_indices, bool has_normals, bool has_texture); void freeMesh(meMeshInfo* mesh); inline glm::vec3 copyVector(aiVector3D v_in, glm::vec3& v_out); meMeshInfo* copyMeshInfo(const char* data_dir, const aiScene* scene, aiMesh* mesh); // interface bool meInitAssimp() { LOG(Info) << "Initializing Assimp\n"; aiLogStream ls; ls.callback = assimpLogCB; aiAttachLogStream(&ls); return true; } bool meLoadFromFile(meMeshGroup& mesh_group, const char* data_dir, const char* filename) { LOG(Info) << "Loading file: " << filename << "\n"; const aiScene* scene = aiImportFile(filename, aiProcessPreset_TargetRealtime_MaxQuality); if (!scene) { LOG(Error) << "Error loading file: " << filename << "\n"; return false; } if (scene->mNumMeshes < 1) { LOG(Error) << "Scene contains no meshes\n"; return false; } mesh_group.num_meshes = scene->mNumMeshes; mesh_group.meshes = UTIL_ALLOC(mesh_group.num_meshes, meMeshInfo*); mesh_group.use_normals = scene->mMeshes[0]->HasNormals(); for (uint i = 0; i < scene->mNumMeshes; i++) { mesh_group.meshes[i] = copyMeshInfo(data_dir, scene, scene->mMeshes[i]); } // free memeory from assimp aiReleaseImport(scene); return true; } void meFreeMeshGroup(meMeshGroup& mesh_group) { for (uint i = 0; i < mesh_group.num_meshes; i++) freeMesh(mesh_group.meshes[i]); utilSafeFree(mesh_group.meshes); } void meShutdownAssimp() { aiDetachAllLogStreams(); } // internal void assimpLogCB(const char* message, char* user) { // NOTE: filter 'info' messages from assimp if (!utilMatchPrefix(message, "Info,", 5)) LOG(Info) << message << "\n"; } meMeshInfo* allocateMeshInfo(uint num_vertices, uint num_indices, bool has_normals, bool has_texture) { meMeshInfo* mi = UTIL_ALLOC(1, meMeshInfo); mi->model_transform = glm::mat4(1); // allocate buffers for vertex and index data from mesh mi->num_vertices = num_vertices; mi->vertices = UTIL_ALLOC(mi->num_vertices, glm::vec3); mi->num_indices = num_indices; mi->indices = UTIL_ALLOC(num_indices, uint); if (has_normals) mi->normals = UTIL_ALLOC(mi->num_vertices, glm::vec3); if (has_texture) mi->texture_coords = UTIL_ALLOC(mi->num_vertices, glm::vec3); return mi; } void freeMesh(meMeshInfo* mesh) { utilFreeImage(mesh->diffuse_texture); utilSafeFree(mesh->vertices); utilSafeFree(mesh->normals); utilSafeFree(mesh->texture_coords); utilSafeFree(mesh->indices); utilSafeFree(mesh); } inline glm::vec3 copyVector(aiVector3D v_in, glm::vec3& v_out) { v_out.x = v_in.x; v_out.y = v_in.y; v_out.z = v_in.z; return v_out; } meMeshInfo* copyMeshInfo(const char* data_dir, const aiScene* scene, aiMesh* mesh) { bool has_tex = mesh->HasTextureCoords(0); bool has_normals = mesh->HasNormals(); meMeshInfo* mi = allocateMeshInfo(mesh->mNumVertices, mesh->mNumFaces * 3, has_normals, has_tex); // copy vertices, normals, and texture coords for (uint i = 0; i < mi->num_vertices; i++) { copyVector(mesh->mVertices[i], mi->vertices[i]); if (has_normals) copyVector(mesh->mNormals[i], mi->normals[i]); if (has_tex) { mi->texture_coords[i].x = mesh->mTextureCoords[0][i].x; mi->texture_coords[i].y = mesh->mTextureCoords[0][i].y; } } // copy indices for (uint i = 0; i < mesh->mNumFaces; i++) for (uint j = 0; j < 3; j++) mi->indices[i * 3 + j] = mesh->mFaces[i].mIndices[j]; // material aiMaterial* mat = scene->mMaterials[mesh->mMaterialIndex]; aiColor3D color(0.f, 0.f, 0.f); if (AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_DIFFUSE, color)) { mi->diffuse_color.r = color.r; mi->diffuse_color.g = color.g; mi->diffuse_color.b = color.b; } if (has_tex && mat->GetTextureCount(aiTextureType_DIFFUSE) > 0) { aiString file_name; if (AI_SUCCESS != mat->GetTexture(aiTextureType_DIFFUSE, 0, &file_name, NULL, NULL, NULL, NULL, NULL)) { LOG(Error) << "No diffuse texture from assimp\n"; } else { LOG(Info) << "Loading texture file: " << file_name.C_Str() << "\n"; mi->diffuse_texture = utilLoadImage(data_dir, file_name.C_Str()); mi->use_texture = true; } } return mi; }