Browse Source

*** empty log message ***

David Rose 25 years ago
parent
commit
aa42fdae2f
33 changed files with 800 additions and 58 deletions
  1. 19 0
      panda/src/egg/eggGroupNode.cxx
  2. 1 0
      panda/src/egg/eggGroupNode.h
  3. 13 0
      panda/src/egg/eggNode.I
  4. 13 0
      panda/src/egg/eggNode.cxx
  5. 2 0
      panda/src/egg/eggNode.h
  6. 14 0
      panda/src/egg/eggVertexPool.cxx
  7. 1 0
      panda/src/egg/eggVertexPool.h
  8. 3 0
      pandatool/src/eggcharbase/Sources.pp
  9. 43 0
      pandatool/src/eggcharbase/config_eggcharbase.cxx
  10. 16 0
      pandatool/src/eggcharbase/config_eggcharbase.h
  11. 38 0
      pandatool/src/eggcharbase/eggCharacterCollection.I
  12. 15 6
      pandatool/src/eggcharbase/eggCharacterCollection.cxx
  13. 4 1
      pandatool/src/eggcharbase/eggCharacterCollection.h
  14. 54 0
      pandatool/src/eggcharbase/eggCharacterData.I
  15. 15 0
      pandatool/src/eggcharbase/eggCharacterData.cxx
  16. 18 1
      pandatool/src/eggcharbase/eggCharacterData.h
  17. 1 3
      pandatool/src/eggcharbase/eggCharacterFilter.cxx
  18. 8 8
      pandatool/src/eggcharbase/eggComponentData.I
  19. 2 2
      pandatool/src/eggcharbase/eggComponentData.cxx
  20. 4 4
      pandatool/src/eggcharbase/eggComponentData.h
  21. 30 7
      pandatool/src/eggcharbase/eggJointData.cxx
  22. 1 0
      pandatool/src/eggcharbase/eggJointData.h
  23. 81 0
      pandatool/src/eggcharbase/eggJointNodePointer.cxx
  24. 51 0
      pandatool/src/eggcharbase/eggJointNodePointer.h
  25. 9 6
      pandatool/src/eggcharbase/eggJointPointer.cxx
  26. 11 7
      pandatool/src/eggcharbase/eggJointPointer.h
  27. 54 0
      pandatool/src/eggcharbase/eggMatrixTablePointer.cxx
  28. 9 4
      pandatool/src/eggcharbase/eggMatrixTablePointer.h
  29. 9 9
      pandatool/src/eggcharbase/eggSliderData.cxx
  30. 205 0
      pandatool/src/eggprogs/eggTopstrip.cxx
  31. 18 0
      pandatool/src/eggprogs/eggTopstrip.h
  32. 36 0
      pandatool/src/progbase/programBase.cxx
  33. 2 0
      pandatool/src/progbase/programBase.h

+ 19 - 0
panda/src/egg/eggGroupNode.cxx

