A small OpenGL 3+ renderer and game engine
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.
 
 
 

262 lines
5.7 KiB

#include <cassert>
#if 0
#include <assimp/cimport.h>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
#endif
#include <glm/glm.hpp>
#include <glm/geometric.hpp>
#include <glm/gtc/matrix_transform.hpp>
#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