X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Fscene.cc;h=f116150396068e9a841a025dadbd13a3610a095b;hb=d4d7f73284783d2a50d71014789d196bef7d0e0e;hp=27be807f47069b1602964c2679d3635e9f89905d;hpb=b7c92831285013b2a0783bccaf3d900545ebb5ba;p=laserbrain_demo diff --git a/src/scene.cc b/src/scene.cc index 27be807..f116150 100644 --- a/src/scene.cc +++ b/src/scene.cc @@ -1,10 +1,22 @@ +#include #include "scene.h" +#include "objmesh.h" static void destroy_node_tree(SceneNode *n); -Scene::Scene() +Scene::Scene(TextureSet *tset) { nodes = 0; + + walk_mesh = 0; + + if(tset) { + texset = tset; + own_texset = false; + } else { + texset = new TextureSet; + own_texset = true; + } } Scene::~Scene() @@ -16,10 +28,215 @@ void Scene::destroy() { destroy_node_tree(nodes); nodes = 0; + + for(int i=0; i<(int)meshes.size(); i++) { + delete meshes[i]; + } + meshes.clear(); + + delete walk_mesh; + walk_mesh = 0; + + for(int i=0; i<(int)objects.size(); i++) { + delete objects[i]; + } + objects.clear(); + + if(own_texset) { + delete texset; + } + texset = 0; +} + +static void destroy_node_tree(SceneNode *n) +{ + if(!n) return; + + int nsub = n->get_num_children(); + for(int i=0; iget_child(i)); + } + delete n; } // Scene::load defined in sceneload.cc +bool Scene::merge(Scene *scn) +{ + if(texset != scn->texset) { + // TODO handle this properly + error_log("for now only able to merge scenes using the same texture set\n"); + return false; + } + + if(walk_mesh) { + if(scn->walk_mesh) { + walk_mesh->append(*scn->walk_mesh); + delete scn->walk_mesh; + scn->walk_mesh = 0; + } + } else { + walk_mesh = scn->walk_mesh; + scn->walk_mesh = 0; + } + + int nmeshes = scn->meshes.size(); + for(int i=0; imeshes[i]); + } + scn->meshes.clear(); + + int nobj = scn->objects.size(); + for(int i=0; iobjects[i]); + } + scn->objects.clear(); + + if(nodes) { + int nchildren = scn->nodes ? scn->nodes->get_num_children() : 0; + for(int i=0; inodes->get_child(i); + scn->nodes->remove_child(n); + nodes->add_child(n); + } + if(scn->nodes && scn->nodes->get_num_objects() > 0) { + warning_log("merging with scene which has objects in its root node. these objects will not be merged!\n"); + } + delete scn->nodes; + } else { + nodes = scn->nodes; + } + scn->nodes = 0; + + return true; +} + +void Scene::add_object(Object *obj) +{ + objects.push_back(obj); +} + +bool Scene::remove_object(Object *obj) +{ + std::vector::iterator it = std::find(objects.begin(), objects.end(), obj); + if(it != objects.end()) { + objects.erase(it); + return true; + } + return false; +} + +bool Scene::have_object(Object *obj) const +{ + return std::find(objects.begin(), objects.end(), obj) != objects.end(); +} + +void Scene::add_mesh(Mesh *m) +{ + meshes.push_back(m); +} + +bool Scene::remove_mesh(Mesh *m) +{ + std::vector::iterator it = std::find(meshes.begin(), meshes.end(), m); + if(it != meshes.end()) { + meshes.erase(it); + return true; + } + return false; +} + +bool Scene::have_mesh(Mesh *m) const +{ + return std::find(meshes.begin(), meshes.end(), m) != meshes.end(); +} + +void Scene::add_node(SceneNode *n) +{ + // we always want to have a dedicated root node + if(!nodes) { + nodes = new SceneNode; + nodes->scene = this; + nodes->set_name("root"); + } + + nodes->add_child(n); +} + +bool Scene::remove_node(SceneNode *n) +{ + SceneNode *par; + if(!n || !(par = n->get_parent())) { + return false; + } + + int nsub = n->get_num_children(); + for(int i=0; iget_child(i); + n->remove_child(c); + par->add_child(c); + } + + return par->remove_child(n); +} + +bool Scene::have_node(SceneNode *n) const +{ + return n->scene == this; +} + +static void find_nodes_rec(std::list *res, SceneNode *tree, const std::regex &re) +{ + if(std::regex_match(tree->get_name(), re)) { + res->push_back(tree); + } + + int num = tree->get_num_children(); + for(int i=0; iget_child(i), re); + } +} + +Scene *Scene::extract_nodes(const char *qstr) +{ + std::regex re{qstr}; + + std::list nodelist; + find_nodes_rec(&nodelist, nodes, re); + if(nodelist.empty()) { + return 0; + } + + Scene *res = new Scene(texset); + + for(SceneNode *n : nodelist) { + + int nobj = n->get_num_objects(); + for(int i=0; iget_object(i); + if(obj->get_type() == OBJ_MESH) { + // XXX this assumes that meshes aren't shared between objects. + // maybe we'll have to refcount them at some point, and copy if nref>1 + ObjMesh *om = (ObjMesh*)obj; + remove_mesh(om->mesh); + res->add_mesh(om->mesh); + } + + remove_object(obj); + res->add_object(obj); + } + + remove_node(n); + res->add_node(n); + } + return res; +} + +void Scene::apply_xform() +{ + nodes->apply_xform(); +} + void Scene::update(float dt) { if(nodes) { @@ -50,14 +267,3 @@ void Scene::draw() const } } } - -static void destroy_node_tree(SceneNode *n) -{ - if(!n) return; - - int nsub = n->get_num_children(); - for(int i=0; iget_child(i)); - } - delete n; -}