瀏覽代碼

egg-retarget-anim

David Rose 20 年之前
父節點
當前提交
53eb393661

+ 18 - 0
pandatool/src/eggcharbase/eggCharacterCollection.cxx

@@ -666,6 +666,24 @@ found_egg_match(EggCharacterData *char_data, EggJointData *joint_data,
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggCharacterCollection::rename_char
+//       Access: Public
+//  Description: Renames the ith character to the indicated name.
+//               This name must not already be used by another
+//               character in the collection.
+////////////////////////////////////////////////////////////////////
+void EggCharacterCollection::
+rename_char(int i, const string &name) {
+  nassertv(i >= 0 && i < (int)_characters.size());
+
+  EggCharacterData *char_data = _characters[i];
+  if (char_data->get_name() != name) {
+    nassertv(get_character_by_name(name) == (EggCharacterData *)NULL);
+    char_data->rename_char(name);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: EggCharacterCollection::write
 //       Access: Public, Virtual

+ 2 - 0
pandatool/src/eggcharbase/eggCharacterCollection.h

@@ -54,6 +54,8 @@ public:
 
   INLINE EggCharacterData *get_character_by_model_index(int model_index) const;
 
+  void rename_char(int i, const string &name);
+
   virtual void write(ostream &out, int indent_level = 0) const;
   void check_errors(ostream &out, bool force_initial_rest_frame);
 

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

@@ -64,6 +64,26 @@ EggCharacterData::
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggCharacterData::rename_char
+//       Access: Public
+//  Description: Renames all of the models in the character data to
+//               the indicated name.  This is the name that is used to
+//               identify unique skeleton hierarchies; if you set two
+//               different models to the same name, they will be
+//               loaded together as if they are expected to have the
+//               same skeleton hierarchy.
+////////////////////////////////////////////////////////////////////
+void EggCharacterData::
+rename_char(const string &name) {
+  Models::iterator mi;
+  for (mi = _models.begin(); mi != _models.end(); ++mi) {
+    (*mi)._model_root->set_name(name);
+  }
+
+  set_name(name);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: EggCharacterData::add_model
 //       Access: Public

+ 2 - 0
pandatool/src/eggcharbase/eggCharacterData.h

@@ -66,6 +66,8 @@ public:
   EggCharacterData(EggCharacterCollection *collection);
   virtual ~EggCharacterData();
 
+  void rename_char(const string &name);
+
   void add_model(int model_index, EggNode *model_root, EggData *egg_data);
   INLINE int get_num_models() const;
   INLINE int get_model_index(int n) const;

+ 9 - 0
pandatool/src/eggprogs/Sources.pp

@@ -56,6 +56,15 @@
 
 #end bin_target
 
+#begin bin_target
+  #define LOCAL_LIBS eggcharbase $[LOCAL_LIBS]
+  #define TARGET egg-retarget-anim
+
+  #define SOURCES \
+    eggRetargetAnim.cxx eggRetargetAnim.h
+
+#end bin_target
+
 #begin bin_target
   #define TARGET egg2c
 

+ 184 - 0
pandatool/src/eggprogs/eggRetargetAnim.cxx

@@ -0,0 +1,184 @@
+// Filename: eggRetargetAnim.cxx
+// Created by:  drose (05May05)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "eggRetargetAnim.h"
+
+#include "dcast.h"
+#include "eggJointData.h"
+#include "eggCharacterCollection.h"
+#include "eggCharacterData.h"
+#include "eggJointPointer.h"
+#include "eggTable.h"
+#include "compose_matrix.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggRetargetAnim::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+EggRetargetAnim::
+EggRetargetAnim() {
+  add_path_replace_options();
+  add_path_store_options();
+
+  set_program_description
+    ("egg-retarget-anim reads a character model and its associated animation "
+     "files, and removes the translations and scales from the animation "
+     "files, replacing them with the translations and scales from the "
+     "rest position of the character model.\n\n"
+
+     "This allows an animation that was generated for a model with one "
+     "skeleton to be played successfully on a model with a different "
+     "skeleton, provided that both skeletons have the same hierarchy and "
+     "differ only in scales and/or translations of the various joints, "
+     "and that scales and translations are not part of the per-frame "
+     "animations.");
+
+  add_option
+    ("r", "file.egg", 0,
+     "Read the reference model from the indicated egg file.  All of the "
+     "animations will be retargeted to match the indicated file.",
+     &EggRetargetAnim::dispatch_filename, NULL, &_reference_filename);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggRetargetAnim::run
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+void EggRetargetAnim::
+run() {
+  nassertv(_collection != (EggCharacterCollection *)NULL);
+  nassertv(_collection->get_num_eggs() > 0);
+
+  if (_reference_filename.empty()) {
+    nout << "No reference filename specified.\n";
+    exit(1);
+  }
+
+  int num_characters = _collection->get_num_characters();
+  if (num_characters != 1) {
+    nout << "All animations must have the same character name.\n";
+    exit(1);
+  }
+
+  // Read in the extra egg file that we use for extracting the
+  // references out.
+  PT(EggData) reference_egg = read_egg(_reference_filename);
+  if (reference_egg == (EggData *)NULL) {
+    nout << "Cannot read " << _reference_filename << "\n";
+    exit(1);
+  }
+
+  // First, we add it to a separate EggCharacterCollection, so we can
+  // figure out its name.
+  EggCharacterCollection col;
+  if (col.add_egg(reference_egg) < 0) {
+    nout << _reference_filename
+         << " does not contain a character model or animation reference.\n";
+    exit(1);
+  }
+
+  if (col.get_num_characters() != 1) {
+    nout << "Reference model must contain only one character.\n";
+    exit(1);
+  }
+
+  string ref_name = col.get_character(0)->get_name();
+
+  // Now rename all of the animations to the same name as the
+  // reference model, and add the reference animation in to the same
+  // collection to match it up joint-for-joint.
+  _collection->rename_char(0, ref_name);
+  int reference_egg_index = _collection->add_egg(reference_egg);
+  nassertv(reference_egg_index > 0);
+  nassertv(_collection->get_num_characters() == 1);
+  
+  int reference_model = _collection->get_first_model_index(reference_egg_index);
+  EggCharacterData *char_data = _collection->get_character(0);
+  nout << "Processing " << char_data->get_name() << "\n";
+
+  EggJointData *root_joint = char_data->get_root_joint();
+  retarget_anim(char_data, root_joint, reference_model);
+  root_joint->do_rebuild();
+
+  write_eggs();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggRetargetAnim::retarget_anim
+//       Access: Public
+//  Description: Recursively replaces the scale and translate
+//               information on all of the joints in the char_data
+//               hierarchy wiht this from reference_char.
+////////////////////////////////////////////////////////////////////
+void EggRetargetAnim::
+retarget_anim(EggCharacterData *char_data, EggJointData *joint_data,
+              int reference_model) {
+  int num_models = joint_data->get_num_models();
+  for (int i = 0; i < num_models; i++) {
+    if (joint_data->has_model(i)) {
+      int num_frames = char_data->get_num_frames(i);
+
+      EggBackPointer *back = joint_data->get_model(i);
+      nassertv(back != (EggBackPointer *)NULL);
+      EggJointPointer *joint;
+      DCAST_INTO_V(joint, back);
+
+      LMatrix4d ref = joint_data->get_frame(reference_model, 0);
+      LVecBase3d ref_scale, ref_shear, ref_hpr, ref_translate;
+      if (!decompose_matrix(ref, ref_scale, ref_shear, ref_hpr, ref_translate)) {
+        nout << "Could not decompose rest frame for " 
+             << joint_data->get_name() << "\n";
+      } else {
+        int f;
+        for (f = 0; f < num_frames; f++) {
+          LMatrix4d mat = joint_data->get_frame(i, f);
+          
+          LVecBase3d scale, shear, hpr, translate;
+          if (decompose_matrix(mat, scale, shear, hpr, translate)) {
+            compose_matrix(mat, ref_scale, ref_shear, hpr, ref_translate);
+          } else {
+            nout << "Could not decompose matrix for " << joint_data->get_name()
+                 << "\n";
+          }
+          
+          if (!joint->add_rebuild_frame(mat)) {
+            nout << "Unable to combine animations.\n";
+            exit(1);
+          }
+        }
+      }
+    }
+  }
+
+
+  int num_children = joint_data->get_num_children();
+  for (int i = 0; i < num_children; i++) {
+    EggJointData *next_joint_data = joint_data->get_child(i);
+    retarget_anim(char_data, next_joint_data, reference_model);
+  }
+}
+
+
+int main(int argc, char *argv[]) {
+  EggRetargetAnim prog;
+  prog.parse_command_line(argc, argv);
+  prog.run();
+  return 0;
+}

+ 52 - 0
pandatool/src/eggprogs/eggRetargetAnim.h

@@ -0,0 +1,52 @@
+// Filename: eggRetargetAnim.h
+// Created by:  drose (05May05)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef EGGRETARGETANIM_H
+#define EGGRETARGETANIM_H
+
+#include "pandatoolbase.h"
+
+#include "eggCharacterFilter.h"
+#include "luse.h"
+
+#include "pvector.h"
+
+class EggCharacterData;
+class EggJointData;
+
+////////////////////////////////////////////////////////////////////
+//       Class : EggRetargetAnim
+// Description : Retargets one or more animation files from one
+//               particular skeleton to a similar, but differently
+//               scaled skeleton by preserving the rotation
+//               information but discarding translation and/or scale.
+////////////////////////////////////////////////////////////////////
+class EggRetargetAnim : public EggCharacterFilter {
+public:
+  EggRetargetAnim();
+
+  void run();
+
+  void retarget_anim(EggCharacterData *char_data, EggJointData *joint_data,
+                     int reference_model);
+
+  Filename _reference_filename;
+};
+
+#endif
+