Browse Source

*** empty log message ***

David Rose 25 years ago
parent
commit
8ce02ceab8

+ 6 - 3
panda/src/egg/Sources.pp

@@ -20,11 +20,13 @@
     eggGroup.h eggGroupNode.I eggGroupNode.cxx eggGroupNode.h \
     eggMaterial.I eggMaterial.cxx eggMaterial.h eggMiscFuncs.I \
     eggMiscFuncs.cxx eggMiscFuncs.h eggNamedObject.I eggNamedObject.cxx \
-    eggNamedObject.h eggNode.I eggNode.cxx eggNode.h eggNurbsCurve.I \
+    eggNamedObject.h eggNameUniquifier.cxx eggNameUniquifier.h \
+    eggNode.I eggNode.cxx eggNode.h eggNurbsCurve.I \
     eggNurbsCurve.cxx eggNurbsCurve.h eggNurbsSurface.I \
     eggNurbsSurface.cxx eggNurbsSurface.h eggObject.I eggObject.cxx \
     eggObject.h eggParameters.cxx eggParameters.h eggPoint.I \
     eggPoint.cxx eggPoint.h eggPolygon.I eggPolygon.cxx eggPolygon.h \
+    eggPoolUniquifier.cxx eggPoolUniquifier.h \
     eggPrimitive.I eggPrimitive.cxx eggPrimitive.h eggSAnimData.I \
     eggSAnimData.cxx eggSAnimData.h eggSurface.I eggSurface.cxx \
     eggSurface.h eggSwitchCondition.cxx eggSwitchCondition.h eggTable.I \
@@ -44,10 +46,11 @@
     eggExternalReference.h eggFilenameNode.I eggFilenameNode.h \
     eggGroup.I eggGroup.h eggGroupNode.I eggGroupNode.h eggMaterial.I \
     eggMaterial.h eggMorph.I eggMorph.h eggMorphList.I eggMorphList.h \
-    eggNamedObject.I eggNamedObject.h eggNode.I eggNode.h \
+    eggNamedObject.I eggNamedObject.h eggNameUniquifier.h eggNode.I eggNode.h \
     eggNurbsCurve.I eggNurbsCurve.h eggNurbsSurface.I eggNurbsSurface.h \
     eggObject.I eggObject.h eggParameters.h eggPoint.I eggPoint.h \
-    eggPolygon.I eggPolygon.h eggPrimitive.I eggPrimitive.h \
+    eggPolygon.I eggPolygon.h eggPoolUniquifier.h \
+    eggPrimitive.I eggPrimitive.h \
     eggSAnimData.I eggSAnimData.h eggSurface.I eggSurface.h \
     eggSwitchCondition.h eggTable.I eggTable.h eggTexture.I \
     eggTexture.h eggTextureCollection.I eggTextureCollection.h \

+ 6 - 0
panda/src/egg/config_egg.cxx

@@ -16,6 +16,8 @@
 #include "eggFilenameNode.h"
 #include "eggGroup.h"
 #include "eggGroupNode.h"
+#include "eggMaterial.h"
+#include "eggNameUniquifier.h"
 #include "eggNamedObject.h"
 #include "eggNode.h"
 #include "eggNurbsCurve.h"
@@ -23,6 +25,7 @@
 #include "eggObject.h"
 #include "eggPoint.h"
 #include "eggPolygon.h"
+#include "eggPoolUniquifier.h"
 #include "eggPrimitive.h"
 #include "eggSAnimData.h"
 #include "eggSurface.h"
