Browse Source

support egg2bam -combine-geoms

David Rose 21 years ago
parent
commit
c3fd483b19

+ 11 - 2
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_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.
-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);
 bool egg_show_collision_solids = config_egg2pg.GetBool("egg-show-collision-solids", false);
 
 

+ 2 - 1
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_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;

+ 9 - 1
panda/src/egg2pg/load_egg_file.cxx

@@ -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";
   }
   }
 
 

+ 1 - 1
panda/src/grutil/cardMaker.cxx

@@ -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;
 }
 }

+ 2 - 2
panda/src/pgraph/nodePath.cxx

@@ -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;
 }
 }

+ 44 - 22
panda/src/pgraph/sceneGraphReducer.cxx

@@ -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
-//               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.
 //               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) {
-      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;
     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;
   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);
       }
       }
     }
     }

+ 10 - 3
panda/src/pgraph/sceneGraphReducer.h

@@ -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 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,
   bool consider_child(PandaNode *grandparent_node,
                       PandaNode *parent_node, PandaNode *child_node);
                       PandaNode *parent_node, PandaNode *child_node);

+ 1 - 1
panda/src/text/textNode.cxx

@@ -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;

+ 18 - 4
pandatool/src/bam/eggToBam.cxx

@@ -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;

+ 2 - 0
pandatool/src/bam/eggToBam.h

@@ -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;