quick backup of the finished scene loader before I submit other parts
[demo] / src / scene.cc
index e53e5a3..2dc20bc 100644 (file)
@@ -25,24 +25,28 @@ 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 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)
                delete meshes[i];
        meshes.clear();
 
-       /* clear materials */
        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)
@@ -55,7 +59,7 @@ bool Scene::load(const char *fname)
                return false;
        }
 
-       /* loading scene meshes */
+       /* load meshes */
        for(unsigned int i=0; i<scene->mNumMeshes; ++i) {
                Mesh *mesh = load_mesh(scene, i);
                if(!mesh) {
@@ -65,7 +69,7 @@ bool Scene::load(const char *fname)
                meshes.push_back(mesh);
        }
 
-       /* loading materials */
+       /* load materials */
        for(unsigned int i=0; i<scene->mNumMaterials; ++i) {
                Material *material = load_material(scene, this, i);
                if(!material) {
@@ -76,10 +80,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);
+}
 
-       aiReleaseImport(scene);
-       return true;
+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);
+       }
+
+       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)
@@ -133,8 +178,7 @@ 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 {
@@ -164,6 +208,7 @@ static Mesh *load_mesh(const aiScene *scene, unsigned int index)
        else
                fprintf(stderr, "No faces found.\n");
 
+       mesh->mat_idx = amesh->mMaterialIndex;
        return mesh;
 }
 
@@ -179,7 +224,9 @@ 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);