@@ -54,6 +57,8 @@ ConfigureFn(config_egg) {
   EggFilenameNode::init_type();
   EggGroup::init_type();
   EggGroupNode::init_type();
+  EggMaterial::init_type();
+  EggNameUniquifier::init_type();
   EggNamedObject::init_type();
   EggNode::init_type();
   EggNurbsCurve::init_type();
@@ -61,6 +66,7 @@ ConfigureFn(config_egg) {
   EggObject::init_type();
   EggPoint::init_type();
   EggPolygon::init_type();
+  EggPoolUniquifier::init_type();
   EggPrimitive::init_type();
   EggSAnimData::init_type();
   EggSurface::init_type();

+ 3 - 3
panda/src/egg/eggBinMaker.h

@@ -48,7 +48,7 @@
 //          }
 //        }
 //
-
+//
 //    This function may also return the bin number that a given node
 //    should be dropped into.  The bin number is completely arbitrary,
 //    and it just serves to differentiate different bins.
@@ -207,7 +207,7 @@ class EggGroupNode;
 class EggBin;
 class EggBinMaker;
 
-///////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////
 // 	 Class : EggBinMakerCompareNodes
 // Description : This is just an STL function object, used to sort
 //               nodes within EggBinMaker.  It's part of the private
@@ -227,7 +227,7 @@ public:
 };
 
 
-///////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////
 // 	 Class : EggBinMaker
 // Description : This is a handy class for collecting related nodes
 //               together.  It is an abstract class; to use it you

+ 20 - 14
panda/src/egg/eggData.cxx

@@ -7,6 +7,7 @@
 #include "eggCoordinateSystem.h"
 #include "eggTextureCollection.h"
 #include "eggComment.h"
+#include "eggPoolUniquifier.h"
 #include "config_egg.h"
 
 #include <config_util.h>
@@ -181,6 +182,20 @@ set_coordinate_system(CoordinateSystem new_coordsys) {
   _coordsys = new_coordsys;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggData::write
+//       Access: Protected, Virtual
+//  Description: Writes the egg data out to the indicated output
+//               stream.
+////////////////////////////////////////////////////////////////////
+void EggData::
+write(ostream &out, int indent_level) const {
+  EggCoordinateSystem ecs(_coordsys);
+  ecs.write(out, indent_level);
+  EggGroupNode::write(out, indent_level);
+  out << flush;
+}
+
 
 ////////////////////////////////////////////////////////////////////
 //     Function: EggData::post_read
@@ -251,19 +266,10 @@ pre_write() {
   }
 
   textures.insert_textures(this, ci);
-}
 
-////////////////////////////////////////////////////////////////////
-//     Function: EggData::write
-//       Access: Public, Virtual
-//  Description: Writes the egg data out to the indicated output
-//               stream.
-////////////////////////////////////////////////////////////////////
-void EggData::
-write(ostream &out, int indent_level) const {
-  EggCoordinateSystem ecs(_coordsys);
-  ecs.write(out, indent_level);
-  EggGroupNode::write(out, indent_level);
-  out << flush;
+  // Also make sure that the vertex pools and materials are uniquely
+  // named.  This also checks textures, which is kind of redundant
+  // since we just did that, but we don't mind.
+  EggPoolUniquifier pu;
+  pu.uniquify(this);
 }
-

+ 2 - 0
panda/src/egg/eggMaterial.cxx

@@ -7,6 +7,8 @@
 
 #include <indent.h>
 
+TypeHandle EggMaterial::_type_handle;
+
 
 ////////////////////////////////////////////////////////////////////
 //     Function: EggMaterial::Constructor

+ 18 - 0
panda/src/egg/eggMaterial.h

@@ -31,6 +31,24 @@ public:
 private:
   bool _has_diff;
   Colorf _diff;
+
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    EggNode::init_type();
+    register_type(_type_handle, "EggMaterial",
+		  EggNode::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+ 
+private:
+  static TypeHandle _type_handle;
 };
 
 #include "eggMaterial.I"

+ 153 - 0
panda/src/egg/eggNameUniquifier.cxx

@@ -0,0 +1,153 @@
+// Filename: eggNameUniquifier.cxx
+// Created by:  drose (09Nov00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "eggNameUniquifier.h"
+#include "eggNode.h"
+#include "eggGroupNode.h"
+
+#include <notify.h>
+
+TypeHandle EggNameUniquifier::_type_handle;
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggNameUniquifier::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+EggNameUniquifier::
+EggNameUniquifier() {
+  _index = 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggNameUniquifier::clear
+//       Access: Public
+//  Description: Empties the table of used named and prepares the
+//               Uniquifier for a new tree.
+////////////////////////////////////////////////////////////////////
+void EggNameUniquifier::
+clear() {
+  _categories.clear();
+  _index = 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggNameUniquifier::uniquify
+//       Access: Public
+//  Description: Begins the traversal from the indicated node.
+////////////////////////////////////////////////////////////////////
+void EggNameUniquifier::
+uniquify(EggNode *node) {
+  string category = get_category(node);
+
+  if (!category.empty()) {
+    string name = node->get_name();
+
+    UsedNames &names = _categories[category];
+    bool inserted;
+    inserted = names.insert(UsedNames::value_type(name, node)).second;
+    if (!inserted) {
+      while (!inserted) {
+	_index++;
+	name = generate_name(node, category, _index);
+	inserted = names.insert(UsedNames::value_type(name, node)).second;
+      }
+      node->set_name(name);
+    }
+  }
+
+  if (node->is_of_type(EggGroupNode::get_class_type())) {
+    EggGroupNode *group;
+    DCAST_INTO_V(group, node);
+
+    EggGroupNode::iterator ci;
+    for (ci = group->begin(); ci != group->end(); ++ci) {
+      uniquify(*ci);
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggNameUniquifier::get_node
+//       Access: Public
+//  Description: Returns the node associated with the given category
+//               and name, or NULL if the name has not been used.
+////////////////////////////////////////////////////////////////////
+EggNode *EggNameUniquifier::
+get_node(const string &category, const string &name) const {
+  Categories::const_iterator ci;
+  ci = _categories.find(category);
+  if (ci == _categories.end()) {
+    return (EggNode *)NULL;
+  }
+
+  const UsedNames &names = (*ci).second;
+  UsedNames::const_iterator ni;
+  ni = names.find(name);
+  if (ni == names.end()) {
+    return (EggNode *)NULL;
+  }
+
+  return (*ni).second;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggNameUniquifier::has_name
+//       Access: Public
+//  Description: Returns true if the name has been used for the
+//               indicated category already, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool EggNameUniquifier::
+has_name(const string &category, const string &name) const {
+  Categories::const_iterator ci;
+  ci = _categories.find(category);
+  if (ci == _categories.end()) {
+    return false;
+  }
+
+  const UsedNames &names = (*ci).second;
+  UsedNames::const_iterator ni;
+  ni = names.find(name);
+  if (ni == names.end()) {
+    return false;
+  }
+
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggNameUniquifier::add_name
+//       Access: Public
+//  Description: Adds the name to the indicated category.  This name
+//               will not be used for any other egg node within this
+//               category.  Returns true if the name was added, or
+//               false if it was already in use for the category.
+////////////////////////////////////////////////////////////////////
+bool EggNameUniquifier::
+add_name(const string &category, const string &name, EggNode *node) {
+  UsedNames &names = _categories[category];
+  bool inserted = names.insert(UsedNames::value_type(name, node)).second;
+  return inserted;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggNameUniquifier::generate_name
+//       Access: Public, Virtual
+//  Description: Generates a new name for the given node when its
+//               existing name clashes with some other node.  This
+//               function will be called repeatedly, if necessary,
+//               until it returns a name that actually is unique.
+//
+//               The category is the string returned by
+//               get_category(), and index is a uniquely-generated
+//               number that may be useful for synthesizing the name.
+////////////////////////////////////////////////////////////////////
+string EggNameUniquifier::
+generate_name(EggNode *node, const string &category, int index) {
+  ostringstream str;
+  str << node->get_name() << "." << category << index;
+  return str.str();
+}

+ 118 - 0
panda/src/egg/eggNameUniquifier.h

@@ -0,0 +1,118 @@
+// Filename: eggNameUniquifier.h
+// Created by:  drose (09Nov00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef EGGNAMEUNIQUIFIER_H
+#define EGGNAMEUNIQUIFIER_H
+
+///////////////////////////////////////////////////////////////////
+//
+// EggNameUniquifier
+//
+// This is a utility class for renaming nodes in an egg hierarchy so
+// that no two nodes share the same name.  It's useful, for instance,
+// as a preprocess before translating the egg hierarchy to a scene
+// graph format that doesn't tolerate two identically-named nodes;
+// it's also particularly useful for guaranteeing that VertexPools and
+// Textures do not have conflicting names.
+//
+// This is actually an abstract class; in order to use it, you must
+// derive your own class and redefine some key functions (but see
+// EggPoolUniquifier).
+//
+// You must define at least the following function:
+//
+// virtual string get_category(EggNode *node);
+//
+//    This function defines the particular category that the
+//    particular node should be grouped into.  All nodes that share
+//    the same category name will be considered in the same name pool
+//    and may not have the same name; two nodes that have different
+//    categories will be allowed to keep the same name.
+//
+//    If the category is the empty string, the node will not be
+//    considered for uniquification.
+//
+//
+// You may also define the following function:
+//
+// virtual string generate_name(EggNode *node,
+//                              const string &category, int index);
+//
+//    This returns a new name for the given node, once a node has been
+//    identified as having the same name as another node.  It may use
+//    any algorithm you please to generate a new name, using any
+//    combination of the node's original name, the category (as
+//    returned by get_category()), and/or the supplied unique index
+//    number.
+//
+//    If this function returns a name that happens to collide with
+//    some other already-existing node, it will simply be called again
+//    (with a new index number) until it finally returns a unique
+//    name.
+//
+///////////////////////////////////////////////////////////////////
+
+#include <pandabase.h>
+
+#include "eggObject.h"
+
+#include <map>
+
+class EggNode;
+
+////////////////////////////////////////////////////////////////////
+// 	 Class : EggNameUniquifier
+// Description : This is a handy class for guaranteeing unique node
+//               names in an egg hierarchy.  It is an abstract class;
+//               to use it you must subclass off of it.  See the
+//               comment above.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDAEGG EggNameUniquifier : public EggObject {
+public:
+  EggNameUniquifier();
+
+  void clear();
+
+  void uniquify(EggNode *node);
+
+  EggNode *get_node(const string &category, const string &name) const;
+  bool has_name(const string &category, const string &name) const;
+  bool add_name(const string &category, const string &name,
+		EggNode *node = NULL);
+
+  virtual string get_category(EggNode *node)=0;
+  virtual string generate_name(EggNode *node,
+			       const string &category, int index);
+
+private:
+  typedef map<string, EggNode *> UsedNames;
+  typedef map<string, UsedNames> Categories;
+
+  Categories _categories;
+  int _index;
+
+public:
+
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    EggObject::init_type();
+    register_type(_type_handle, "EggNameUniquifier",
+		  EggObject::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+
+};
+
+#endif
+ 
+ 

+ 44 - 0
panda/src/egg/eggPoolUniquifier.cxx

@@ -0,0 +1,44 @@
+// Filename: eggPoolUniquifier.cxx
+// Created by:  drose (09Nov00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "eggPoolUniquifier.h"
+#include "eggNode.h"
+#include "eggTexture.h"
+#include "eggMaterial.h"
+#include "eggVertexPool.h"
+
+#include <notify.h>
+
+TypeHandle EggPoolUniquifier::_type_handle;
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggPoolUniquifier::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+EggPoolUniquifier::
+EggPoolUniquifier() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggPoolUniquifier::get_category
+//       Access: Public
+//  Description: Returns the category name into which the given node
+//               should be collected, or the empty string if the
+//               node's name should be left alone.
+////////////////////////////////////////////////////////////////////
+string EggPoolUniquifier::
+get_category(EggNode *node) {
+  if (node->is_of_type(EggTexture::get_class_type())) {
+    return "tex";
+  } else if (node->is_of_type(EggMaterial::get_class_type())) {
+    return "mat";
+  } else if (node->is_of_type(EggVertexPool::get_class_type())) {
+    return "vpool";
+  }
+
+  return string();
+}

+ 51 - 0
panda/src/egg/eggPoolUniquifier.h

@@ -0,0 +1,51 @@
+// Filename: eggPoolUniquifier.h
+// Created by:  drose (09Nov00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef EGGPOOLUNIQUIFIER_H
+#define EGGPOOLUNIQUIFIER_H
+
+#include <pandabase.h>
+
+#include "eggNameUniquifier.h"
+
+#include <map>
+
+class EggNode;
+
+////////////////////////////////////////////////////////////////////
+// 	 Class : EggPoolUniquifier
+// Description : This is a specialization of EggNameUniquifier to
+//               generate unique names for textures, materials, and
+//               vertex pools prior to writing out an egg file.  It's
+//               called by EggData prior to writing out an egg file.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDAEGG EggPoolUniquifier : public EggNameUniquifier {
+public:
+  EggPoolUniquifier();
+
+  virtual string get_category(EggNode *node);
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    EggNameUniquifier::init_type();
+    register_type(_type_handle, "EggPoolUniquifier",
+		  EggNameUniquifier::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+
+};
+
+#endif
+ 
+ 

+ 3 - 7
panda/src/egg/eggTextureCollection.cxx

@@ -94,13 +94,9 @@ insert_textures(EggGroupNode *node) {
 ////////////////////////////////////////////////////////////////////
 int EggTextureCollection::
 insert_textures(EggGroupNode *node, EggGroupNode::iterator position) {
-  // We add the textures in reverse order because we stick each one at
-  // the head of the group's children.  When we're done, they'll all
-  // be in the correct order.
-
-  OrderedTextures::reverse_iterator oti;
-  for (oti = _ordered_textures.rbegin(); 
-       oti != _ordered_textures.rend(); 
+  OrderedTextures::iterator oti;
+  for (oti = _ordered_textures.begin(); 
+       oti != _ordered_textures.end(); 
        ++oti) {
     node->insert(position, (*oti).p());
   }

+ 1 - 1
panda/src/loader/bamFile.cxx

@@ -140,7 +140,7 @@ open_write(const Filename &filename, bool) {
 
   loader_cat.info() << "Writing " << filename << "\n";
 
-  filename.make_dir();
+  filename.unlink();
   if (!_dout.open(filename)) {
     loader_cat.error() << "Unable to open " << filename << "\n";
     return false;

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

@@ -52,9 +52,11 @@ run() {
   // constructor, above.
   nassertv(has_output_filename());
 
-  nout << "Writing " << get_output_filename() << "\n";
+  Filename filename = get_output_filename();
+  filename.make_dir();
+  nout << "Writing " << filename << "\n";
   BamFile bam_file;
-  if (!bam_file.open_write(get_output_filename())) {
+  if (!bam_file.open_write(filename)) {
     nout << "Error in writing.\n";
     exit(1);
   }

+ 1 - 0
pandatool/src/eggbase/eggWriter.cxx

@@ -97,6 +97,7 @@ get_output() {
       // Attempt to open the named file.
       unlink(_output_filename.c_str());
       _output_filename.make_dir();
+      _output_filename.set_text();
       if (!_output_filename.open_write(_output_stream)) {
 	nout << "Unable to write to " << _output_filename << "\n";
 	exit(1);