You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
175 lines
4.3 KiB
175 lines
4.3 KiB
#include <cassert> |
|
|
|
#include <assimp/cimport.h> |
|
#include <assimp/scene.h> |
|
#include <assimp/postprocess.h> |
|
|
|
#include <glm/glm.hpp> |
|
#include <glm/geometric.hpp> |
|
#include <glm/gtc/matrix_transform.hpp> |
|
|
|
#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; |
|
}
|
|
|