#include #if 0 #include #include #include #endif #include #include #include #include "dumbLog.h" #include "mesh.h" // WIP bool meInitAssimp() { return false; } bool meLoadFromFile(mesh_group& mesh_group, const char* filepath) { return false; } simple_mesh* meInitMesh(uint num_vertices) { return nullptr; } void meFreeMeshGroup(mesh_group& mesh_group) {} void meFreeSimpleMesh(simple_mesh* mesh) {} void meShutdownAssimp() {} // WIP #if 0 // forward declarations mesh_info* allocateMeshInfo(uint num_vertices, uint num_indices); void assimpLogCB(const char* message, char* user); mesh_info* copyMeshInfo(const aiScene* scene, aiMesh* mesh); inline glm::vec3 copyVector(aiVector3D v_in, glm::vec3& v_out); void freeMesh(mesh_info* mesh); bool loadDiffuseTexture(const aiScene* scene, aiMesh* mesh, mesh_info* mi); bool validateScene(const aiScene* scene, const char* filepath); // interface bool meInitAssimp() { LOG(Info) << "Initializing Assimp\n"; aiLogStream ls; ls.callback = assimpLogCB; aiAttachLogStream(&ls); return true; } bool meLoadFromFile(mesh_group& mesh_group, const char* filepath) { LOG(Info) << "Loading file: " << filepath << "\n"; const aiScene* scene = aiImportFile(filepath, aiProcessPreset_TargetRealtime_MaxQuality); if (!validateScene(scene, filepath)) return false; mesh_group.num_meshes = scene->mNumMeshes; mesh_group.meshes = UTIL_ALLOC(mesh_group.num_meshes, mesh_info*); for (uint i = 0; i < scene->mNumMeshes; i++) { aiMesh* mesh = scene->mMeshes[i]; mesh_info* mi = copyMeshInfo(scene, mesh); if (!mesh->HasTextureCoords(0) || !loadDiffuseTexture(scene, mesh, mi)) { LOG(Error) << "Error loading texture, cleaning up import\n"; freeMesh(mi); aiReleaseImport(scene); return false; } mesh_group.meshes[i] = mi; } aiReleaseImport(scene); return true; } simple_mesh* meInitMesh(uint num_vertices) { assert(num_vertices > 0); simple_mesh* sm = UTIL_ALLOC(1, simple_mesh); sm->model_transform = glm::mat4(1.0); sm->num_vertices = num_vertices; sm->vertices = UTIL_ALLOC(num_vertices, glm::vec3); sm->vert_colors = UTIL_ALLOC(num_vertices, glm::vec3); return sm; } void meFreeMeshGroup(mesh_group& mesh_group) { for (uint i = 0; i < mesh_group.num_meshes; i++) freeMesh(mesh_group.meshes[i]); utilSafeFree(mesh_group.meshes); mesh_group.num_meshes = 0; mesh_group.meshes = nullptr; } void meFreeSimpleMesh(simple_mesh* mesh) { assert(mesh != nullptr); utilSafeFree(mesh->vertices); mesh->vertices = nullptr; utilSafeFree(mesh->vert_colors); mesh->vert_colors = nullptr; mesh->num_vertices = 0; } void meShutdownAssimp() { aiDetachAllLogStreams(); } // internal mesh_info* allocateMeshInfo(uint num_vertices, uint num_indices) { mesh_info* mi = UTIL_ALLOC(1, mesh_info); 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); mi->normals = UTIL_ALLOC(mi->num_vertices, glm::vec3); mi->texture_coords = UTIL_ALLOC(mi->num_vertices, glm::vec3); return mi; } void assimpLogCB(const char* message, char* user) { // NOTE: filter 'info' messages from assimp if (!utilMatchPrefix(message, "Info,", 5)) LOG(Info) << message << "\n"; } mesh_info* copyMeshInfo(const aiScene* scene, aiMesh* mesh) { mesh_info* mi = allocateMeshInfo(mesh->mNumVertices, mesh->mNumFaces * 3); // copy vertices, normals, and texture coords for (uint i = 0; i < mi->num_vertices; i++) { copyVector(mesh->mVertices[i], mi->vertices[i]); copyVector(mesh->mNormals[i], mi->normals[i]); mi->texture_coords[i].x = mesh->mTextureCoords[0][i].x; mi->texture_coords[i].y = mesh->mTextureCoords[0][i].y; mi->texture_coords[i].z = 0; } // 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]; return mi; } 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; } void freeMesh(mesh_info* mesh) { utilFreeImage(mesh->diffuse_texture); utilSafeFree(mesh->vertices); utilSafeFree(mesh->normals); utilSafeFree(mesh->texture_coords); utilSafeFree(mesh->indices); utilSafeFree(mesh); } bool loadDiffuseTexture(const aiScene* scene, aiMesh* mesh, mesh_info* mi) { aiMaterial* mat = scene->mMaterials[mesh->mMaterialIndex]; aiString file_name; if (mat->GetTextureCount(aiTextureType_DIFFUSE) < 1) return false; if (AI_SUCCESS != mat->GetTexture( aiTextureType_DIFFUSE, 0, &file_name, NULL, NULL, NULL, NULL, NULL)) { LOG(Error) << "No diffuse texture from assimp\n"; return false; } else { const aiTexture* tex = scene->GetEmbeddedTexture(file_name.C_Str()); if (tex != nullptr) { LOG(Info) << "has embedded texture\n"; mi->diffuse_texture = utilLoadImageBytes((const uint8*) tex->pcData, tex->mWidth); } else { LOG(Info) << "Loading texture file: " << file_name.C_Str() << "\n"; mi->diffuse_texture = utilLoadImagePath(file_name.C_Str()); } if (mi->diffuse_texture.pixels == nullptr) { LOG(Error) << "Error loading texture\n"; return false; } } return true; } bool validateScene(const aiScene* scene, const char* filepath) { if (!scene) { LOG(Error) << "Error loading file: " << filepath << "\n"; return false; } if (scene->mNumMeshes < 1) { LOG(Error) << "Scene contains no meshes\n"; return false; } if (!scene->mMeshes[0]->HasNormals()) { LOG(Error) << "Mesh doesn't have normals\n"; return false; } return true; } #endif