extern bool use_vulkan;
static Mesh *load_mesh(const aiScene *scene, unsigned int index);
-static Material *load_material(const aiScene *ascene, Scene *scene, unsigned int index);
+static Material *load_material(const aiScene *ascene, Scene *scene, unsigned int index, const char *tex_fname);
+
+static Mat4 aiMatrix2Mat(aiMatrix4x4 t);
+static void create_object(aiNode *node, Mat4 transform, Scene *scene, const aiScene *ascene);
Scene::Scene() {}
Scene::~Scene()
{
- for(size_t i=0; i<meshes.size(); ++i)
+ for(size_t i=0; i<meshes.size(); i++)
delete meshes[i];
meshes.clear();
- for(size_t i=0; i<materials.size(); ++i)
+ for(size_t i=0; i<materials.size(); i++)
delete materials[i];
materials.clear();
- for(size_t i=0; i<textures.size(); ++i)
+ for(size_t i=0; i<textures.size(); i++)
delete textures[i];
textures.clear();
- for(size_t i=0; i<objects.size(); ++i)
+ for(size_t i=0; i<objects.size(); i++)
delete objects[i];
objects.clear();
}
bool Scene::load(const char *fname)
{
/* loading scene */
- unsigned int ai_flags = aiProcessPreset_TargetRealtime_Quality;
+ /* TODO !!!!!!!!!!!!!!!! flipuvs might need to be removed + fix the cow */
+ unsigned int ai_flags = aiProcessPreset_TargetRealtime_Quality | aiProcess_FlipUVs;
const aiScene *scene = aiImportFile(fname, ai_flags);
if(!scene) {
fprintf(stderr, "Failed to import scene: %s\n", fname);
return false;
}
- /* loading scene meshes */
- for(unsigned int i=0; i<scene->mNumMeshes; ++i) {
+ /* load meshes */
+ for(unsigned int i=0; i<scene->mNumMeshes; i++) {
Mesh *mesh = load_mesh(scene, i);
if(!mesh) {
fprintf(stderr, "Failed to load mesh no: %d.\n", i);
return false;
}
+ mesh->update_vertex_data();
meshes.push_back(mesh);
}
- /* loading materials */
- for(unsigned int i=0; i<scene->mNumMaterials; ++i) {
- Material *material = load_material(scene, this, i);
+ /* load materials */
+ char *tex_path = new char[strlen(fname) + 1];
+ strcpy(tex_path, fname);
+ char *last_slash = strrchr(tex_path, '/');
+ if(last_slash) {
+ *last_slash = '\0';
+ }
+ else {
+ delete [] tex_path;
+ tex_path = 0;
+ }
+
+ for(unsigned int i=0; i<scene->mNumMaterials; i++) {
+ Material *material = load_material(scene, this, i, tex_path);
if(!material) {
fprintf(stderr, "Failed to load material no: %d", i);
return false;
}
/* create objects */
- for(unsigned int i=0; i<scene->mNumMeshes; ++i) {
- Object *object = new Object();
- object->mesh = meshes[i];
- int idx = meshes[i]->mat_idx;
- object->material = materials[idx];
- objects.push_back(object);
+ aiNode *node = scene->mRootNode;
+ Mat4 transform = Mat4::identity;
+ create_object(node, transform, this, scene);
+ return true;
+}
+
+static Mat4 aiMatrix2Mat(aiMatrix4x4 t)
+{
+ return Mat4(t.a1, t.a2, t.a3, t.a4,
+ t.b1, t.b2, t.b3, t.b4,
+ t.c1, t.c2, t.c3, t.c4,
+ t.d1, t.d2, t.d3, t.d4);
+}
+
+static void create_object(aiNode *node, Mat4 parent_transform, Scene *scene, const aiScene *ascene)
+{
+ /* Note:
+ The 99% of the scenes have 1 mesh per node => for simplicity we only check the 1st one.
+ Also: the 3D models we are going to use for this demo, have flat structure (no hierarchy)
+ but just in case we need to replace them later, we calculate the transform by assuming that we
+ have a node hierarchy. This => that each object's modelling transformation is the
+ product of its local transformation (mTransformation) with the acc parent nodes transformations
+ (parent_transform)
+ */
+ Mat4 modelling_transform = parent_transform * aiMatrix2Mat(node->mTransformation);
+
+ if(node->mNumMeshes > 0) {
+ Object *object = new Object;
+
+ // get the mesh index from node
+ int mesh_idx = node->mMeshes[0];
+ object->mesh = scene->meshes[mesh_idx];
+
+ // get the material index from the mesh that is assigned to this node
+ aiMesh *amesh = ascene->mMeshes[mesh_idx];
+ object->material = scene->materials[amesh->mMaterialIndex];
+
+ // set the object's transformation
+ object->transform = modelling_transform;
+ scene->objects.push_back(object);
}
- aiReleaseImport(scene);
- return true;
+ for(unsigned int i=0; i<node->mNumChildren; i++) {
+ create_object(node->mChildren[i], modelling_transform, scene, ascene);
+ }
}
static Mesh *load_mesh(const aiScene *scene, unsigned int index)
}
mesh->name = std::string(amesh->mName.data);
- mesh->which_mask = 0;
- for(unsigned int i=0; i<amesh->mNumVertices; ++i) {
+ for(unsigned int i=0; i<amesh->mNumVertices; i++) {
/* vertices */
if(amesh->HasPositions()) {
- mesh->which_mask |= MESH_VERTEX;
Vec3 vertex = Vec3(amesh->mVertices[i].x, amesh->mVertices[i].y,
amesh->mVertices[i].z);
/* normals */
if(amesh->HasNormals()) {
- mesh->which_mask |= MESH_NORMAL;
Vec3 normal = Vec3(amesh->mNormals[i].x, amesh->mNormals[i].y,
amesh->mNormals[i].z);
mesh->normals.push_back(normal);
/* texture coordinates */
if(amesh->mTextureCoords[0]) {
- mesh->which_mask |= MESH_TEXTURE;
- Vec2 tex_coord =
- Vec2(amesh->mTextureCoords[0][i].x, amesh->mTextureCoords[0][i].y);
+ Vec2 tex_coord = Vec2(amesh->mTextureCoords[0][i].x, amesh->mTextureCoords[0][i].y);
mesh->tex_coords.push_back(tex_coord);
}
else {
+ printf("mesh has no texture coordinates.\n");
mesh->tex_coords.push_back(Vec2(0, 0));
}
/* tangents */
- if(amesh->mTangents) {
- mesh->which_mask |= MESH_TANGENT;
- Vec3 tangent = Vec3(amesh->mTangents[i].x, amesh->mTangents[i].y,
- amesh->mTangents[i].z);
- mesh->tangents.push_back(tangent);
- }
- else {
- mesh->tangents.push_back(Vec3(1, 0, 0));
- }
+ // if(amesh->mTangents) {
+ // mesh->which_mask |= MESH_TANGENT;
+ // Vec3 tangent = Vec3(amesh->mTangents[i].x, amesh->mTangents[i].y,
+ // amesh->mTangents[i].z);
+ // mesh->tangents.push_back(tangent);
+ // }
+ // else {
+ // mesh->tangents.push_back(Vec3(1, 0, 0));
+ // }
}
/* indices (called faces in assimp) */
if(amesh->HasFaces()) {
- mesh->which_mask |= MESH_INDEX;
- for(unsigned int i=0; i<amesh->mNumFaces; ++i) {
+ for(unsigned int i=0; i<amesh->mNumFaces; i++) {
mesh->indices.push_back(amesh->mFaces[i].mIndices[0]);
mesh->indices.push_back(amesh->mFaces[i].mIndices[1]);
mesh->indices.push_back(amesh->mFaces[i].mIndices[2]);
fprintf(stderr, "No faces found.\n");
mesh->mat_idx = amesh->mMaterialIndex;
- printf("material idx:%u", mesh->mat_idx);
return mesh;
}
-static Material *load_material(const aiScene *ascene, Scene *scene, unsigned int index)
+static Material *load_material(const aiScene *ascene, Scene *scene, unsigned int index, const char *tex_path)
{
aiMaterial *amat = ascene->mMaterials[index];
if(!amat) {
mat->dtex = 0;
mat->shininess = 40;
- // aiString name;
- // amat->Get(AI_MATKEY_NAME, name);
- // mat->name = std::string(name.data);
+ aiString name;
+ amat->Get(AI_MATKEY_NAME, name);
+ mat->name = std::string(name.data);
aiColor4D color;
aiGetMaterialColor(amat, AI_MATKEY_COLOR_DIFFUSE, &color);
mat->diffuse = Vec3(color.r, color.g, color.b);
aiGetMaterialColor(amat, AI_MATKEY_COLOR_SPECULAR, &color);
- float spstr;
- aiGetMaterialFloat(amat, AI_MATKEY_SHININESS_STRENGTH, &spstr);
- mat->specular = spstr * Vec3(color.r, color.g, color.b);
+ // float spstr;
+ // aiGetMaterialFloat(amat, AI_MATKEY_SHININESS_STRENGTH, &spstr);
+ // mat->specular = spstr * Vec3(color.r, color.g, color.b);
+ mat->specular = Vec3(color.r, color.g, color.b);
aiGetMaterialFloat(amat, AI_MATKEY_SHININESS, &mat->shininess);
+ mat->shininess /= 128.0;
+ printf("shininess: %f\n", mat->shininess);
aiString tex_name;
if(aiGetMaterialString(amat, AI_MATKEY_TEXTURE_DIFFUSE(0), &tex_name) == aiReturn_SUCCESS) {
/* different scene objects might use the same texture, we shouldn't store it twice*/
- //mat->dtex = scene->find_texture(tex_name.data);
+
+ std::string tex_fname = tex_path ? std::string(tex_path) + "/" + tex_name.data : tex_name.data;
+
+ mat->dtex = scene->find_texture(tex_fname.c_str());
if(!mat->dtex) {
+ printf("!mat->dtex\n");
if(use_vulkan) {
mat->dtex = new TextureVK;
}
else {
mat->dtex = new TextureGL;
}
- if(!mat->dtex->load(tex_name.data)) {
- fprintf(stderr, "Failed to load texture data: %s.\n", tex_name.data);
+ if(!mat->dtex->load(tex_fname.c_str())) {
+ fprintf(stderr, "Failed to load texture data: %s.\n", tex_fname.c_str());
delete mat->dtex;
mat->dtex = 0;
}
+ else {
+ mat->dtex->name = std::string(tex_fname.c_str());
+ }
+ printf("Successfully loaded texture: %s\n", tex_fname.c_str());
scene->textures.push_back(mat->dtex);
}
}
return mat;
}
+
+Mesh *Scene::find_mesh(const char *name)
+{
+ for(size_t i=0; i<meshes.size(); i++) {
+ if(meshes[i]->name == name) {
+ return meshes[i];
+ }
+ }
+ fprintf(stderr, "Mesh %s not found.\n", name);
+ return 0;
+}
+
+Material *Scene::find_material(const char *name)
+{
+ for(size_t i=0; i<materials.size(); i++) {
+ if(materials[i]->name == name) {
+ return materials[i];
+ }
+ }
+ fprintf(stderr, "Material %s not found.\n", name);
+ return 0;
+}
+
+Texture *Scene::find_texture(const char *name)
+{
+ for(size_t i=0; i<textures.size(); i++) {
+ if(textures[i]->name == name) {
+ return textures[i];
+ }
+ }
+ fprintf(stderr, "Texture %s not found.\n", name);
+ return 0;
+}
\ No newline at end of file