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;
}
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);
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());
}
}
- node_by_name[node->get_name()] = node;
+ ldata->node_by_name[node->get_name()] = node;
return node;
}