assman was renamed to assfile
[laserbrain_demo] / src / sceneload.cc
index ad6e61e..a488385 100644 (file)
@@ -5,6 +5,7 @@
 #include <map>
 #include <gmath/gmath.h>
 #include <assimp/cimport.h>
+#include <assimp/cfileio.h>
 #include <assimp/postprocess.h>
 #include <assimp/scene.h>
 #include <assimp/mesh.h>
@@ -13,6 +14,8 @@
 #include <assimp/vector3.h>
 #include <assimp/matrix4x4.h>
 #include <assimp/quaternion.h>
+#include "assfile.h"
+#include "app.h"
 #include "scene.h"
 #include "objmesh.h"
 #include "datamap.h"
@@ -25,7 +28,7 @@ static Mesh *load_mesh(Scene *scn, const aiScene *aiscn, unsigned int flags, con
 /*static const char *mprop_semantic(int x);
 static int count_textures(const aiMaterial *aimat);*/
 static int assimp_textype(aiTextureType type);
-static const char *assimp_textypestr(aiTextureType type);
+//static const char *assimp_textypestr(aiTextureType type);
 
 static Mat4 assimp_matrix(const aiMatrix4x4 &aim);
 
@@ -35,6 +38,13 @@ static long assimp_time(const aiAnimation *anim, double aitime);
 static void print_hierarchy(const aiNode *node);
 */
 
+static aiFile *io_open(aiFileIO *io, const char *fname, const char *mode);
+static void io_close(aiFileIO *io, aiFile *aifp);
+static size_t io_read(aiFile *aifp, char *buf, size_t size, size_t count);
+static size_t io_tell(aiFile *aifp);
+static size_t io_filesize(aiFile *aifp);
+static aiReturn io_seek(aiFile *aifp, size_t offs, aiOrigin whence);
+
 struct LoaderData {
        const aiScene *aiscn;
        std::string fname;
@@ -67,13 +77,41 @@ bool Scene::load(const char *fname, unsigned int flags)
                }
 
                info_log("Loading scene file: %s\n", fname);
+               if(this->name.empty()) {
+                       this->name = std::string(fname);
+               }
+
+               aiFileIO io;
+               io.OpenProc = io_open;
+               io.CloseProc = io_close;
 
-               const aiScene *aiscn = aiImportFile(fname, ppflags);
+               const aiScene *aiscn = aiImportFileEx(fname, ppflags, &io);
                if(!aiscn) {
                        error_log("failed to load scene file: %s\n", fname);
                        return false;
                }
 
+               LoaderData *ldata = new LoaderData;
+               ldata->aiscn = aiscn;
+               ldata->fname = std::string(fname);
+               loader_data = (void*)ldata;
+       }
+
+       /* 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;
+               fname = ldata->fname.c_str();
+
+               clear();        // clear any previous data (TODO: add flag for not clearing)
+
                // assimp adds its own root node, which might have transformations
                Vec3 root_pos, root_scaling(1.0, 1.0, 1.0);
                Quat root_rot;
@@ -94,25 +132,6 @@ bool Scene::load(const char *fname, unsigned int flags)
                        nodes->set_scaling(root_scaling);
                }
 
-               LoaderData *ldata = new LoaderData;
-               ldata->aiscn = aiscn;
-               ldata->fname = std::string(fname);
-               loader_data = (void*)ldata;
-       }
-
-       /* 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;
-               fname = ldata->fname.c_str();
-
                // load all meshes
                for(unsigned int i=0; i<aiscn->mNumMeshes; i++) {
                        aiMesh *aimesh = aiscn->mMeshes[i];
@@ -199,10 +218,11 @@ static bool load_material(Scene *scn, Material *mat, const aiMaterial *aimat)
                                *dptr++ = *sptr == '\\' ? '/' : *sptr;
                        } while(*sptr++);
 
+                       if(!fname || !*fname) continue;
+
                        int textype = assimp_textype(aitype);
-                       info_log("loading %s texture: %s\n", assimp_textypestr(aitype), fname);
 
-                       Texture *tex = scn->texset->get_texture(fname, TEX_2D, &scn->datamap);
+                       Texture *tex = texman.get_texture(fname, TEX_2D, &scn->datamap);
                        assert(tex);
                        mat->textures.push_back(tex);
 
@@ -328,14 +348,14 @@ static int assimp_textype(aiTextureType type)
        case aiTextureType_EMISSIVE:
                return MTL_TEX_LIGHTMAP;
        case aiTextureType_REFLECTION:
-               return MTL_TEX_ENVMAP;
+               return MTL_TEX_REFLECT;
        default:
                break;
        }
        return MTL_TEX_UNKNOWN;
 }
 
-static const char *assimp_textypestr(aiTextureType type)
+/*static const char *assimp_textypestr(aiTextureType type)
 {
        switch(type) {
        case aiTextureType_DIFFUSE:
@@ -353,7 +373,7 @@ static const char *assimp_textypestr(aiTextureType type)
                break;
        }
        return "unknown";
-}
+}*/
 
 static Mat4 assimp_matrix(const aiMatrix4x4 &aim)
 {
@@ -393,3 +413,59 @@ void SceneSet::free_scene(Scene *scn)
 {
        delete scn;
 }
+
+
+// ------ custom file I/O for assimp -------
+
+static aiFile *io_open(aiFileIO *io, const char *fname, const char *mode)
+{
+       ass_file *fp;
+       if(!(fp = ass_fopen(fname, mode))) {
+               error_log("failed to open scene file: %s: %s\n", fname, strerror(ass_errno));
+               return 0;
+       }
+
+       aiFile *aifp = new aiFile;
+       aifp->ReadProc = io_read;
+       aifp->WriteProc = 0;
+       aifp->TellProc = io_tell;
+       aifp->FileSizeProc = io_filesize;
+       aifp->SeekProc = io_seek;
+       aifp->FlushProc = 0;
+       aifp->UserData = (aiUserData)fp;
+       return aifp;
+}
+
+static void io_close(aiFileIO *io, aiFile *aifp)
+{
+       ass_fclose(aifp->UserData);
+       delete aifp;
+}
+
+static size_t io_read(aiFile *aifp, char *buf, size_t size, size_t count)
+{
+       return ass_fread(buf, size, count, aifp->UserData);
+}
+
+static size_t io_tell(aiFile *aifp)
+{
+       return ass_ftell(aifp->UserData);
+}
+
+static size_t io_filesize(aiFile *aifp)
+{
+       ass_file *fp = aifp->UserData;
+       long cur = ass_ftell(fp);
+       ass_fseek(fp, 0, SEEK_END);
+       long off = ass_ftell(fp);
+       ass_fseek(fp, cur, SEEK_SET);
+       return off;
+}
+
+static aiReturn io_seek(aiFile *aifp, size_t offs, aiOrigin whence)
+{
+       if(ass_fseek(aifp->UserData, offs, (int)whence) == -1) {
+               return aiReturn_FAILURE;
+       }
+       return aiReturn_SUCCESS;
+}