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;
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;
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;
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;
static void update(float dt)
{
texman.update();
+ sceneman.update();
- scn->update(dt);
+ mscn->update(dt);
float speed = walk_speed * dt;
Vec3 dir;
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);
glDepthMask(0);
glColor3f(0.3, 0.08, 0.01);
- scn->walk_mesh->draw();
+ mscn->walk_mesh->draw();
glDepthMask(1);
#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) {
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;
// 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");
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) {
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;
}
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
}
}
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
#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_
#include "mesh.h"
#include "snode.h"
#include "texture.h"
+#include "dataset.h"
enum {
SCNLOAD_FLIPYZ = 1,
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_
#include <stdio.h>
#include <assert.h>
+#include <string>
#include <vector>
#include <map>
#include <gmath/gmath.h>
struct LoaderData {
const aiScene *aiscn;
+ std::string fname;
std::map<std::string, SceneNode*> node_by_name;
std::map<aiMesh*, Mesh*> mesh_by_aimesh;
};
LoaderData *ldata = new LoaderData;
ldata->aiscn = aiscn;
+ ldata->fname = std::string(fname);
loader_data = (void*)ldata;
}
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++) {
}
}
+ 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;
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;
+}