@@ -653,6 +653,25 @@ r_transform(const LMatrix4d &mat, const LMatrix4d &inv,
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggGroupNode::r_transform_vertices
+//       Access: Protected, Virtual
+//  Description: This is called from within the egg code by
+//               transform_vertices_only()().  It applies a
+//               transformation matrix to the current node in some
+//               sensible way (if the current node is a vertex pool
+//               with vertices), then continues down the tree.
+////////////////////////////////////////////////////////////////////
+void EggGroupNode::
+r_transform_vertices(const LMatrix4d &mat) {
+  Children::iterator ci;
+  for (ci = _children.begin();
+       ci != _children.end();
+       ++ci) {
+    (*ci)->r_transform_vertices(mat);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: EggGroupNode::r_mark_coordsys
 //     Function: EggGroupNode::r_mark_coordsys
 //       Access: Protected, Virtual
 //       Access: Protected, Virtual

+ 1 - 0
panda/src/egg/eggGroupNode.h

@@ -111,6 +111,7 @@ protected:
 
 
   virtual void r_transform(const LMatrix4d &mat, const LMatrix4d &inv,
   virtual void r_transform(const LMatrix4d &mat, const LMatrix4d &inv,
 			   CoordinateSystem to_cs);
 			   CoordinateSystem to_cs);
+  virtual void r_transform_vertices(const LMatrix4d &mat);
   virtual void r_mark_coordsys(CoordinateSystem cs);
   virtual void r_mark_coordsys(CoordinateSystem cs);
   virtual void r_flatten_transforms();
   virtual void r_flatten_transforms();
   virtual void r_apply_texmats(EggTextureCollection &textures);
   virtual void r_apply_texmats(EggTextureCollection &textures);

+ 13 - 0
panda/src/egg/eggNode.I

@@ -213,6 +213,19 @@ transform(const LMatrix4d &mat) {
   r_transform(mat, inv, CS_default);
   r_transform(mat, inv, CS_default);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggNode::transform_vertices_only
+//       Access: Public
+//  Description: Applies the indicated transformation only to vertices
+//               that appear in global space within vertex pools at
+//               this node and below.  Joints and other transforms are
+//               not affected, nor are local vertices.
+////////////////////////////////////////////////////////////////////
+INLINE void EggNode::
+transform_vertices_only(const LMatrix4d &mat) {
+  r_transform_vertices(mat);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: EggNode::flatten_transforms
 //     Function: EggNode::flatten_transforms
 //       Access: Public
 //       Access: Public

+ 13 - 0
panda/src/egg/eggNode.cxx

@@ -232,6 +232,19 @@ void EggNode::
 r_transform(const LMatrix4d &, const LMatrix4d &, CoordinateSystem) {
 r_transform(const LMatrix4d &, const LMatrix4d &, CoordinateSystem) {
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggNode::r_transform_vertices
+//       Access: Protected, Virtual
+//  Description: This is called from within the egg code by
+//               transform_vertices_only()().  It applies a
+//               transformation matrix to the current node in some
+//               sensible way (if the current node is a vertex pool
+//               with vertices), then continues down the tree.
+////////////////////////////////////////////////////////////////////
+void EggNode::
+r_transform_vertices(const LMatrix4d &) {
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: EggNode::r_mark_coordsys
 //     Function: EggNode::r_mark_coordsys
 //       Access: Protected, Virtual
 //       Access: Protected, Virtual

+ 2 - 0
panda/src/egg/eggNode.h

@@ -45,6 +45,7 @@ public:
   INLINE const LMatrix4d &get_vertex_to_node() const;
   INLINE const LMatrix4d &get_vertex_to_node() const;
 
 
   INLINE void transform(const LMatrix4d &mat);
   INLINE void transform(const LMatrix4d &mat);
+  INLINE void transform_vertices_only(const LMatrix4d &mat);
   INLINE void flatten_transforms();
   INLINE void flatten_transforms();
   void apply_texmats();
   void apply_texmats();
 
 
@@ -75,6 +76,7 @@ protected:
 
 
   virtual void r_transform(const LMatrix4d &mat, const LMatrix4d &inv,
   virtual void r_transform(const LMatrix4d &mat, const LMatrix4d &inv,
 			   CoordinateSystem to_cs);
 			   CoordinateSystem to_cs);
+  virtual void r_transform_vertices(const LMatrix4d &mat);
   virtual void r_mark_coordsys(CoordinateSystem cs);
   virtual void r_mark_coordsys(CoordinateSystem cs);
   virtual void r_flatten_transforms();
   virtual void r_flatten_transforms();
   virtual void r_apply_texmats(EggTextureCollection &textures);
   virtual void r_apply_texmats(EggTextureCollection &textures);

+ 14 - 0
panda/src/egg/eggVertexPool.cxx

@@ -404,3 +404,17 @@ void EggVertexPool::
 r_transform(const LMatrix4d &mat, const LMatrix4d &, CoordinateSystem) {
 r_transform(const LMatrix4d &mat, const LMatrix4d &, CoordinateSystem) {
   transform(mat);
   transform(mat);
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggVertexPool::r_transform_vertices
+//       Access: Protected, Virtual
+//  Description: This is called from within the egg code by
+//               transform_vertices_only()().  It applies a
+//               transformation matrix to the current node in some
+//               sensible way (if the current node is a vertex pool
+//               with vertices), then continues down the tree.
+////////////////////////////////////////////////////////////////////
+void EggVertexPool::
+r_transform_vertices(const LMatrix4d &mat) {
+  transform(mat);
+}

+ 1 - 0
panda/src/egg/eggVertexPool.h

@@ -104,6 +104,7 @@ public:
 protected:
 protected:
   virtual void r_transform(const LMatrix4d &mat, const LMatrix4d &inv,
   virtual void r_transform(const LMatrix4d &mat, const LMatrix4d &inv,
 			   CoordinateSystem to_cs);
 			   CoordinateSystem to_cs);
+  virtual void r_transform_vertices(const LMatrix4d &mat);
 
 
 private:
 private:
   UniqueVertices _unique_vertices;
   UniqueVertices _unique_vertices;

+ 3 - 0
pandatool/src/eggcharbase/Sources.pp

@@ -6,6 +6,7 @@
     egg:c panda:m
     egg:c panda:m
 
 
   #define SOURCES \
   #define SOURCES \
+    config_eggcharbase.cxx config_eggcharbase.h \
     eggBackPointer.cxx eggBackPointer.h \
     eggBackPointer.cxx eggBackPointer.h \
     eggCharacterCollection.cxx eggCharacterCollection.h \
     eggCharacterCollection.cxx eggCharacterCollection.h \
     eggCharacterCollection.I \
     eggCharacterCollection.I \
@@ -14,6 +15,7 @@
     eggComponentData.cxx eggComponentData.h eggComponentData.I \
     eggComponentData.cxx eggComponentData.h eggComponentData.I \
     eggJointData.cxx eggJointData.h eggJointData.I \
     eggJointData.cxx eggJointData.h eggJointData.I \
     eggJointPointer.cxx eggJointPointer.h \
     eggJointPointer.cxx eggJointPointer.h \
+    eggJointNodePointer.cxx eggJointNodePointer.h \
     eggMatrixTablePointer.cxx eggMatrixTablePointer.h \
     eggMatrixTablePointer.cxx eggMatrixTablePointer.h \
     eggSliderData.cxx eggSliderData.h eggSliderData.I \
     eggSliderData.cxx eggSliderData.h eggSliderData.I \
     eggVertexPointer.cxx eggVertexPointer.h
     eggVertexPointer.cxx eggVertexPointer.h
@@ -25,6 +27,7 @@
     eggComponentData.I eggComponentData.h \
     eggComponentData.I eggComponentData.h \
     eggJointData.h eggJointData.I \
     eggJointData.h eggJointData.I \
     eggJointPointer.h \
     eggJointPointer.h \
+    eggJointNodePointer.h \
     eggMatrixTablePointer.h \
     eggMatrixTablePointer.h \
     eggSliderData.I eggSliderData.h \
     eggSliderData.I eggSliderData.h \
     eggVertexPointer.h
     eggVertexPointer.h

+ 43 - 0
pandatool/src/eggcharbase/config_eggcharbase.cxx

@@ -0,0 +1,43 @@
+// Filename: config_eggcharbase.cxx
+// Created by:  drose (26Feb01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "config_eggcharbase.h"
+#include "eggBackPointer.h"
+#include "eggJointNodePointer.h"
+#include "eggJointPointer.h"
+#include "eggMatrixTablePointer.h"
+#include "eggVertexPointer.h"
+
+#include <dconfig.h>
+
+Configure(config_eggcharbase);
+NotifyCategoryDef(eggcharbase, "");
+
+ConfigureFn(config_eggcharbase) {
+  init_libeggcharbase();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: init_libeggcharbase
+//  Description: Initializes the library.  This must be called at
+//               least once before any of the functions or classes in
+//               this library can be used.  Normally it will be
+//               called by the static initializers and need not be
+//               called explicitly, but special cases exist.
+////////////////////////////////////////////////////////////////////
+void
+init_libeggcharbase() {
+  static bool initialized = false;
+  if (initialized) {
+    return;
+  }
+  initialized = true;
+
+  EggBackPointer::init_type();
+  EggJointNodePointer::init_type();
+  EggJointPointer::init_type();
+  EggMatrixTablePointer::init_type();
+  EggVertexPointer::init_type();
+}

+ 16 - 0
pandatool/src/eggcharbase/config_eggcharbase.h

@@ -0,0 +1,16 @@
+// Filename: config_eggcharbase.h
+// Created by:  drose (26Feb01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef CONFIG_EGGCHARBASE_H
+#define CONFIG_EGGCHARBASE_H
+
+#include <pandabase.h>
+#include <notifyCategoryProxy.h>
+
+NotifyCategoryDecl(eggcharbase, EXPCL_MISC, EXPTP_MISC);
+
+extern void init_libeggcharbase();
+
+#endif

+ 38 - 0
pandatool/src/eggcharbase/eggCharacterCollection.I

@@ -26,6 +26,44 @@ get_egg(int i) const {
   return _eggs[i]._egg;
   return _eggs[i]._egg;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggCharacterCollection::get_first_model_index
+//       Access: Public
+//  Description: Returns the first model index associated with the
+//               indicated egg file.  An egg file may contain multiple
+//               models, which will be consecutive integers beginning
+//               at get_first_model_index() and continuing for
+//               get_num_models().
+//
+//               Each "model" corresponds to a single character model,
+//               or one LOD of a multiple-LOD model, or a single
+//               animation bundle.
+////////////////////////////////////////////////////////////////////
+INLINE int EggCharacterCollection::
+get_first_model_index(int egg_index) const {
+  nassertr(egg_index >= 0 && egg_index < (int)_eggs.size(), 0);
+  return _eggs[egg_index]._first_model_index;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggCharacterCollection::get_num_models
+//       Access: Public
+//  Description: Returns the number of different models found in the
+//               indicated egg file.  An egg file may contain multiple
+//               models, which will be consecutive integers beginning
+//               at get_first_model_index() and continuing for
+//               get_num_models().
+//
+//               Each "model" corresponds to a single character model,
+//               or one LOD of a multiple-LOD model, or a single
+//               animation bundle.
+////////////////////////////////////////////////////////////////////
+INLINE int EggCharacterCollection::
+get_num_models(int egg_index) const {
+  nassertr(egg_index >= 0 && egg_index < (int)_eggs.size(), 0);
+  return _eggs[egg_index]._models.size();
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: EggCharacterCollection::get_num_characters
 //     Function: EggCharacterCollection::get_num_characters
 //       Access: Public
 //       Access: Public

+ 15 - 6
pandatool/src/eggcharbase/eggCharacterCollection.cxx

@@ -49,25 +49,28 @@ EggCharacterCollection::
 //       Access: Public
 //       Access: Public
 //  Description: Adds a new egg file to the list of models and
 //  Description: Adds a new egg file to the list of models and
 //               animation files for this particular character.
 //               animation files for this particular character.
-//               Returns true if the file is successfully added, or
-//               false if there is some problem (for instance, it does
-//               not contain a character model or animation table).
+//
+//               Returns the new egg_index if the file is successfully
+//               added, or -1 if there is some problem (for instance,
+//               it does not contain a character model or animation
+//               table).
 //
 //
 //               If the joint hierarchy does not match the existing
 //               If the joint hierarchy does not match the existing
 //               joint hierarchy, a best match is attempted.
 //               joint hierarchy, a best match is attempted.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-bool EggCharacterCollection::
+int EggCharacterCollection::
 add_egg(EggData *egg) {
 add_egg(EggData *egg) {
   _top_egg_nodes.clear();
   _top_egg_nodes.clear();
 
 
   if (!scan_hierarchy(egg)) {
   if (!scan_hierarchy(egg)) {
-    return false;
+    return -1;
   }
   }
 
 
   int egg_index = _eggs.size();
   int egg_index = _eggs.size();
   _eggs.push_back(EggInfo());
   _eggs.push_back(EggInfo());
   EggInfo &egg_info = _eggs.back();
   EggInfo &egg_info = _eggs.back();
   egg_info._egg = egg;
   egg_info._egg = egg;
+  egg_info._first_model_index = 0;
 
 
   // Now, for each model, add an entry in the egg_info and match the
   // Now, for each model, add an entry in the egg_info and match the
   // joint hierarchy to the known joints.
   // joint hierarchy to the known joints.
@@ -84,7 +87,13 @@ add_egg(EggData *egg) {
       EggNodeList &egg_nodes = (*ti).second;
       EggNodeList &egg_nodes = (*ti).second;
       
       
       int model_index = _next_model_index++;
       int model_index = _next_model_index++;
+      if (egg_info._models.empty()) {
+	egg_info._first_model_index = model_index;
+      }
       egg_info._models.push_back(model_root);
       egg_info._models.push_back(model_root);
+
+      char_data->add_model(model_index, model_root);
+
       match_egg_nodes(char_data, root_joint, egg_nodes,
       match_egg_nodes(char_data, root_joint, egg_nodes,
 		      egg_index, model_index);
 		      egg_index, model_index);
 
 
@@ -93,7 +102,7 @@ add_egg(EggData *egg) {
     }
     }
   }
   }
 
 
-  return true;
+  return egg_index;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 4 - 1
pandatool/src/eggcharbase/eggCharacterCollection.h

@@ -28,10 +28,12 @@ public:
   EggCharacterCollection();
   EggCharacterCollection();
   virtual ~EggCharacterCollection();
   virtual ~EggCharacterCollection();
 
 
-  bool add_egg(EggData *egg);
+  int add_egg(EggData *egg);
 
 
   INLINE int get_num_eggs() const;
   INLINE int get_num_eggs() const;
   INLINE EggData *get_egg(int i) const;
   INLINE EggData *get_egg(int i) const;
+  INLINE int get_first_model_index(int egg_index) const;
+  INLINE int get_num_models(int egg_index) const;
 
 
   INLINE int get_num_characters() const;
   INLINE int get_num_characters() const;
   INLINE EggCharacterData *get_character(int i) const;
   INLINE EggCharacterData *get_character(int i) const;
@@ -51,6 +53,7 @@ public:
     PT(EggData) _egg;
     PT(EggData) _egg;
     typedef vector<PT(EggNode)> Models;
     typedef vector<PT(EggNode)> Models;
     Models _models;
     Models _models;
+    int _first_model_index;
   };
   };
   
   
   typedef vector<EggInfo> Eggs;
   typedef vector<EggInfo> Eggs;

+ 54 - 0
pandatool/src/eggcharbase/eggCharacterData.I

@@ -4,6 +4,49 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
 
 
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggCharacterData::get_num_models
+//       Access: Public
+//  Description: Returns the total number of models associated with
+//               this character.
+////////////////////////////////////////////////////////////////////
+INLINE int EggCharacterData::
+get_num_models() const {
+  return _models.size();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggCharacterData::get_model_index
+//       Access: Public
+//  Description: Returns the model_index of the nth model associated
+//               with this character.  This model_index may be used to
+//               ask questions about the particular model from the
+//               EggCharacterCollection object, or from the individual
+//               EggJointData and EggSliderData objects.
+////////////////////////////////////////////////////////////////////
+INLINE int EggCharacterData::
+get_model_index(int n) const {
+  nassertr(n >= 0 && n < (int)_models.size(), 0);
+  return _models[n]._model_index;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggCharacterData::get_model_root
+//       Access: Public
+//  Description: Returns the model_root of the nth model associated
+//               with this character.  
+//
+//               This is the node at which the character, animation
+//               bundle, or LOD officially began within its particular
+//               egg file.
+////////////////////////////////////////////////////////////////////
+INLINE EggNode *EggCharacterData::
+get_model_root(int n) const {
+  nassertr(n >= 0 && n < (int)_models.size(), (EggNode *)NULL);
+  return _models[n]._model_root;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: EggCharacterData::get_root_joint
 //     Function: EggCharacterData::get_root_joint
 //       Access: Public
 //       Access: Public
@@ -18,3 +61,14 @@ INLINE EggJointData *EggCharacterData::
 get_root_joint() const {
 get_root_joint() const {
   return _root_joint;
   return _root_joint;
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggCharacterData::find_joint
+//       Access: Public
+//  Description: Returns the first joint found with the indicated
+//               name, or NULL if no joint has that name.
+////////////////////////////////////////////////////////////////////
+INLINE EggJointData *EggCharacterData::
+find_joint(const string &name) const {
+  return _root_joint->find_joint(name);
+}

+ 15 - 0
pandatool/src/eggcharbase/eggCharacterData.cxx

@@ -37,6 +37,21 @@ EggCharacterData::
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggCharacterData::add_model
+//       Access: Public
+//  Description: Indicates that the given model_index (with the
+//               indicated model_root) is associated with this
+//               character.
+////////////////////////////////////////////////////////////////////
+void EggCharacterData::
+add_model(int model_index, EggNode *model_root) {
+  Model m;
+  m._model_index = model_index;
+  m._model_root = model_root;
+  _models.push_back(m);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: EggCharacterData::make_slider
 //     Function: EggCharacterData::make_slider
 //       Access: Public
 //       Access: Public

+ 18 - 1
pandatool/src/eggcharbase/eggCharacterData.h

@@ -8,12 +8,15 @@
 
 
 #include <pandatoolbase.h>
 #include <pandatoolbase.h>
 
 
+#include "eggJointData.h"
+
+#include <eggNode.h>
+#include <pointerTo.h>
 #include <namable.h>
 #include <namable.h>
 
 
 #include <map>
 #include <map>
 
 
 class EggCharacterCollection;
 class EggCharacterCollection;
-class EggJointData;
 class EggSliderData;
 class EggSliderData;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -45,13 +48,27 @@ public:
   EggCharacterData(EggCharacterCollection *collection);
   EggCharacterData(EggCharacterCollection *collection);
   virtual ~EggCharacterData();
   virtual ~EggCharacterData();
 
 
+  void add_model(int model_index, EggNode *model_root);
+  INLINE int get_num_models() const;
+  INLINE int get_model_index(int n) const;
+  INLINE EggNode *get_model_root(int n) const;
+
   INLINE EggJointData *get_root_joint() const;
   INLINE EggJointData *get_root_joint() const;
+  INLINE EggJointData *find_joint(const string &name) const;
 
 
   EggSliderData *make_slider(const string &name);
   EggSliderData *make_slider(const string &name);
 
 
   virtual void write(ostream &out, int indent_level = 0) const;
   virtual void write(ostream &out, int indent_level = 0) const;
 
 
 protected:
 protected:
+  class Model {
+  public:
+    int _model_index;
+    PT(EggNode) _model_root;
+  };
+  typedef vector<Model> Models;
+  Models _models;
+
   EggCharacterCollection *_collection;
   EggCharacterCollection *_collection;
   EggJointData *_root_joint;
   EggJointData *_root_joint;
 
 

+ 1 - 3
pandatool/src/eggcharbase/eggCharacterFilter.cxx

@@ -49,15 +49,13 @@ post_command_line() {
   for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) {
   for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) {
     EggData *data = (*ei);
     EggData *data = (*ei);
     
     
-    if (!_collection->add_egg(data)) {
+    if (_collection->add_egg(data) < 0) {
       nout << data->get_egg_filename().get_basename()
       nout << data->get_egg_filename().get_basename()
 	   << " does not contain a character model or animation channel.\n";
 	   << " does not contain a character model or animation channel.\n";
       return false;
       return false;
     }
     }
   }
   }
 
 
-  _collection->write(cerr);
-
   return true;
   return true;
 }
 }
 
 

+ 8 - 8
pandatool/src/eggcharbase/eggComponentData.I

@@ -5,29 +5,29 @@
 
 
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggComponentData::get_num_back_pointers
+//     Function: EggComponentData::get_num_models
 //       Access: Public
 //       Access: Public
 //  Description: Returns the maximum number of back pointers this
 //  Description: Returns the maximum number of back pointers this
 //               component may have.  The component may store a back
 //               component may have.  The component may store a back
-//               pointer for models indexed 0 .. num_back_pointers -
-//               1.  You must call has_back_pointer() on each model
+//               pointer for models indexed 0 .. num_models -
+//               1.  You must call has_model() on each model
 //               index to confirm whether a particular model in that
 //               index to confirm whether a particular model in that
 //               range has a back pointer.
 //               range has a back pointer.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE int EggComponentData::
 INLINE int EggComponentData::
-get_num_back_pointers() const {
+get_num_models() const {
   return _back_pointers.size();
   return _back_pointers.size();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggComponentData::has_back_pointer
+//     Function: EggComponentData::has_model
 //       Access: Public
 //       Access: Public
 //  Description: Returns true if the component has a back pointer to
 //  Description: Returns true if the component has a back pointer to
 //               an egg file somewhere for the indicated model, false
 //               an egg file somewhere for the indicated model, false
 //               otherwise.
 //               otherwise.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE bool EggComponentData::
 INLINE bool EggComponentData::
-has_back_pointer(int model_index) const {
+has_model(int model_index) const {
   if (model_index >= 0 && model_index < (int)_back_pointers.size()) {
   if (model_index >= 0 && model_index < (int)_back_pointers.size()) {
     return _back_pointers[model_index] != (EggBackPointer *)NULL;
     return _back_pointers[model_index] != (EggBackPointer *)NULL;
   }
   }
@@ -35,13 +35,13 @@ has_back_pointer(int model_index) const {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggComponentData::get_back_pointer
+//     Function: EggComponentData::get_model
 //       Access: Public
 //       Access: Public
 //  Description: Returns the back pointer to an egg file for the
 //  Description: Returns the back pointer to an egg file for the
 //               indicated model if it exists, or NULL if it does not.
 //               indicated model if it exists, or NULL if it does not.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE EggBackPointer *EggComponentData::
 INLINE EggBackPointer *EggComponentData::
-get_back_pointer(int model_index) const {
+get_model(int model_index) const {
   if (model_index >= 0 && model_index < (int)_back_pointers.size()) {
   if (model_index >= 0 && model_index < (int)_back_pointers.size()) {
     return _back_pointers[model_index];
     return _back_pointers[model_index];
   }
   }

+ 2 - 2
pandatool/src/eggcharbase/eggComponentData.cxx

@@ -68,13 +68,13 @@ matches_name(const string &name) const {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggComponentData::set_back_pointer
+//     Function: EggComponentData::set_model
 //       Access: Public
 //       Access: Public
 //  Description: Sets the back_pointer associated with the given
 //  Description: Sets the back_pointer associated with the given
 //               model_index.
 //               model_index.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void EggComponentData::
 void EggComponentData::
-set_back_pointer(int model_index, EggBackPointer *back) {
+set_model(int model_index, EggBackPointer *back) {
   while ((int)_back_pointers.size() <= model_index) {
   while ((int)_back_pointers.size() <= model_index) {
     _back_pointers.push_back((EggBackPointer *)NULL);
     _back_pointers.push_back((EggBackPointer *)NULL);
   }
   }

+ 4 - 4
pandatool/src/eggcharbase/eggComponentData.h

@@ -35,10 +35,10 @@ public:
   virtual void add_back_pointer(int model_index, EggObject *egg_object)=0;
   virtual void add_back_pointer(int model_index, EggObject *egg_object)=0;
   virtual void write(ostream &out, int indent_level = 0) const=0;
   virtual void write(ostream &out, int indent_level = 0) const=0;
 
 
-  INLINE int get_num_back_pointers() const;
-  INLINE bool has_back_pointer(int model_index) const;
-  INLINE EggBackPointer *get_back_pointer(int model_index) const;
-  void set_back_pointer(int model_index, EggBackPointer *back);
+  INLINE int get_num_models() const;
+  INLINE bool has_model(int model_index) const;
+  INLINE EggBackPointer *get_model(int model_index) const;
+  void set_model(int model_index, EggBackPointer *back);
 
 
 protected:
 protected:
 
 

+ 30 - 7
pandatool/src/eggcharbase/eggJointData.cxx

@@ -4,7 +4,7 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
 #include "eggJointData.h"
 #include "eggJointData.h"
-#include "eggJointPointer.h"
+#include "eggJointNodePointer.h"
 #include "eggMatrixTablePointer.h"
 #include "eggMatrixTablePointer.h"
 
 
 #include <eggGroup.h>
 #include <eggGroup.h>
@@ -24,6 +24,29 @@ EggJointData(EggCharacterCollection *collection,
 {
 {
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggJointData::find_joint
+//       Access: Public
+//  Description: Returns the first descendent joint found with the
+//               indicated name, or NULL if no joint has that name.
+////////////////////////////////////////////////////////////////////
+INLINE EggJointData *EggJointData::
+find_joint(const string &name) {
+  Children::const_iterator ci;
+  for (ci = _children.begin(); ci != _children.end(); ++ci) {
+    EggJointData *child = (*ci);
+    if (child->get_name() == name) {
+      return child;
+    }
+    EggJointData *result = child->find_joint(name);
+    if (result != (EggJointData *)NULL) {
+      return result;
+    }
+  }
+
+  return (EggJointData *)NULL;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: EggJointData::add_back_pointer
 //     Function: EggJointData::add_back_pointer
 //       Access: Public, Virtual
 //       Access: Public, Virtual
@@ -34,13 +57,13 @@ void EggJointData::
 add_back_pointer(int model_index, EggObject *egg_object) {
 add_back_pointer(int model_index, EggObject *egg_object) {
   if (egg_object->is_of_type(EggGroup::get_class_type())) {
   if (egg_object->is_of_type(EggGroup::get_class_type())) {
     // It must be a <Joint>.
     // It must be a <Joint>.
-    EggJointPointer *joint = new EggJointPointer(egg_object);
-    set_back_pointer(model_index, joint);
+    EggJointNodePointer *joint = new EggJointNodePointer(egg_object);
+    set_model(model_index, joint);
 
 
   } else if (egg_object->is_of_type(EggTable::get_class_type())) {
   } else if (egg_object->is_of_type(EggTable::get_class_type())) {
     // It's a <Table> with an "xform" child beneath it.
     // It's a <Table> with an "xform" child beneath it.
     EggMatrixTablePointer *xform = new EggMatrixTablePointer(egg_object);
     EggMatrixTablePointer *xform = new EggMatrixTablePointer(egg_object);
-    set_back_pointer(model_index, xform);
+    set_model(model_index, xform);
 
 
   } else {
   } else {
     nout << "Invalid object added to joint for back pointer.\n";
     nout << "Invalid object added to joint for back pointer.\n";
@@ -57,9 +80,9 @@ write(ostream &out, int indent_level) const {
   indent(out, indent_level)
   indent(out, indent_level)
     << "Joint " << get_name()
     << "Joint " << get_name()
     << " (models:";
     << " (models:";
-  int num_back_pointers = get_num_back_pointers();
-  for (int model_index = 0; model_index < num_back_pointers; model_index++) {
-    if (has_back_pointer(model_index)) {
+  int num_models = get_num_models();
+  for (int model_index = 0; model_index < num_models; model_index++) {
+    if (has_model(model_index)) {
       out << " " << model_index;
       out << " " << model_index;
     }
     }
   }
   }

+ 1 - 0
pandatool/src/eggcharbase/eggJointData.h

@@ -25,6 +25,7 @@ public:
 
 
   INLINE int get_num_children() const;
   INLINE int get_num_children() const;
   INLINE EggJointData *get_child(int n) const;
   INLINE EggJointData *get_child(int n) const;
+  EggJointData *find_joint(const string &name);
 
 
   virtual void add_back_pointer(int model_index, EggObject *egg_object);
   virtual void add_back_pointer(int model_index, EggObject *egg_object);
   virtual void write(ostream &out, int indent_level = 0) const;
   virtual void write(ostream &out, int indent_level = 0) const;

+ 81 - 0
pandatool/src/eggcharbase/eggJointNodePointer.cxx

@@ -0,0 +1,81 @@
+// Filename: eggJointNodePointer.cxx
+// Created by:  drose (26Feb01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "eggJointNodePointer.h"
+
+#include <eggObject.h>
+#include <eggGroup.h>
+#include <pointerTo.h>
+
+
+TypeHandle EggJointNodePointer::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggJointNodePointer::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+EggJointNodePointer::
+EggJointNodePointer(EggObject *object) {
+  _joint = DCAST(EggGroup, object);
+
+  if (_joint != (EggGroup *)NULL) {
+    // Quietly insist that the joint has a transform, for neatness.  If
+    // it does not, give it the identity transform.
+    if (!_joint->has_transform()) {
+      _joint->set_transform(LMatrix4d::ident_mat());
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggJointNodePointer::get_num_frames
+//       Access: Public, Virtual
+//  Description: Returns the number of frames of animation for this
+//               particular joint.
+//
+//               In the case of a EggJointNodePointer, which just
+//               stores a pointer to a <Joint> entry for a character
+//               model (not an animation table), there is always
+//               exactly one frame: the rest pose.
+////////////////////////////////////////////////////////////////////
+int EggJointNodePointer::
+get_num_frames() const {
+  return 1;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggJointNodePointer::get_frame
+//       Access: Public, Virtual
+//  Description: Returns the transform matrix corresponding to this
+//               joint position in the nth frame.
+//
+//               In the case of a EggJointNodePointer, which just
+//               stores a pointer to a <Joint> entry for a character
+//               model (not an animation table), there is always
+//               exactly one frame: the rest pose.
+////////////////////////////////////////////////////////////////////
+LMatrix4d EggJointNodePointer::
+get_frame(int n) const {
+  nassertr(n == 0, LMatrix4d::ident_mat());
+  return _joint->get_transform();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggJointNodePointer::set_frame
+//       Access: Public, Virtual
+//  Description: Sets the transform matrix corresponding to this
+//               joint position in the nth frame.
+//
+//               In the case of a EggJointNodePointer, which just
+//               stores a pointer to a <Joint> entry for a character
+//               model (not an animation table), there is always
+//               exactly one frame: the rest pose.
+////////////////////////////////////////////////////////////////////
+void EggJointNodePointer::
+set_frame(int n, const LMatrix4d &mat) {
+  nassertv(n == 0);
+  _joint->set_transform(mat);
+}

+ 51 - 0
pandatool/src/eggcharbase/eggJointNodePointer.h

@@ -0,0 +1,51 @@
+// Filename: eggJointNodePointer.h
+// Created by:  drose (26Feb01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef EGGJOINTNODEPOINTER_H
+#define EGGJOINTNODEPOINTER_H
+
+#include <pandatoolbase.h>
+
+#include "eggJointPointer.h"
+
+#include <eggGroup.h>
+#include <pointerTo.h>
+
+////////////////////////////////////////////////////////////////////
+// 	 Class : EggJointNodePointer
+// Description : This stores a pointer back to a <Joint> node.
+////////////////////////////////////////////////////////////////////
+class EggJointNodePointer : public EggJointPointer {
+public:
+  EggJointNodePointer(EggObject *object);
+
+  virtual int get_num_frames() const;
+  virtual LMatrix4d get_frame(int n) const;
+  virtual void set_frame(int n, const LMatrix4d &mat);
+
+private:
+  PT(EggGroup) _joint;
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    EggJointPointer::init_type();
+    register_type(_type_handle, "EggJointNodePointer",
+		  EggJointPointer::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
+
+

+ 9 - 6
pandatool/src/eggcharbase/eggJointPointer.cxx

@@ -8,12 +8,15 @@
 
 
 TypeHandle EggJointPointer::_type_handle;
 TypeHandle EggJointPointer::_type_handle;
 
 
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggJointPointer::Constructor
-//       Access: Public
-//  Description: 
+//     Function: EggJointPointer::add_frame
+//       Access: Public, Virtual
+//  Description: Appends a new frame onto the end of the data, if
+//               possible; returns true if not possible, or false
+//               otherwise (e.g. for a static joint).
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-EggJointPointer::
-EggJointPointer(EggObject *object) {
-  _joint = DCAST(EggGroup, object);
+bool EggJointPointer::
+add_frame(const LMatrix4d &) {
+  return false;
 }
 }

+ 11 - 7
pandatool/src/eggcharbase/eggJointPointer.h

@@ -10,19 +10,23 @@
 
 
 #include "eggBackPointer.h"
 #include "eggBackPointer.h"
 
 
-#include <eggGroup.h>
-#include <pointerTo.h>
+#include <luse.h>
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 // 	 Class : EggJointPointer
 // 	 Class : EggJointPointer
-// Description : This stores a pointer back to a <Joint> node.
+// Description : This is a base class for EggJointNodePointer and
+//               EggMatrixTablePointer.  It stores a back pointer to
+//               either a <Joint> entry or an xform <Table> data, and
+//               thus presents an interface that returns 1-n matrices,
+//               one for each frame.  (<Joint> entries, for model
+//               files, appear the same as one-frame animations.)
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EggJointPointer : public EggBackPointer {
 class EggJointPointer : public EggBackPointer {
 public:
 public:
-  EggJointPointer(EggObject *object);
-
-private:
-  PT(EggGroup) _joint;
+  virtual int get_num_frames() const=0;
+  virtual LMatrix4d get_frame(int n) const=0;
+  virtual void set_frame(int n, const LMatrix4d &mat)=0;
+  virtual bool add_frame(const LMatrix4d &mat);
 
 
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {

+ 54 - 0
pandatool/src/eggcharbase/eggMatrixTablePointer.cxx

@@ -43,3 +43,57 @@ EggMatrixTablePointer(EggObject *object) {
     }
     }
   }
   }
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggMatrixTablePointer::get_num_frames
+//       Access: Public, Virtual
+//  Description: Returns the number of frames of animation for this
+//               particular joint.
+////////////////////////////////////////////////////////////////////
+int EggMatrixTablePointer::
+get_num_frames() const {
+  if (_xform == (EggXfmSAnim *)NULL) {
+    return 0;
+  } else {
+    return _xform->get_num_rows();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggMatrixTablePointer::get_frame
+//       Access: Public, Virtual
+//  Description: Returns the transform matrix corresponding to this
+//               joint position in the nth frame.
+////////////////////////////////////////////////////////////////////
+LMatrix4d EggMatrixTablePointer::
+get_frame(int n) const {
+  nassertr(n >= 0 && n < get_num_frames(), LMatrix4d::ident_mat());
+  LMatrix4d mat;
+  _xform->get_value(n, mat);
+  return mat;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggMatrixTablePointer::set_frame
+//       Access: Public, Virtual
+//  Description: Sets the transform matrix corresponding to this
+//               joint position in the nth frame.
+////////////////////////////////////////////////////////////////////
+void EggMatrixTablePointer::
+set_frame(int n, const LMatrix4d &mat) {
+  nassertv(n >= 0 && n < get_num_frames());
+  // Do something here.
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggMatrixTablePointer::add_frame
+//       Access: Public, Virtual
+//  Description: Appends a new frame onto the end of the data, if
+//               possible; returns true if not possible, or false
+//               otherwise (e.g. for a static joint).
+////////////////////////////////////////////////////////////////////
+bool EggMatrixTablePointer::
+add_frame(const LMatrix4d &mat) {
+  // Do something here.
+  return true;
+}

+ 9 - 4
pandatool/src/eggcharbase/eggMatrixTablePointer.h

@@ -8,7 +8,7 @@
 
 
 #include <pandatoolbase.h>
 #include <pandatoolbase.h>
 
 
-#include "eggBackPointer.h"
+#include "eggJointPointer.h"
 
 
 #include <eggTable.h>
 #include <eggTable.h>
 #include <eggXfmSAnim.h>
 #include <eggXfmSAnim.h>
@@ -21,10 +21,15 @@
 //               corresponding to the animation data from a single
 //               corresponding to the animation data from a single
 //               bundle for this joint.
 //               bundle for this joint.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-class EggMatrixTablePointer : public EggBackPointer {
+class EggMatrixTablePointer : public EggJointPointer {
 public:
 public:
   EggMatrixTablePointer(EggObject *object);
   EggMatrixTablePointer(EggObject *object);
 
 
+  virtual int get_num_frames() const;
+  virtual LMatrix4d get_frame(int n) const;
+  virtual void set_frame(int n, const LMatrix4d &mat);
+  virtual bool add_frame(const LMatrix4d &mat);
+
 private:
 private:
   PT(EggTable) _table;
   PT(EggTable) _table;
   PT(EggXfmSAnim) _xform;
   PT(EggXfmSAnim) _xform;
@@ -34,9 +39,9 @@ public:
     return _type_handle;
     return _type_handle;
   }
   }
   static void init_type() {
   static void init_type() {
-    EggBackPointer::init_type();
+    EggJointPointer::init_type();
     register_type(_type_handle, "EggMatrixTablePointer",
     register_type(_type_handle, "EggMatrixTablePointer",
-		  EggBackPointer::get_class_type());
+		  EggJointPointer::get_class_type());
   }
   }
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {
     return get_class_type();
     return get_class_type();

+ 9 - 9
pandatool/src/eggcharbase/eggSliderData.cxx

@@ -33,26 +33,26 @@ void EggSliderData::
 add_back_pointer(int model_index, EggObject *egg_object) {
 add_back_pointer(int model_index, EggObject *egg_object) {
   if (egg_object->is_of_type(EggPrimitive::get_class_type())) {
   if (egg_object->is_of_type(EggPrimitive::get_class_type())) {
     // A primitive!
     // A primitive!
-    EggBackPointer *back = get_back_pointer(model_index);
+    EggBackPointer *back = get_model(model_index);
     if (back == (EggBackPointer *)NULL) {
     if (back == (EggBackPointer *)NULL) {
       back = new EggVertexPointer;
       back = new EggVertexPointer;
-      set_back_pointer(model_index, back);
+      set_model(model_index, back);
     }
     }
 
 
   } else if (egg_object->is_of_type(EggVertex::get_class_type())) {
   } else if (egg_object->is_of_type(EggVertex::get_class_type())) {
     // A vertex!
     // A vertex!
-    EggBackPointer *back = get_back_pointer(model_index);
+    EggBackPointer *back = get_model(model_index);
     if (back == (EggBackPointer *)NULL) {
     if (back == (EggBackPointer *)NULL) {
       back = new EggVertexPointer;
       back = new EggVertexPointer;
-      set_back_pointer(model_index, back);
+      set_model(model_index, back);
     }
     }
 
 
   } else if (egg_object->is_of_type(EggSAnimData::get_class_type())) {
   } else if (egg_object->is_of_type(EggSAnimData::get_class_type())) {
     // A slider animation table!  Woo hoo!
     // A slider animation table!  Woo hoo!
-    EggBackPointer *back = get_back_pointer(model_index);
+    EggBackPointer *back = get_model(model_index);
     if (back == (EggBackPointer *)NULL) {
     if (back == (EggBackPointer *)NULL) {
       back = new EggVertexPointer;
       back = new EggVertexPointer;
-      set_back_pointer(model_index, back);
+      set_model(model_index, back);
     }
     }
 
 
   } else {
   } else {
@@ -70,9 +70,9 @@ write(ostream &out, int indent_level) const {
   indent(out, indent_level)
   indent(out, indent_level)
     << "Slider " << get_name()
     << "Slider " << get_name()
     << " (models:";
     << " (models:";
-  int num_back_pointers = get_num_back_pointers();
-  for (int model_index = 0; model_index < num_back_pointers; model_index++) {
-    if (has_back_pointer(model_index)) {
+  int num_models = get_num_models();
+  for (int model_index = 0; model_index < num_models; model_index++) {
+    if (has_model(model_index)) {
       out << " " << model_index;
       out << " " << model_index;
     }
     }
   }
   }

+ 205 - 0
pandatool/src/eggprogs/eggTopstrip.cxx

@@ -5,6 +5,12 @@
 
 
 #include "eggTopstrip.h"
 #include "eggTopstrip.h"
 
 
+#include <eggJointData.h>
+#include <eggCharacterCollection.h>
+#include <eggCharacterData.h>
+#include <eggJointPointer.h>
+#include <eggTable.h>
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: EggTopstrip::Constructor
 //     Function: EggTopstrip::Constructor
 //       Access: Public
 //       Access: Public
@@ -20,6 +26,42 @@ EggTopstrip() {
 
 
      "This is a particularly useful thing to do to generate character "
      "This is a particularly useful thing to do to generate character "
      "models that can stack one on top of the other in a sensible way.");
      "models that can stack one on top of the other in a sensible way.");
+
+  add_option
+    ("t", "name", 0, 
+     "Specify the name of the 'top' joint, from which to draw the "
+     "animation channels which will be applied to the entire animation.",
+     &EggTopstrip::dispatch_string, NULL, &_top_joint_name);
+
+  add_option
+    ("i", "", 0, 
+     "Invert the matrix before applying.  This causes a subtractive "
+     "effect.  This is the default unless -r is specified.",
+     &EggTopstrip::dispatch_true, &_got_invert_transform, &_invert_transform);
+
+  add_option
+    ("n", "", 0, 
+     "Do not invert the matrix before applying.  This causes an "
+     "additive effect.",
+     &EggTopstrip::dispatch_true, &_got_invert_transform, &_invert_transform);
+
+  add_option
+    ("s", "[ijkphrxyz]", 0, 
+     "Specify the components of the transform that are to be applied.  Use "
+     "any combination of the nine token letters: i, j, k represent the "
+     "three scale axes; h, p, r represent rotation; and x, y, z represent "
+     "translation.  The default is everything: -s ijkphrxyz.",
+     &EggTopstrip::dispatch_string, NULL, &_transform_channels);
+
+  add_option
+    ("r", "file.egg", 0, 
+     "Read the animation channel from the indicated egg file.  If this "
+     "is not specified, the first egg file named on the command line is "
+     "used.",
+     &EggTopstrip::dispatch_filename, NULL, &_channel_filename);
+
+  _invert_transform = true;
+  _transform_channels = "ijkphrxyz";
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -29,6 +71,169 @@ EggTopstrip() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void EggTopstrip::
 void EggTopstrip::
 run() {
 run() {
+  nassertv(_collection != (EggCharacterCollection *)NULL);
+  nassertv(_collection->get_num_eggs() > 0);
+
+  // Get the number of characters first, in case adding the
+  // _channel_egg changes this.
+  int num_characters = _collection->get_num_characters();
+
+  // Determine which model we'll be pulling the animation channels
+  // from.
+  int from_model = -1;
+
+  if (!_channel_filename.empty()) {
+    // Read in the extra egg file that we use for extracting the
+    // channels out.
+    PT(EggData) channel_egg = read_egg(_channel_filename);
+    if (channel_egg == (EggData *)NULL) {
+      nout << "Cannot read " << _channel_filename << "\n";
+      exit(1);
+    }
+    int channel_egg_index = _collection->add_egg(channel_egg);
+    if (channel_egg_index < 0) {
+      nout << _channel_filename
+	   << " does not contain a character model or animation channel.\n";
+      exit(1);
+    }
+
+    from_model = _collection->get_first_model_index(channel_egg_index);
+
+    if (!_got_invert_transform) {
+      // With -r, the default is not to invert the transform.
+      _invert_transform = false;
+    }
+  }
+
+  // Now process each character.
+  for (int i = 0; i < num_characters; i++) {
+    EggCharacterData *char_data = _collection->get_character(i);
+
+    EggJointData *root_joint = char_data->get_root_joint();
+
+    EggJointData *top_joint = (EggJointData *)NULL;
+    if (_top_joint_name.empty()) {
+      // The default top joint name is the alphabetically first joint
+      // in the top level.
+      if (root_joint->get_num_children() == 0) {
+	nout << "Character " << char_data->get_name() << " has no joints.\n";
+	exit(1);
+      }
+      top_joint = root_joint->get_child(0);
+    } else {
+      top_joint = char_data->find_joint(_top_joint_name);
+      if (top_joint == (EggJointData *)NULL) {
+	nout << "Character " << char_data->get_name()
+	     << " has no joint named " << _top_joint_name << "\n";
+	exit(1);
+      }
+    }
+
+    int num_children = root_joint->get_num_children();
+    for (int i = 0; i < num_children; i++) {
+      EggJointData *joint_data = root_joint->get_child(i);
+      strip_anim(joint_data, from_model, top_joint);
+    }
+
+    // We also need to transform the vertices for any models involved
+    // here.
+    int num_models = char_data->get_num_models();
+    for (int m = 0; m < num_models; m++) {
+      EggNode *node = char_data->get_model_root(m);
+      if (!node->is_of_type(EggTable::get_class_type())) {
+	strip_anim_vertices(node, m, from_model, top_joint);
+      }
+    }
+  }
+
+  write_eggs();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggTopstrip::strip_anim
+//       Access: Public
+//  Description: Applies the channels from joint _top_joint
+//               in model from_model to the joint referenced by
+//               joint_data.
+////////////////////////////////////////////////////////////////////
+void EggTopstrip::
+strip_anim(EggJointData *joint_data, int from_model, EggJointData *top_joint) {
+  int num_models = joint_data->get_num_models();
+  for (int i = 0; i < num_models; i++) {
+    EggBackPointer *back = joint_data->get_model(i);
+    if (back != (EggBackPointer *)NULL) {
+      EggJointPointer *joint;
+      DCAST_INTO_V(joint, back);
+
+      cerr << "joint is " << joint->get_type() << "\n";
+
+      int model = (from_model < 0) ? i : from_model;
+      EggBackPointer *from_back = top_joint->get_model(model);
+      if (from_back == (EggBackPointer *)NULL) {
+	nout << "Joint " << top_joint->get_name() << " has no model index "
+	     << model << "\n";
+	exit(1);
+      }
+      EggJointPointer *from_joint;
+      DCAST_INTO_V(from_joint, from_back);
+
+      int num_into_frames = joint->get_num_frames();
+      int num_from_frames = from_joint->get_num_frames();
+
+      int num_frames = max(num_into_frames, num_from_frames);
+
+      for (int f = 0; f < num_frames; f++) {
+	LMatrix4d start = joint->get_frame(f % num_into_frames);
+	LMatrix4d strip = from_joint->get_frame(f % num_from_frames);
+
+	if (_invert_transform) {
+	  strip.invert_in_place();
+	}
+
+	cerr << "Applying " << strip << " to " << f << " of " 
+	     << joint_data->get_name() << " model " << i << "\n";
+
+	if (f >= num_into_frames) {
+	  if (!joint->add_frame(start * strip)) {
+	    nout << "Cannot apply multiple frames of animation to a model file.\n"
+		 << "In general, be careful when using -r and model files.\n";
+	    exit(1);
+	  }
+	} else {
+	  joint->set_frame(f, start * strip);
+	}
+      }
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggTopstrip::strip_anim_vertices
+//       Access: Public
+//  Description: Applies the channels from joint _top_joint
+//               in model from_model to the vertices at egg_node.
+////////////////////////////////////////////////////////////////////
+void EggTopstrip::
+strip_anim_vertices(EggNode *egg_node, int into_model, int from_model, 
+		    EggJointData *top_joint) {
+  int model = (from_model < 0) ? into_model : from_model;
+  EggBackPointer *from_back = top_joint->get_model(model);
+  if (from_back == (EggBackPointer *)NULL) {
+    nout << "Joint " << top_joint->get_name() << " has no model index "
+	 << model << "\n";
+    exit(1);
+  }
+
+  EggJointPointer *from_joint;
+  DCAST_INTO_V(from_joint, from_back);
+
+  LMatrix4d strip = from_joint->get_frame(0);
+  if (_invert_transform) {
+    strip.invert_in_place();
+  }
+
+  cerr << "Applying " << strip << " to vertices.\n";
+  egg_node->transform_vertices_only(strip);
 }
 }
 
 
 
 

+ 18 - 0
pandatool/src/eggprogs/eggTopstrip.h

@@ -9,6 +9,12 @@
 #include <pandatoolbase.h>
 #include <pandatoolbase.h>
 
 
 #include <eggCharacterFilter.h>
 #include <eggCharacterFilter.h>
+#include <luse.h>
+
+#include <vector>
+
+class EggJointData;
+class EggJointPointer;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 // 	 Class : EggTopstrip
 // 	 Class : EggTopstrip
@@ -23,6 +29,18 @@ public:
   EggTopstrip();
   EggTopstrip();
 
 
   void run();
   void run();
+
+  void strip_anim(EggJointData *joint_data, int from_model,
+		  EggJointData *top_joint);
+  void strip_anim_vertices(EggNode *egg_node, int into_model,
+			   int from_model, EggJointData *top_joint);
+
+
+  string _top_joint_name;
+  bool _got_invert_transform;
+  bool _invert_transform;
+  string _transform_channels;
+  Filename _channel_filename;
 };
 };
 
 
 #endif
 #endif

+ 36 - 0
pandatool/src/progbase/programBase.cxx

@@ -567,6 +567,42 @@ dispatch_none(const string &, const string &, void *) {
   return true;
   return true;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: ProgramBase::dispatch_true
+//       Access: Protected, Static
+//  Description: Standard dispatch function for an option that takes
+//               no parameters, and when it is present sets a bool
+//               variable to the 'true' value.  This is another way to
+//               handle a boolean flag.  See also dispatch_none() and
+//               dispatch_false().
+//
+//               The data pointer is to a bool variable.
+////////////////////////////////////////////////////////////////////
+bool ProgramBase::
+dispatch_true(const string &, const string &, void *var) {
+  bool *bp = (bool *)var;
+  (*bp) = true;
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ProgramBase::dispatch_false
+//       Access: Protected, Static
+//  Description: Standard dispatch function for an option that takes
+//               no parameters, and when it is present sets a bool
+//               variable to the 'false' value.  This is another way to
+//               handle a boolean flag.  See also dispatch_none() and
+//               dispatch_true().
+//
+//               The data pointer is to a bool variable.
+////////////////////////////////////////////////////////////////////
+bool ProgramBase::
+dispatch_false(const string &, const string &, void *var) {
+  bool *bp = (bool *)var;
+  (*bp) = false;
+  return true;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ProgramBase::dispatch_count
 //     Function: ProgramBase::dispatch_count
 //       Access: Protected, Static
 //       Access: Protected, Static

+ 2 - 0
pandatool/src/progbase/programBase.h

@@ -66,6 +66,8 @@ protected:
   bool remove_option(const string &option);
   bool remove_option(const string &option);
 
 
   static bool dispatch_none(const string &opt, const string &arg, void *);
   static bool dispatch_none(const string &opt, const string &arg, void *);
+  static bool dispatch_true(const string &opt, const string &arg, void *var);
+  static bool dispatch_false(const string &opt, const string &arg, void *var);
   static bool dispatch_count(const string &opt, const string &arg, void *var);
   static bool dispatch_count(const string &opt, const string &arg, void *var);
   static bool dispatch_int(const string &opt, const string &arg, void *var);
   static bool dispatch_int(const string &opt, const string &arg, void *var);
   static bool dispatch_int_pair(const string &opt, const string &arg, void *var);
   static bool dispatch_int_pair(const string &opt, const string &arg, void *var);