MetaScene class
authorJohn Tsiombikas <nuclear@mutantstargoat.com>
Fri, 2 Dec 2016 00:16:09 +0000 (02:16 +0200)
committerJohn Tsiombikas <nuclear@mutantstargoat.com>
Fri, 2 Dec 2016 00:16:09 +0000 (02:16 +0200)
src/app.cc
src/metascene.cc
src/metascene.h
src/scene.h
src/sceneload.cc

index a1936b2..f92899d 100644 (file)
@@ -49,7 +49,8 @@ static float joy_deadzone = 0.01;
 
 static Mat4 view_matrix, mouse_view_matrix, proj_matrix;
 static TextureSet texman;
-static Scene *scn;
+static SceneSet sceneman;
+static MetaScene *mscn;
 static unsigned int sdr_post_gamma;
 
 static long prev_msec;
@@ -97,20 +98,13 @@ bool app_init(int argc, char **argv)
 
        glClearColor(0.2, 0.2, 0.2, 1.0);
 
-       scn = new Scene(&texman);
-       if(!load_scene(scn, opt.scenefile ? opt.scenefile : "data/museum.scene")) {
+       mscn = new MetaScene(&sceneman, &texman);
+       if(!mscn->load(opt.scenefile ? opt.scenefile : "data/museum.scene")) {
                return false;
        }
 
-       // set initial cam_pos above the center of the walk mesh (if any)
-       if(scn->walk_mesh) {
-               Vec3 bcent;
-               float brad;
-               scn->walk_mesh->get_bsphere(&bcent, &brad);
-
-               floor_y = bcent.y;
-               cam_pos = bcent + Vec3(0, user_eye_height, 0);
-       }
+       cam_pos = mscn->start_pos;
+       // TODO use start_rot
 
        if(!(sdr_ltmap_notex = create_program_load("sdr/lightmap.v.glsl", "sdr/lightmap-notex.p.glsl"))) {
                return false;
@@ -140,12 +134,14 @@ void app_cleanup()
        if(opt.vr) {
                goatvr_shutdown();
        }
+
        texman.clear();
+       sceneman.clear();
 }
 
 static bool constrain_walk_mesh(const Vec3 &v, Vec3 *newv)
 {
-       Mesh *wm = scn->walk_mesh;
+       Mesh *wm = mscn->walk_mesh;
        if(!wm) {
                *newv = v;
                return true;
@@ -153,7 +149,7 @@ static bool constrain_walk_mesh(const Vec3 &v, Vec3 *newv)
 
        Ray downray = Ray(v, Vec3(0, -1, 0));
        HitPoint hit;
-       if(scn->walk_mesh->intersect(downray, &hit)) {
+       if(mscn->walk_mesh->intersect(downray, &hit)) {
                *newv = hit.pos;
                newv->y += user_eye_height;
                return true;
@@ -164,8 +160,9 @@ static bool constrain_walk_mesh(const Vec3 &v, Vec3 *newv)
 static void update(float dt)
 {
        texman.update();
+       sceneman.update();
 
-       scn->update(dt);
+       mscn->update(dt);
 
        float speed = walk_speed * dt;
        Vec3 dir;
@@ -329,9 +326,9 @@ static void draw_scene()
        set_light(1, lpos[1], Vec3(0.6, 0.7, 1.0) * 0.6);
        set_light(2, lpos[2], Vec3(0.8, 1.0, 0.8) * 0.3);
 
-       scn->draw();
+       mscn->draw();
 
-       if(show_walk_mesh && scn->walk_mesh) {
+       if(show_walk_mesh && mscn->walk_mesh) {
                glPushAttrib(GL_ENABLE_BIT);
                glEnable(GL_BLEND);
                glBlendFunc(GL_ONE, GL_ONE);
@@ -344,7 +341,7 @@ static void draw_scene()
                glDepthMask(0);
 
                glColor3f(0.3, 0.08, 0.01);
-               scn->walk_mesh->draw();
+               mscn->walk_mesh->draw();
 
                glDepthMask(1);
 
index b92e31f..65c9d66 100644 (file)
 #include <alloca.h>
 #endif
 
-static bool proc_node(Scene *scn, struct ts_node *node);
-static bool proc_scenefile(Scene *scn, struct ts_node *node);
+static bool proc_node(MetaScene *mscn, struct ts_node *node);
+static bool proc_scenefile(MetaScene *mscn, struct ts_node *node);
 static bool proc_mtledit(Scene *scn, struct ts_node *node);
 static struct ts_attr *attr_inscope(struct ts_node *node, const char *name);
 
 static void print_scene_graph(SceneNode *n, int level);
 
-bool load_scene(Scene *scn, const char *fname)
+
+MetaScene::MetaScene(SceneSet *sman, TextureSet *tman)
+{
+       sceneman = sman;
+       texman = tman;
+       walk_mesh = 0;
+}
+
+MetaScene::~MetaScene()
+{
+       delete walk_mesh;
+}
+
+
+bool MetaScene::load(const char *fname)
 {
        struct ts_node *root = ts_load(fname);
        if(!root || strcmp(root->name, "scene") != 0) {
@@ -27,20 +41,37 @@ bool load_scene(Scene *scn, const char *fname)
                return false;
        }
 
-       bool res = proc_node(scn, root);
+       bool res = proc_node(this, root);
        ts_free_tree(root);
 
-       info_log("loaded scene: %s\n", fname);
+       /*info_log("loaded scene: %s\n", fname);
        info_log("scene graph:\n");
        print_scene_graph(scn->nodes, 0);
+       */
        return res;
 }
 
-static bool proc_node(Scene *scn, struct ts_node *node)
+void MetaScene::update(float dt)
+{
+       int nscn = scenes.size();
+       for(int i=0; i<nscn; i++) {
+               scenes[i]->update(dt);
+       }
+}
+
+void MetaScene::draw() const
+{
+       int nscn = scenes.size();
+       for(int i=0; i<nscn; i++) {
+               scenes[i]->draw();
+       }
+}
+
+static bool proc_node(MetaScene *mscn, struct ts_node *node)
 {
        struct ts_node *c = node->child_list;
        while(c) {
-               if(!proc_node(scn, c)) {
+               if(!proc_node(mscn, c)) {
                        return false;
                }
                c = c->next;
@@ -48,7 +79,7 @@ static bool proc_node(Scene *scn, struct ts_node *node)
 
        // do this last to allow other contents of the node to do their thing
        if(strcmp(node->name, "scenefile") == 0) {
-               return proc_scenefile(scn, node);
+               return proc_scenefile(mscn, node);
 
        } else if(strcmp(node->name, "remap") == 0) {
                const char *match = ts_get_attr_str(node, "match");
@@ -61,7 +92,7 @@ static bool proc_node(Scene *scn, struct ts_node *node)
        return true;
 }
 
-static bool proc_scenefile(Scene *scn, struct ts_node *node)
+static bool proc_scenefile(MetaScene *mscn, struct ts_node *node)
 {
        const char *fname = ts_get_attr_str(node, "file");
        if(fname) {
@@ -85,7 +116,7 @@ static bool proc_scenefile(Scene *scn, struct ts_node *node)
                        fname = namebuf;
                }
 
-               Scene *newscn = new Scene(scn->texset);
+               Scene *newscn = new Scene(mscn->texman);
                if(!(newscn->load(fname, SCNLOAD_FLIPTEX))) {   // TODO unhardcode FLIPTEX
                        return false;
                }
@@ -100,10 +131,10 @@ static bool proc_scenefile(Scene *scn, struct ts_node *node)
                        for(int i=0; i<nmeshes; i++) {
                                Mesh *m = wscn->meshes[i];
 
-                               if(newscn->walk_mesh) {
-                                       newscn->walk_mesh->append(*m);
+                               if(mscn->walk_mesh) {
+                                       mscn->walk_mesh->append(*m);
                                } else {
-                                       newscn->walk_mesh = m;
+                                       mscn->walk_mesh = m;
                                        wscn->remove_mesh(m);   // to save it from destruction
                                }
                        }
@@ -118,8 +149,7 @@ static bool proc_scenefile(Scene *scn, struct ts_node *node)
                        child = child->next;
                }
 
-               scn->merge(newscn);
-               delete newscn;
+               mscn->scenes.push_back(newscn);
        }
        //datamap_reset();      // TODO this should be push/pop instead of hard reset
 
index 8d512eb..e793a39 100644 (file)
@@ -1,8 +1,27 @@
 #ifndef METASCENE_H_
 #define METASCENE_H_
 
-class Scene;
+#include "scene.h"
+#include "mesh.h"
 
-bool load_scene(Scene *scn, const char *fname);
+class MetaScene {
+public:
+       SceneSet *sceneman;
+       TextureSet *texman;
+
+       std::vector<Scene*> scenes;
+
+       Mesh *walk_mesh;
+       Vec3 start_pos;
+       Quat start_rot;
+
+       MetaScene(SceneSet *sman, TextureSet *tman);
+       ~MetaScene();
+
+       bool load(const char *fname);
+
+       void update(float dt);
+       void draw() const;
+};
 
 #endif // METASCENE_H_
index ece454e..3712ee6 100644 (file)
@@ -6,6 +6,7 @@
 #include "mesh.h"
 #include "snode.h"
 #include "texture.h"
+#include "dataset.h"
 
 enum {
        SCNLOAD_FLIPYZ = 1,
@@ -72,4 +73,16 @@ public:
        void draw() const;
 };
 
+
+class SceneSet : public DataSet<Scene*> {
+private:
+       static Scene *create_scene();
+       static bool load_scene(Scene *scn, const char *fname);
+       static bool done_scene(Scene *scn);
+       static void free_scene(Scene *scn);
+
+public:
+       SceneSet();
+};
+
 #endif // SCENE_H_
index 7fdc004..11ce1e1 100644 (file)
@@ -1,5 +1,6 @@
 #include <stdio.h>
 #include <assert.h>
+#include <string>
 #include <vector>
 #include <map>
 #include <gmath/gmath.h>
@@ -35,6 +36,7 @@ static void print_hierarchy(const aiNode *node);
 
 struct LoaderData {
        const aiScene *aiscn;
+       std::string fname;
        std::map<std::string, SceneNode*> node_by_name;
        std::map<aiMesh*, Mesh*> mesh_by_aimesh;
 };
@@ -93,6 +95,7 @@ bool Scene::load(const char *fname, unsigned int flags)
 
                LoaderData *ldata = new LoaderData;
                ldata->aiscn = aiscn;
+               ldata->fname = std::string(fname);
                loader_data = (void*)ldata;
        }
 
@@ -107,6 +110,7 @@ bool Scene::load(const char *fname, unsigned int flags)
 
                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++) {
@@ -135,10 +139,11 @@ bool Scene::load(const char *fname, unsigned int flags)
                        }
                }
 
+               info_log("loaded scene file: %s, %d meshes\n", fname, (int)meshes.size());
+
                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;
@@ -355,3 +360,31 @@ static Mat4 assimp_matrix(const aiMatrix4x4 &aim)
        memcpy(m[0], &aim, 16 * sizeof(float));
        return transpose(m);
 }
+
+
+// --- SceneSet ---
+
+SceneSet::SceneSet()
+       : DataSet<Scene*>(create_scene, load_scene, done_scene, free_scene)
+{
+}
+
+Scene *SceneSet::create_scene()
+{
+       return new Scene;
+}
+
+bool SceneSet::load_scene(Scene *scn, const char *fname)
+{
+       return scn->load(fname, SCNLOAD_FLIPTEX | SCNLOAD_STAGE_IO);
+}
+
+bool SceneSet::done_scene(Scene *scn)
+{
+       return scn->load(0, SCNLOAD_STAGE_GL);
+}
+
+void SceneSet::free_scene(Scene *scn)
+{
+       delete scn;
+}