support egg2bam -combine-geoms

This commit is contained in:
David Rose 2004-09-21 22:21:53 +00:00
parent d91112167e
commit c3fd483b19
10 changed files with 100 additions and 37 deletions

View File

@ -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_ignore_decals = config_egg2pg.GetBool("egg-ignore-decals", false);
bool egg_flatten = config_egg2pg.GetBool("egg-flatten", true); bool egg_flatten = config_egg2pg.GetBool("egg-flatten", true);
// It is almost always a bad idea to set this true. // Set this true to combine sibling GeomNodes into a single GeomNode,
bool egg_flatten_siblings = config_egg2pg.GetBool("egg-flatten-siblings", false); // 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); bool egg_show_collision_solids = config_egg2pg.GetBool("egg-show-collision-solids", false);

View File

@ -49,7 +49,8 @@ extern EXPCL_PANDAEGG bool egg_ignore_filters;
extern EXPCL_PANDAEGG bool egg_ignore_clamp; extern EXPCL_PANDAEGG bool egg_ignore_clamp;
extern EXPCL_PANDAEGG bool egg_ignore_decals; extern EXPCL_PANDAEGG bool egg_ignore_decals;
extern EXPCL_PANDAEGG bool egg_flatten; 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_show_collision_solids;
extern EXPCL_PANDAEGG bool egg_load_old_curves; extern EXPCL_PANDAEGG bool egg_load_old_curves;
extern EXPCL_PANDAEGG bool egg_load_classic_nurbs_curves; extern EXPCL_PANDAEGG bool egg_load_classic_nurbs_curves;

View File

@ -36,8 +36,16 @@ load_from_loader(EggLoader &loader) {
} }
if (loader._root != (PandaNode *)NULL && egg_flatten) { 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; 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"; egg2pg_cat.info() << "Flattened " << num_reduced << " nodes.\n";
} }

View File

@ -131,7 +131,7 @@ rescale_source_geometry() {
// Now flatten out the geometry as much as we can. // Now flatten out the geometry as much as we can.
SceneGraphReducer reducer; SceneGraphReducer reducer;
reducer.apply_attribs(root); reducer.apply_attribs(root);
reducer.flatten(root, true); reducer.flatten(root, ~0);
return root; return root;
} }

View File

@ -4523,7 +4523,7 @@ flatten_medium() {
nassertr_always(!is_empty(), 0); nassertr_always(!is_empty(), 0);
SceneGraphReducer gr; SceneGraphReducer gr;
gr.apply_attribs(node()); gr.apply_attribs(node());
int num_removed = gr.flatten(node(), false); int num_removed = gr.flatten(node(), 0);
return num_removed; return num_removed;
} }
@ -4550,7 +4550,7 @@ flatten_strong() {
nassertr_always(!is_empty(), 0); nassertr_always(!is_empty(), 0);
SceneGraphReducer gr; SceneGraphReducer gr;
gr.apply_attribs(node()); gr.apply_attribs(node());
int num_removed = gr.flatten(node(), true); int num_removed = gr.flatten(node(), ~0);
return num_removed; return num_removed;
} }

View File

