quick backup
[demo] / src / scene.cc
index e53e5a3..8adb7df 100644 (file)
 
 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()
 {
-       /* clear meshes */
-       for(size_t i=0; i<meshes.size(); ++i)
+       for(size_t i=0; i<meshes.size(); i++)
                delete meshes[i];
        meshes.clear();
 
-       /* clear materials */
-       for(size_t i=0; i<materials.size(); ++i)
+       for(size_t i=0; i<materials.size(); i++)
                delete materials[i];
        materials.clear();
 
-       /* clear textures */
-       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++)
+               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;
@@ -76,10 +93,51 @@ bool Scene::load(const char *fname)
        }
 
        /* create objects */
+       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)
@@ -100,12 +158,10 @@ 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);
 
@@ -119,7 +175,6 @@ static Mesh *load_mesh(const aiScene *scene, unsigned int index)
 
                /* 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);
@@ -132,30 +187,28 @@ static Mesh *load_mesh(const aiScene *scene, unsigned int index)
 
                /* 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]);
@@ -164,10 +217,11 @@ static Mesh *load_mesh(const aiScene *scene, unsigned int index)
        else
                fprintf(stderr, "No faces found.\n");
 
+       mesh->mat_idx = amesh->mMaterialIndex;
        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) {
@@ -179,38 +233,83 @@ static Material *load_material(const aiScene *ascene, Scene *scene, unsigned int
        mat->dtex = 0;
        mat->shininess = 40;
 
-       // mat->name = std::string(amat->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