separated scene loading into IO and GL parts in preparation for resman
authorJohn Tsiombikas <nuclear@mutantstargoat.com>
Thu, 1 Dec 2016 03:01:48 +0000 (05:01 +0200)
committerJohn Tsiombikas <nuclear@mutantstargoat.com>
Thu, 1 Dec 2016 03:01:48 +0000 (05:01 +0200)
src/scene.h
src/sceneload.cc

index a8c8e6a..ece454e 100644 (file)
@@ -9,7 +9,10 @@
 
 enum {
        SCNLOAD_FLIPYZ = 1,
-       SCNLOAD_FLIPTEX = 2
+       SCNLOAD_FLIPTEX = 2,
+
+       SCNLOAD_STAGE_IO = 0x4000,
+       SCNLOAD_STAGE_GL = 0x8000
 };
 
 class Scene {
@@ -25,6 +28,7 @@ public:
        Mesh *walk_mesh;
 
        TextureSet *texset;     // only owned by Scene if own_texset is true
+       void *loader_data;
 
        explicit Scene(TextureSet *tset = 0);
        ~Scene();
index 6e959b2..7fdc004 100644 (file)
@@ -33,85 +33,114 @@ static long assimp_time(const aiAnimation *anim, double aitime);
 static void print_hierarchy(const aiNode *node);
 */
 
-static std::map<std::string, SceneNode*> node_by_name;
-static std::map<aiMesh*, Mesh*> mesh_by_aimesh;
+struct LoaderData {
+       const aiScene *aiscn;
+       std::map<std::string, SceneNode*> node_by_name;
+       std::map<aiMesh*, Mesh*> mesh_by_aimesh;
+};
+
+#define LD_STAGE_MASK  0xf000
 
 bool Scene::load(const char *fname, unsigned int flags)
 {
-       unsigned int ppflags = aiProcess_CalcTangentSpace |
-               aiProcess_GenNormals |
-               aiProcess_JoinIdenticalVertices |
-               aiProcess_Triangulate |
-               aiProcess_SortByPType |
-               aiProcess_GenUVCoords |
-               //aiProcess_PreTransformVertices |
-               aiProcess_TransformUVCoords;
-
-       if(flags & SCNLOAD_FLIPTEX) {
-               ppflags |= aiProcess_FlipUVs;
+       if((flags & LD_STAGE_MASK) == 0) {
+               // not passing either of the stage specifiers, means do the whole job
+               flags |= LD_STAGE_MASK;
        }
 
-       info_log("Loading scene file: %s\n", fname);
-
-       const aiScene *aiscn = aiImportFile(fname, ppflags);
-       if(!aiscn) {
-               error_log("failed to load scene file: %s\n", fname);
-               return false;
-       }
+       // first perform I/O and all operations not requiring access to an OpenGL context
+       if(flags & SCNLOAD_STAGE_IO) {
+               unsigned int ppflags = aiProcess_CalcTangentSpace |
+                       aiProcess_GenNormals |
+                       aiProcess_JoinIdenticalVertices |
+                       aiProcess_Triangulate |
+                       aiProcess_SortByPType |
+                       aiProcess_GenUVCoords |
+                       //aiProcess_PreTransformVertices |
+                       aiProcess_TransformUVCoords;
+
+               if(flags & SCNLOAD_FLIPTEX) {
+                       ppflags |= aiProcess_FlipUVs;
+               }
 
-       // assimp adds its own root node, which might have transformations
-       Vec3 root_pos, root_scaling(1.0, 1.0, 1.0);
-       Quat root_rot;
+               info_log("Loading scene file: %s\n", fname);
 
-       if(aiscn->mRootNode) {
-               Mat4 root_matrix = assimp_matrix(aiscn->mRootNode->mTransformation);
-               root_pos = root_matrix.get_translation();
-               root_rot = root_matrix.get_rotation();
-               root_scaling = root_matrix.get_scaling();
-       }
+               const aiScene *aiscn = aiImportFile(fname, ppflags);
+               if(!aiscn) {
+                       error_log("failed to load scene file: %s\n", fname);
+                       return false;
+               }
 
-       // load all meshes
-       for(unsigned int i=0; i<aiscn->mNumMeshes; i++) {
-               aiMesh *aimesh = aiscn->mMeshes[i];
-               Mesh *mesh;
+               // assimp adds its own root node, which might have transformations
+               Vec3 root_pos, root_scaling(1.0, 1.0, 1.0);
+               Quat root_rot;
 
-               switch(aimesh->mPrimitiveTypes) {
-               case aiPrimitiveType_TRIANGLE:
-                       if((mesh = load_mesh(this, aiscn, flags, aimesh))) {
-                               mesh_by_aimesh[aimesh] = mesh;
-                               meshes.push_back(mesh);
-                       }
-                       break;
+               if(aiscn->mRootNode) {
+                       Mat4 root_matrix = assimp_matrix(aiscn->mRootNode->mTransformation);
+                       root_pos = root_matrix.get_translation();
+                       root_rot = root_matrix.get_rotation();
+                       root_scaling = root_matrix.get_scaling();
+               }
 
-               default:
-                       error_log("unsupported primitive type: %u\n", aimesh->mPrimitiveTypes);
-                       break;
+               if(!nodes) {
+                       nodes = new SceneNode;
+                       nodes->scene = this;
+                       nodes->set_name("root");
+                       nodes->set_position(root_pos);
+                       nodes->set_rotation(root_rot);
+                       nodes->set_scaling(root_scaling);
                }
-       }
 
-       if(!nodes) {
-               nodes = new SceneNode;
-               nodes->scene = this;
-               nodes->set_name("root");
-               nodes->set_position(root_pos);
-               nodes->set_rotation(root_rot);
-               nodes->set_scaling(root_scaling);
+               LoaderData *ldata = new LoaderData;
+               ldata->aiscn = aiscn;
+               loader_data = (void*)ldata;
        }
 
-       // load all the nodes recursively
-       for(unsigned int i=0; i<aiscn->mRootNode->mNumChildren; i++) {
-               SceneNode *node = load_node(this, aiscn, flags, aiscn->mRootNode->mChildren[i]);
-               if(node) {
-                       nodes->add_child(node);
+       /* then, assuming we have successfully loaded everything, proceed to construct
+        * all the engine objects, which require access to the OpenGL context
+        */
+       if(flags & SCNLOAD_STAGE_GL) {
+               if(!loader_data) {
+                       error_log("second stage scene loader failed to find valid I/O data\n");
+                       return false;
+               }
+
+               LoaderData *ldata = (LoaderData*)loader_data;
+               const aiScene *aiscn = ldata->aiscn;
+
+               // load all meshes
+               for(unsigned int i=0; i<aiscn->mNumMeshes; i++) {
+                       aiMesh *aimesh = aiscn->mMeshes[i];
+                       Mesh *mesh;
+
+                       switch(aimesh->mPrimitiveTypes) {
+                       case aiPrimitiveType_TRIANGLE:
+                               if((mesh = load_mesh(this, aiscn, flags, aimesh))) {
+                                       ldata->mesh_by_aimesh[aimesh] = mesh;
+                                       meshes.push_back(mesh);
+                               }
+                               break;
+
+                       default:
+                               error_log("unsupported primitive type: %u\n", aimesh->mPrimitiveTypes);
+                               break;
+                       }
                }
-       }
 
-       node_by_name.clear();
-       mesh_by_aimesh.clear();
+               // load all the nodes recursively
+               for(unsigned int i=0; i<aiscn->mRootNode->mNumChildren; i++) {
+                       SceneNode *node = load_node(this, aiscn, flags, aiscn->mRootNode->mChildren[i]);
+                       if(node) {
+                               nodes->add_child(node);
+                       }
+               }
 
-       aiReleaseImport(aiscn);
-       info_log("loaded scene file: %s, %d meshes\n", fname, (int)meshes.size());
-       nodes->update(0);
+               aiReleaseImport(aiscn);
+               delete ldata;
+               loader_data = 0;
+               info_log("loaded scene file: %s, %d meshes\n", fname, (int)meshes.size());
+               nodes->update(0);
+       }
        return true;
 }
 
@@ -182,6 +211,8 @@ static bool load_material(Scene *scn, Material *mat, const aiMaterial *aimat)
 
 static SceneNode *load_node(Scene *scn, const aiScene *aiscn, unsigned int flags, const aiNode *ainode)
 {
+       LoaderData *ldata = (LoaderData*)scn->loader_data;
+
        SceneNode *node = new SceneNode;
        node->set_name(ainode->mName.data);
 
@@ -200,7 +231,7 @@ static SceneNode *load_node(Scene *scn, const aiScene *aiscn, unsigned int flags
        for(unsigned int i=0; i<ainode->mNumMeshes; i++) {
                aiMesh *aimesh = aiscn->mMeshes[ainode->mMeshes[i]];
 
-               Mesh *mesh = mesh_by_aimesh[aimesh];
+               Mesh *mesh = ldata->mesh_by_aimesh[aimesh];
                if(mesh) {
                        ObjMesh *obj = new ObjMesh;
                        obj->set_name(mesh->get_name());
@@ -221,7 +252,7 @@ static SceneNode *load_node(Scene *scn, const aiScene *aiscn, unsigned int flags
                }
        }
 
-       node_by_name[node->get_name()] = node;
+       ldata->node_by_name[node->get_name()] = node;
        return node;
 }