metadata, walk polygons, stuff...
[laserbrain_demo] / src / metascene.cc
1 #include "metascene.h"
2 #include "scene.h"
3 #include "datamap.h"
4 #include "treestore.h"
5
6 #ifdef WIN32
7 #include <malloc.h>
8 #else
9 #include <alloca.h>
10 #endif
11
12 static bool proc_node(Scene *scn, struct ts_node *node);
13 static bool proc_scenefile(Scene *scn, struct ts_node *node);
14 static struct ts_attr *attr_inscope(struct ts_node *node, const char *name);
15
16 static void print_scene_graph(SceneNode *n, int level);
17
18 bool load_scene(Scene *scn, const char *fname)
19 {
20         struct ts_node *root = ts_load(fname);
21         if(!root || strcmp(root->name, "scene") != 0) {
22                 ts_free_tree(root);
23                 fprintf(stderr, "failed to load scene metadata: %s\n", fname);
24                 return false;
25         }
26
27         bool res = proc_node(scn, root);
28         ts_free_tree(root);
29
30         printf("loaded scene: %s\n", fname);
31         printf("scene graph:\n");
32         print_scene_graph(scn->nodes, 0);
33         return res;
34 }
35
36 static bool proc_node(Scene *scn, struct ts_node *node)
37 {
38         struct ts_node *c = node->child_list;
39         while(c) {
40                 if(!proc_node(scn, c)) {
41                         return false;
42                 }
43                 c = c->next;
44         }
45
46         // do this last to allow other contents of the node to do their thing
47         if(strcmp(node->name, "scenefile") == 0) {
48                 return proc_scenefile(scn, node);
49
50         } else if(strcmp(node->name, "remap") == 0) {
51                 const char *match = ts_get_attr_str(node, "match");
52                 const char *replace = ts_get_attr_str(node, "replace");
53                 if(match && replace) {
54                         datamap_map(match, replace);
55                 }
56         }
57
58         return true;
59 }
60
61 static bool proc_scenefile(Scene *scn, struct ts_node *node)
62 {
63         const char *fname = ts_get_attr_str(node, "file");
64         if(fname) {
65                 // datapath
66                 struct ts_attr *adpath = attr_inscope(node, "datapath");
67                 if(adpath && adpath->val.type == TS_STRING) {
68                         printf("adding data path: %s\n", adpath->val.str);
69                         datamap_set_path(adpath->val.str);
70                 }
71
72                 // walkmesh
73                 char *walkmesh_regexp = 0;
74                 struct ts_attr *awmesh = attr_inscope(node, "walkmesh");
75                 if(awmesh && awmesh->val.type == TS_STRING) {
76                         walkmesh_regexp = awmesh->val.str;
77                 }
78
79                 int namesz = datamap_lookup(fname, 0, 0);
80                 char *namebuf = (char*)alloca(namesz + 1);
81                 if(datamap_lookup(fname, namebuf, namesz + 1)) {
82                         fname = namebuf;
83                 }
84
85                 if(!(scn->load(fname, SCNLOAD_FLIPTEX))) {
86                         return false;
87                 }
88
89                 // extract the walk mesh if necessary
90                 // XXX as written, this will match even objects loaded by previous scenefile blocks
91                 Scene *wscn;
92                 if(walkmesh_regexp && (wscn = scn->extract_nodes(walkmesh_regexp))) {
93                         // apply all transformations to the meshes
94                         wscn->apply_xform();
95
96                         int nmeshes = wscn->meshes.size();
97                         for(int i=0; i<nmeshes; i++) {
98                                 Mesh *m = wscn->meshes[i];
99
100                                 if(scn->walk_mesh) {
101                                         scn->walk_mesh->append(*m);
102                                 } else {
103                                         scn->walk_mesh = m;
104                                         wscn->remove_mesh(m);   // to save it from destruction
105                                 }
106                         }
107
108                         delete wscn;
109                 }
110         }
111         datamap_reset();
112
113         return true;
114 }
115
116 static struct ts_attr *attr_inscope(struct ts_node *node, const char *name)
117 {
118         struct ts_attr *attr = 0;
119
120         while(node && !(attr = ts_get_attr(node, name))) {
121                 node = node->parent;
122         }
123         return attr;
124 }
125
126 static void print_scene_graph(SceneNode *n, int level)
127 {
128         if(!n) return;
129
130         for(int i=0; i<level; i++) {
131                 fputs("  ", stdout);
132         }
133
134         int nobj = n->get_num_objects();
135         if(nobj) {
136                 printf("%s - %d obj\n", n->get_name(), n->get_num_objects());
137         } else {
138                 printf("%s\n", n->get_name());
139         }
140
141         for(int i=0; i<n->get_num_children(); i++) {
142                 print_scene_graph(n->get_child(i), level + 1);
143         }
144 }