quick backup of the finished scene loader before I submit other parts
authorEleni Maria Stea <estea@igalia.com>
Tue, 11 Jul 2017 07:20:12 +0000 (10:20 +0300)
committerEleni Maria Stea <estea@igalia.com>
Tue, 11 Jul 2017 07:20:12 +0000 (10:20 +0300)
changes

*Note: I made a change to simplify the recursive create_object function.
Since most nodes contain only one mesh, there's no point to iterate
through meshes, we just choose the first one available.

Also: despite the fact that our 3d model is flat (no node hierarchy) we
calculate its modelling transformation recursively (as a product of its
local transform with the accumulative transformation of its parent
nodes), this way we can safely replace the models anytime.

src/main.cc
src/object.cc
src/object.h
src/scene.cc

index 2926420..dc3440d 100644 (file)
@@ -3,6 +3,10 @@
 #include <string.h>
 #include <vector>
 
+#include "object.h"
+#include "mesh.h"
+#include "scene.h"
+
 #include "opengl/opengl.h"
 #include "vulkan/vk.h"
 
@@ -20,6 +24,7 @@ bool use_vulkan;
 GLFWwindow *win;
 
 /* variables */
+static Scene scene;
 
 int main(int argc, char **argv)
 {
@@ -66,6 +71,18 @@ static bool init()
                        return false;
        }
 
+       if(!scene.load("data/spot/spot_control_mesh.obj")) {
+               fprintf(stderr, "Failed to load scene.\n");
+               return false;
+       }
+
+       for(size_t i=0; i<scene.objects.size(); ++i) {
+               printf("object: %d\n", (int)i);
+               printf("mesh: %s\n", scene.objects[i]->mesh->name.c_str());
+               printf("material: %s\n", scene.objects[i]->material->name.c_str());
+               printf("transform:\n");
+               scene.objects[i]->transform.print();
+       }
        return true;
 }
 
index 7b6292d..acb5240 100644 (file)
@@ -10,5 +10,4 @@ Object::Object()
 
 Object::~Object()
 {
-       delete mesh;
 }
\ No newline at end of file
index 220e1d7..57aef84 100644 (file)
@@ -21,6 +21,7 @@ struct Material {
        float shininess;
 
        Texture *dtex; // diffuse
+       std::string name;
 };
 
 class Object {
index 7f9a879..2dc20bc 100644 (file)
@@ -25,6 +25,9 @@ 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()
@@ -56,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) {
@@ -66,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) {
@@ -77,16 +80,51 @@ bool Scene::load(const char *fname)
        }
 
        /* 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)
@@ -140,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 {
@@ -172,7 +209,6 @@ static Mesh *load_mesh(const aiScene *scene, unsigned int index)
                fprintf(stderr, "No faces found.\n");
 
        mesh->mat_idx = amesh->mMaterialIndex;
-       printf("material idx:%u", mesh->mat_idx);
        return mesh;
 }
 
@@ -188,9 +224,9 @@ static Material *load_material(const aiScene *ascene, Scene *scene, unsigned int
        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);