@ -39,16 +39,17 @@
// candidate for removal if the node has no siblings and // candidate for removal if the node has no siblings and
// the node has no special properties. // the node has no special properties.
// //
// If combine_siblings is true, sibling nodes may also // If combine_siblings_bits is nonzero, some sibling
// be collapsed into a single node. This will further // nodes (according to the bits set in
// reduce scene graph complexity, sometimes // combine_siblings_bits) may also be collapsed into a
// substantially, at the cost of reduced spatial // single node. This will further reduce scene graph
// separation. // complexity, sometimes substantially, at the cost of
// reduced spatial separation.
// //
// Returns the number of nodes removed from the graph. // Returns the number of nodes removed from the graph.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
int SceneGraphReducer:: int SceneGraphReducer::
flatten(PandaNode *root, bool combine_siblings) { flatten(PandaNode *root, int combine_siblings_bits) {
int num_total_nodes = 0; int num_total_nodes = 0;
int num_pass_nodes; int num_pass_nodes;
@ -63,22 +64,20 @@ flatten(PandaNode *root, bool combine_siblings) {
int num_children = cr.get_num_children(); int num_children = cr.get_num_children();
for (int i = 0; i < num_children; i++) { for (int i = 0; i < num_children; i++) {
PandaNode *child_node = cr.get_child(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) { if (combine_siblings_bits != 0 && root->get_num_children() >= 2) {
num_pass_nodes += flatten_siblings(root); num_pass_nodes += flatten_siblings(root, combine_siblings_bits);
} }
num_total_nodes += num_pass_nodes; num_total_nodes += num_pass_nodes;
// If combine_siblings is true, we should repeat the above until // If combine_siblings_bits has CS_recurse set, we should repeat
// we don't get any more benefit from flattening, because each // the above until we don't get any more benefit from flattening,
// pass could convert cousins into siblings, which may get // because each pass could convert cousins into siblings, which
// flattened next pass. If combine_siblings is not true, the // may get flattened next pass.
// first pass will be fully effective, and there's no point in } while ((combine_siblings_bits & CS_recurse) != 0 && num_pass_nodes != 0);
// trying again.
} while (combine_siblings && num_pass_nodes != 0);
return num_total_nodes; return num_total_nodes;
} }
@ -218,7 +217,7 @@ r_apply_attribs(PandaNode *node, const AccumulatedAttribs &attribs,
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
int SceneGraphReducer:: int SceneGraphReducer::
r_flatten(PandaNode *grandparent_node, PandaNode *parent_node, r_flatten(PandaNode *grandparent_node, PandaNode *parent_node,
bool combine_siblings) { int combine_siblings_bits) {
int num_nodes = 0; int num_nodes = 0;
// First, recurse on each of the children. // 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(); int num_children = cr.get_num_children();
for (int i = 0; i < num_children; i++) { for (int i = 0; i < num_children; i++) {
PandaNode *child_node = cr.get_child(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 // Now that the above loop has removed some children, the child list
// saved above is no longer accurate, so hereafter we must ask the // saved above is no longer accurate, so hereafter we must ask the
// node for its real child list. // 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()) { 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; return num_nodes;
} }
@ -295,7 +308,7 @@ operator () (const PandaNode *node1, const PandaNode *node2) const {
// of the indicated node that share the same properties. // of the indicated node that share the same properties.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
int SceneGraphReducer:: int SceneGraphReducer::
flatten_siblings(PandaNode *parent_node) { flatten_siblings(PandaNode *parent_node, int combine_siblings_bits) {
int num_nodes = 0; int num_nodes = 0;
// First, collect the children into groups of nodes with common // 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(); int num_children = cr.get_num_children();
for (int i = 0; i < num_children; i++) { for (int i = 0; i < num_children; i++) {
PandaNode *child_node = cr.get_child(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); collected[child_node].push_back(child_node);
} }
} }

View File

@ -55,19 +55,26 @@ PUBLISHED:
TT_other = 0x010, 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, int attrib_types = ~0);
INLINE void apply_attribs(PandaNode *node, const AccumulatedAttribs &attribs, INLINE void apply_attribs(PandaNode *node, const AccumulatedAttribs &attribs,
int attrib_types, GeomTransformer &transformer); int attrib_types, GeomTransformer &transformer);
int flatten(PandaNode *root, bool combine_siblings); int flatten(PandaNode *root, int combine_siblings_bits);
protected: protected:
void r_apply_attribs(PandaNode *node, const AccumulatedAttribs &attribs, void r_apply_attribs(PandaNode *node, const AccumulatedAttribs &attribs,
int attrib_types, GeomTransformer &transformer); int attrib_types, GeomTransformer &transformer);
int r_flatten(PandaNode *grandparent_node, PandaNode *parent_node, int r_flatten(PandaNode *grandparent_node, PandaNode *parent_node,
bool combine_siblings); int combine_siblings_bits);
int flatten_siblings(PandaNode *parent_node); int flatten_siblings(PandaNode *parent_node,
int combine_siblings_bits);
bool consider_child(PandaNode *grandparent_node, bool consider_child(PandaNode *grandparent_node,
PandaNode *parent_node, PandaNode *child_node); PandaNode *parent_node, PandaNode *child_node);

View File

@ -294,7 +294,7 @@ generate() {
if (text_flatten) { if (text_flatten) {
SceneGraphReducer gr; SceneGraphReducer gr;
gr.apply_attribs(root); gr.apply_attribs(root);
gr.flatten(root, true); gr.flatten(root, ~0);
} }
return root; return root;

View File

@ -52,10 +52,19 @@ EggToBam() :
"instead be written to the bam file exactly as it is. If flag is " "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 " "non-zero, the hierarchy will be flattened so that unnecessary nodes "
"(usually group nodes with only one child) are eliminated. The default " "(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.", "variable.",
&EggToBam::dispatch_int, &_has_egg_flatten, &_egg_flatten); &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 add_option
("suppress-hidden", "flag", 0, ("suppress-hidden", "flag", 0,
"Specifies whether to suppress hidden geometry. If this is nonzero, " "Specifies whether to suppress hidden geometry. If this is nonzero, "
@ -78,7 +87,7 @@ EggToBam() :
"inclusive, where higher numbers produce larger files with greater " "inclusive, where higher numbers produce larger files with greater "
"quality. Generally, 95 is the highest useful quality level. Use " "quality. Generally, 95 is the highest useful quality level. Use "
"-NC (described below) to disable channel compression. If neither " "-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); &EggToBam::dispatch_int, &_has_compression_quality, &_compression_quality);
add_option add_option
@ -107,6 +116,7 @@ EggToBam() :
_force_complete = true; _force_complete = true;
_egg_flatten = 0; _egg_flatten = 0;
_egg_combine_geoms = 0;
_egg_suppress_hidden = 1; _egg_suppress_hidden = 1;
} }
@ -119,9 +129,13 @@ void EggToBam::
run() { run() {
if (_has_egg_flatten) { if (_has_egg_flatten) {
// If the user specified some -flatten, we need to set the // If the user specified some -flatten, we need to set the
// corresponding Configrc variable. // corresponding Config.prc variable.
egg_flatten = (_egg_flatten != 0); 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. // We always set egg_suppress_hidden.
egg_suppress_hidden = _egg_suppress_hidden; egg_suppress_hidden = _egg_suppress_hidden;
@ -183,7 +197,7 @@ run() {
bool EggToBam:: bool EggToBam::
handle_args(ProgramBase::Args &args) { handle_args(ProgramBase::Args &args) {
// If the user specified a path store option, we need to set the // 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). // (otherwise the bam code will do what it wants to do anyway).
if (_tex_rawdata) { if (_tex_rawdata) {
bam_texture_mode = BTM_rawdata; bam_texture_mode = BTM_rawdata;

View File

@ -39,6 +39,8 @@ protected:
private: private:
bool _has_egg_flatten; bool _has_egg_flatten;
int _egg_flatten; int _egg_flatten;
bool _has_egg_combine_geoms;
int _egg_combine_geoms;
bool _egg_suppress_hidden; bool _egg_suppress_hidden;
bool _ls; bool _ls;
bool _has_compression_quality; bool _has_compression_quality;