From c3fd483b19073f97d4d6153171dbac9744dfb65c Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 21 Sep 2004 22:21:53 +0000 Subject: [PATCH] support egg2bam -combine-geoms --- panda/src/egg2pg/config_egg2pg.cxx | 13 ++++- panda/src/egg2pg/config_egg2pg.h | 3 +- panda/src/egg2pg/load_egg_file.cxx | 10 +++- panda/src/grutil/cardMaker.cxx | 2 +- panda/src/pgraph/nodePath.cxx | 4 +- panda/src/pgraph/sceneGraphReducer.cxx | 66 +++++++++++++++++--------- panda/src/pgraph/sceneGraphReducer.h | 13 +++-- panda/src/text/textNode.cxx | 2 +- pandatool/src/bam/eggToBam.cxx | 22 +++++++-- pandatool/src/bam/eggToBam.h | 2 + 10 files changed, 100 insertions(+), 37 deletions(-) diff --git a/panda/src/egg2pg/config_egg2pg.cxx b/panda/src/egg2pg/config_egg2pg.cxx index 02924ebfb3..9afdbf98ea 100644 --- a/panda/src/egg2pg/config_egg2pg.cxx +++ b/panda/src/egg2pg/config_egg2pg.cxx @@ -46,8 +46,17 @@ bool egg_ignore_clamp = config_egg2pg.GetBool("egg-ignore-clamp", false); bool egg_ignore_decals = config_egg2pg.GetBool("egg-ignore-decals", false); bool egg_flatten = config_egg2pg.GetBool("egg-flatten", true); -// It is almost always a bad idea to set this true. -bool egg_flatten_siblings = config_egg2pg.GetBool("egg-flatten-siblings", false); +// Set this true to combine sibling GeomNodes into a single GeomNode, +// when possible. This is probably a good idea in general, but we +// have it default to false for now for historical reasons (to avoid +// breaking code that assumes this doesn't happen). Eventually the +// default will be set to true. +bool egg_combine_geoms = config_egg2pg.GetBool("egg-combine-geoms", false); + +// Set this true to combine siblings of any combinable type into a +// single Node when possible. It is almost always a bad idea to set +// this true. +bool egg_combine_siblings = config_egg2pg.GetBool("egg-combine-siblings", false); bool egg_show_collision_solids = config_egg2pg.GetBool("egg-show-collision-solids", false); diff --git a/panda/src/egg2pg/config_egg2pg.h b/panda/src/egg2pg/config_egg2pg.h index 49d94746da..2bc10ec41a 100644 --- a/panda/src/egg2pg/config_egg2pg.h +++ b/panda/src/egg2pg/config_egg2pg.h @@ -49,7 +49,8 @@ extern EXPCL_PANDAEGG bool egg_ignore_filters; extern EXPCL_PANDAEGG bool egg_ignore_clamp; extern EXPCL_PANDAEGG bool egg_ignore_decals; extern EXPCL_PANDAEGG bool egg_flatten; -extern EXPCL_PANDAEGG bool egg_flatten_siblings; +extern EXPCL_PANDAEGG bool egg_combine_geoms; +extern EXPCL_PANDAEGG bool egg_combine_siblings; extern EXPCL_PANDAEGG bool egg_show_collision_solids; extern EXPCL_PANDAEGG bool egg_load_old_curves; extern EXPCL_PANDAEGG bool egg_load_classic_nurbs_curves; diff --git a/panda/src/egg2pg/load_egg_file.cxx b/panda/src/egg2pg/load_egg_file.cxx index ff7d1d83d0..5fdd4574d2 100644 --- a/panda/src/egg2pg/load_egg_file.cxx +++ b/panda/src/egg2pg/load_egg_file.cxx @@ -36,8 +36,16 @@ load_from_loader(EggLoader &loader) { } if (loader._root != (PandaNode *)NULL && egg_flatten) { + int combine_siblings_bits = 0; + if (egg_combine_geoms) { + combine_siblings_bits |= SceneGraphReducer::CS_geom_node; + } + if (egg_combine_siblings) { + combine_siblings_bits |= ~0; + } + SceneGraphReducer gr; - int num_reduced = gr.flatten(loader._root, egg_flatten_siblings); + int num_reduced = gr.flatten(loader._root, combine_siblings_bits); egg2pg_cat.info() << "Flattened " << num_reduced << " nodes.\n"; } diff --git a/panda/src/grutil/cardMaker.cxx b/panda/src/grutil/cardMaker.cxx index 838de62f5e..09a336778f 100644 --- a/panda/src/grutil/cardMaker.cxx +++ b/panda/src/grutil/cardMaker.cxx @@ -131,7 +131,7 @@ rescale_source_geometry() { // Now flatten out the geometry as much as we can. SceneGraphReducer reducer; reducer.apply_attribs(root); - reducer.flatten(root, true); + reducer.flatten(root, ~0); return root; } diff --git a/panda/src/pgraph/nodePath.cxx b/panda/src/pgraph/nodePath.cxx index 16650d2714..1641d6df71 100644 --- a/panda/src/pgraph/nodePath.cxx +++ b/panda/src/pgraph/nodePath.cxx @@ -4523,7 +4523,7 @@ flatten_medium() { nassertr_always(!is_empty(), 0); SceneGraphReducer gr; gr.apply_attribs(node()); - int num_removed = gr.flatten(node(), false); + int num_removed = gr.flatten(node(), 0); return num_removed; } @@ -4550,7 +4550,7 @@ flatten_strong() { nassertr_always(!is_empty(), 0); SceneGraphReducer gr; gr.apply_attribs(node()); - int num_removed = gr.flatten(node(), true); + int num_removed = gr.flatten(node(), ~0); return num_removed; } diff --git a/panda/src/pgraph/sceneGraphReducer.cxx b/panda/src/pgraph/sceneGraphReducer.cxx index 0efe2d036e..18f48b5721 100644 --- a/panda/src/pgraph/sceneGraphReducer.cxx +++ b/panda/src/pgraph/sceneGraphReducer.cxx @@ -39,16 +39,17 @@ // candidate for removal if the node has no siblings and // the node has no special properties. // -// If combine_siblings is true, sibling nodes may also -// be collapsed into a single node. This will further -// reduce scene graph complexity, sometimes -// substantially, at the cost of reduced spatial -// separation. +// If combine_siblings_bits is nonzero, some sibling +// nodes (according to the bits set in +// combine_siblings_bits) may also be collapsed into a +// single node. This will further reduce scene graph +// complexity, sometimes substantially, at the cost of +// reduced spatial separation. // // Returns the number of nodes removed from the graph. //////////////////////////////////////////////////////////////////// int SceneGraphReducer:: -flatten(PandaNode *root, bool combine_siblings) { +flatten(PandaNode *root, int combine_siblings_bits) { int num_total_nodes = 0; int num_pass_nodes; @@ -63,22 +64,20 @@ flatten(PandaNode *root, bool combine_siblings) { int num_children = cr.get_num_children(); for (int i = 0; i < num_children; i++) { PandaNode *child_node = cr.get_child(i); - num_pass_nodes += r_flatten(root, child_node, combine_siblings); + num_pass_nodes += r_flatten(root, child_node, combine_siblings_bits); } - if (combine_siblings && root->get_num_children() >= 2) { - num_pass_nodes += flatten_siblings(root); + if (combine_siblings_bits != 0 && root->get_num_children() >= 2) { + num_pass_nodes += flatten_siblings(root, combine_siblings_bits); } num_total_nodes += num_pass_nodes; - // If combine_siblings is true, we should repeat the above until - // we don't get any more benefit from flattening, because each - // pass could convert cousins into siblings, which may get - // flattened next pass. If combine_siblings is not true, the - // first pass will be fully effective, and there's no point in - // trying again. - } while (combine_siblings && num_pass_nodes != 0); + // If combine_siblings_bits has CS_recurse set, we should repeat + // the above until we don't get any more benefit from flattening, + // because each pass could convert cousins into siblings, which + // may get flattened next pass. + } while ((combine_siblings_bits & CS_recurse) != 0 && num_pass_nodes != 0); return num_total_nodes; } @@ -218,7 +217,7 @@ r_apply_attribs(PandaNode *node, const AccumulatedAttribs &attribs, //////////////////////////////////////////////////////////////////// int SceneGraphReducer:: r_flatten(PandaNode *grandparent_node, PandaNode *parent_node, - bool combine_siblings) { + int combine_siblings_bits) { int num_nodes = 0; // First, recurse on each of the children. @@ -227,16 +226,22 @@ r_flatten(PandaNode *grandparent_node, PandaNode *parent_node, int num_children = cr.get_num_children(); for (int i = 0; i < num_children; i++) { PandaNode *child_node = cr.get_child(i); - num_nodes += r_flatten(parent_node, child_node, combine_siblings); + num_nodes += r_flatten(parent_node, child_node, combine_siblings_bits); } } // Now that the above loop has removed some children, the child list // saved above is no longer accurate, so hereafter we must ask the // node for its real child list. - if (combine_siblings && parent_node->get_num_children() >= 2) { + + // If we have CS_recurse set, then we flatten siblings before trying + // to flatten children. Otherwise, we flatten children first, and + // then flatten siblings, which avoids overly enthusiastic + // flattening. + if ((combine_siblings_bits & CS_recurse) != 0 && + parent_node->get_num_children() >= 2) { if (parent_node->safe_to_combine()) { - num_nodes += flatten_siblings(parent_node); + num_nodes += flatten_siblings(parent_node, combine_siblings_bits); } } @@ -260,6 +265,14 @@ r_flatten(PandaNode *grandparent_node, PandaNode *parent_node, } } + if ((combine_siblings_bits & CS_recurse) == 0 && + (combine_siblings_bits & ~CS_recurse) != 0 && + parent_node->get_num_children() >= 2) { + if (parent_node->safe_to_combine()) { + num_nodes += flatten_siblings(parent_node, combine_siblings_bits); + } + } + return num_nodes; } @@ -295,7 +308,7 @@ operator () (const PandaNode *node1, const PandaNode *node2) const { // of the indicated node that share the same properties. //////////////////////////////////////////////////////////////////// int SceneGraphReducer:: -flatten_siblings(PandaNode *parent_node) { +flatten_siblings(PandaNode *parent_node, int combine_siblings_bits) { int num_nodes = 0; // First, collect the children into groups of nodes with common @@ -312,7 +325,16 @@ flatten_siblings(PandaNode *parent_node) { int num_children = cr.get_num_children(); for (int i = 0; i < num_children; i++) { PandaNode *child_node = cr.get_child(i); - if (child_node->safe_to_combine()) { + bool safe_to_combine = child_node->safe_to_combine(); + if (safe_to_combine) { + if (child_node->is_geom_node()) { + safe_to_combine = (combine_siblings_bits & CS_geom_node) != 0; + } else { + safe_to_combine = (combine_siblings_bits & CS_other) != 0; + } + } + + if (safe_to_combine) { collected[child_node].push_back(child_node); } } diff --git a/panda/src/pgraph/sceneGraphReducer.h b/panda/src/pgraph/sceneGraphReducer.h index f0024ddc0c..3b3755cb03 100644 --- a/panda/src/pgraph/sceneGraphReducer.h +++ b/panda/src/pgraph/sceneGraphReducer.h @@ -55,19 +55,26 @@ PUBLISHED: TT_other = 0x010, }; + enum CombineSiblings { + CS_other = 0x001, + CS_geom_node = 0x002, + CS_recurse = 0x004, + }; + INLINE void apply_attribs(PandaNode *node, int attrib_types = ~0); INLINE void apply_attribs(PandaNode *node, const AccumulatedAttribs &attribs, int attrib_types, GeomTransformer &transformer); - int flatten(PandaNode *root, bool combine_siblings); + int flatten(PandaNode *root, int combine_siblings_bits); protected: void r_apply_attribs(PandaNode *node, const AccumulatedAttribs &attribs, int attrib_types, GeomTransformer &transformer); int r_flatten(PandaNode *grandparent_node, PandaNode *parent_node, - bool combine_siblings); - int flatten_siblings(PandaNode *parent_node); + int combine_siblings_bits); + int flatten_siblings(PandaNode *parent_node, + int combine_siblings_bits); bool consider_child(PandaNode *grandparent_node, PandaNode *parent_node, PandaNode *child_node); diff --git a/panda/src/text/textNode.cxx b/panda/src/text/textNode.cxx index 9478c644ec..7fd28226ab 100644 --- a/panda/src/text/textNode.cxx +++ b/panda/src/text/textNode.cxx @@ -294,7 +294,7 @@ generate() { if (text_flatten) { SceneGraphReducer gr; gr.apply_attribs(root); - gr.flatten(root, true); + gr.flatten(root, ~0); } return root; diff --git a/pandatool/src/bam/eggToBam.cxx b/pandatool/src/bam/eggToBam.cxx index 5311ba2782..ca34b82aa3 100644 --- a/pandatool/src/bam/eggToBam.cxx +++ b/pandatool/src/bam/eggToBam.cxx @@ -52,10 +52,19 @@ EggToBam() : "instead be written to the bam file exactly as it is. If flag is " "non-zero, the hierarchy will be flattened so that unnecessary nodes " "(usually group nodes with only one child) are eliminated. The default " - "if this is not specified is taken from the egg-flatten Configrc " + "if this is not specified is taken from the egg-flatten Config.prc " "variable.", &EggToBam::dispatch_int, &_has_egg_flatten, &_egg_flatten); + add_option + ("combine-geoms", "flag", 0, + "Specifies whether to combine sibling GeomNodes into a common GeomNode " + "when possible. This flag is only respected if flatten, above, is also " + "enabled (or implicitly true from the Config.prc file). The default if " + "this is not specified is taken from the egg-combine-geoms Config.prc " + "variable.", + &EggToBam::dispatch_int, &_has_egg_combine_geoms, &_egg_combine_geoms); + add_option ("suppress-hidden", "flag", 0, "Specifies whether to suppress hidden geometry. If this is nonzero, " @@ -78,7 +87,7 @@ EggToBam() : "inclusive, where higher numbers produce larger files with greater " "quality. Generally, 95 is the highest useful quality level. Use " "-NC (described below) to disable channel compression. If neither " - "option is specified, the default comes from the Configrc file.", + "option is specified, the default comes from the Config.prc file.", &EggToBam::dispatch_int, &_has_compression_quality, &_compression_quality); add_option @@ -107,6 +116,7 @@ EggToBam() : _force_complete = true; _egg_flatten = 0; + _egg_combine_geoms = 0; _egg_suppress_hidden = 1; } @@ -119,9 +129,13 @@ void EggToBam:: run() { if (_has_egg_flatten) { // If the user specified some -flatten, we need to set the - // corresponding Configrc variable. + // corresponding Config.prc variable. egg_flatten = (_egg_flatten != 0); } + if (_has_egg_combine_geoms) { + // Ditto with -combine_geoms. + egg_combine_geoms = (_egg_combine_geoms != 0); + } // We always set egg_suppress_hidden. egg_suppress_hidden = _egg_suppress_hidden; @@ -183,7 +197,7 @@ run() { bool EggToBam:: handle_args(ProgramBase::Args &args) { // If the user specified a path store option, we need to set the - // bam-texture-mode Configrc variable directly to support this + // bam-texture-mode Config.prc variable directly to support this // (otherwise the bam code will do what it wants to do anyway). if (_tex_rawdata) { bam_texture_mode = BTM_rawdata; diff --git a/pandatool/src/bam/eggToBam.h b/pandatool/src/bam/eggToBam.h index 0042debdac..4df8f3a5a7 100644 --- a/pandatool/src/bam/eggToBam.h +++ b/pandatool/src/bam/eggToBam.h @@ -39,6 +39,8 @@ protected: private: bool _has_egg_flatten; int _egg_flatten; + bool _has_egg_combine_geoms; + int _egg_combine_geoms; bool _egg_suppress_hidden; bool _ls; bool _has_compression_quality;