Panda3D
eggRetargetAnim.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file eggRetargetAnim.cxx
10  * @author drose
11  * @date 2005-05-05
12  */
13 
14 #include "eggRetargetAnim.h"
15 
16 #include "dcast.h"
17 #include "eggJointData.h"
18 #include "eggCharacterCollection.h"
19 #include "eggCharacterData.h"
20 #include "eggCharacterDb.h"
21 #include "eggJointPointer.h"
22 #include "eggTable.h"
23 #include "compose_matrix.h"
24 
25 /**
26  *
27  */
28 EggRetargetAnim::
29 EggRetargetAnim() {
30  add_path_replace_options();
31  add_path_store_options();
32 
33  set_program_brief("remove transformations from animation data in .egg files");
34  set_program_description
35  ("egg-retarget-anim reads a character model and its associated animation "
36  "files, and removes the translations and scales from the animation "
37  "files, replacing them with the translations and scales from the "
38  "rest position of the character model.\n\n"
39 
40  "This allows an animation that was generated for a model with one "
41  "skeleton to be played successfully on a model with a different "
42  "skeleton, provided that both skeletons have the same hierarchy and "
43  "differ only in scales and/or translations of the various joints, "
44  "and that scales and translations are not part of the per-frame "
45  "animations.");
46 
47  add_option
48  ("r", "file.egg", 0,
49  "Read the reference model from the indicated egg file. All of the "
50  "animations will be retargeted to match the indicated file.",
51  &EggRetargetAnim::dispatch_filename, nullptr, &_reference_filename);
52 
53  add_option
54  ("keep", "joint[,joint...]", 0,
55  "Preserve the full animation on the named joint(s). This is especially "
56  "appropriate for the root joint.",
57  &EggRetargetAnim::dispatch_vector_string_comma, nullptr, &_keep_joints);
58 }
59 
60 /**
61  *
62  */
63 void EggRetargetAnim::
64 run() {
65  nassertv(_collection != nullptr);
66  nassertv(_collection->get_num_eggs() > 0);
67 
68  if (_reference_filename.empty()) {
69  nout << "No reference filename specified.\n";
70  exit(1);
71  }
72 
73  int num_characters = _collection->get_num_characters();
74  if (num_characters != 1) {
75  nout << "All animations must have the same character name.\n";
76  exit(1);
77  }
78 
79  // Read in the extra egg file that we use for extracting the references out.
80  PT(EggData) reference_egg = read_egg(_reference_filename);
81  if (reference_egg == nullptr) {
82  nout << "Cannot read " << _reference_filename << "\n";
83  exit(1);
84  }
85 
86  // First, we add it to a separate EggCharacterCollection, so we can figure
87  // out its name.
89  if (col.add_egg(reference_egg) < 0) {
90  nout << _reference_filename
91  << " does not contain a character model or animation reference.\n";
92  exit(1);
93  }
94 
95  if (col.get_num_characters() != 1) {
96  nout << "Reference model must contain only one character.\n";
97  exit(1);
98  }
99 
100  std::string ref_name = col.get_character(0)->get_name();
101 
102  // Now rename all of the animations to the same name as the reference model,
103  // and add the reference animation in to the same collection to match it up
104  // joint-for-joint.
105  _collection->rename_char(0, ref_name);
106  int reference_egg_index = _collection->add_egg(reference_egg);
107  nassertv(reference_egg_index > 0);
108  nassertv(_collection->get_num_characters() == 1);
109 
110  int reference_model = _collection->get_first_model_index(reference_egg_index);
111  EggCharacterData *char_data = _collection->get_character(0);
112  nout << "Processing " << char_data->get_name() << "\n";
113 
114  typedef pset<std::string> Names;
115  Names keep_names;
116 
117  vector_string::const_iterator si;
118  for (si = _keep_joints.begin(); si != _keep_joints.end(); ++si) {
119  keep_names.insert(*si);
120  }
121 
122  EggCharacterDb db;
123  EggJointData *root_joint = char_data->get_root_joint();
124  retarget_anim(char_data, root_joint, reference_model, keep_names, db);
125  root_joint->do_rebuild_all(db);
126 
127  write_eggs();
128 }
129 
130 /**
131  * Recursively replaces the scale and translate information on all of the
132  * joints in the char_data hierarchy wiht this from reference_char.
133  */
136  int reference_model, const pset<std::string> &keep_names,
137  EggCharacterDb &db) {
138  if (keep_names.find(joint_data->get_name()) != keep_names.end()) {
139  // Don't retarget this joint; keep the translation and scale and whatever.
140 
141  } else {
142  // Retarget this joint.
143  int num_models = joint_data->get_num_models();
144  for (int i = 0; i < num_models; i++) {
145  if (joint_data->has_model(i)) {
146  int num_frames = char_data->get_num_frames(i);
147 
148  EggBackPointer *back = joint_data->get_model(i);
149  nassertv(back != nullptr);
150  EggJointPointer *joint;
151  DCAST_INTO_V(joint, back);
152 
153  LMatrix4d ref = joint_data->get_frame(reference_model, 0);
154  LVecBase3d ref_scale, ref_shear, ref_hpr, ref_translate;
155  if (!decompose_matrix(ref, ref_scale, ref_shear, ref_hpr, ref_translate)) {
156  nout << "Could not decompose rest frame for "
157  << joint_data->get_name() << "\n";
158  } else {
159  int f;
160  for (f = 0; f < num_frames; f++) {
161  LMatrix4d mat = joint_data->get_frame(i, f);
162 
163  LVecBase3d scale, shear, hpr, translate;
164  if (decompose_matrix(mat, scale, shear, hpr, translate)) {
165  compose_matrix(mat, ref_scale, ref_shear, hpr, ref_translate);
166  } else {
167  nout << "Could not decompose matrix for " << joint_data->get_name()
168  << "\n";
169  }
170 
171  db.set_matrix(joint, EggCharacterDb::TT_rebuild_frame,
172  f, mat);
173  }
174  }
175  }
176  }
177  }
178 
179  int num_children = joint_data->get_num_children();
180  for (int i = 0; i < num_children; i++) {
181  EggJointData *next_joint_data = joint_data->get_child(i);
182  retarget_anim(char_data, next_joint_data, reference_model, keep_names, db);
183  }
184 }
185 
186 
187 int main(int argc, char *argv[]) {
188  EggRetargetAnim prog;
189  prog.parse_command_line(argc, argv);
190  prog.run();
191  return 0;
192 }
EggCharacterCollection::get_num_characters
int get_num_characters() const
Returns the number of separate Characters that have been discovered in the various egg files added to...
Definition: eggCharacterCollection.I:65
eggTable.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggJointData::do_rebuild_all
bool do_rebuild_all(EggCharacterDb &db)
Calls do_rebuild() on all models, and recursively on all joints at this node and below.
Definition: eggJointData.cxx:279
eggCharacterCollection.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggCharacterCollection::get_character
EggCharacterData * get_character(int i) const
Returns the ith character in the collection.
Definition: eggCharacterCollection.I:73
eggCharacterDb.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggRetargetAnim::retarget_anim
void retarget_anim(EggCharacterData *char_data, EggJointData *joint_data, int reference_model, const pset< std::string > &keep_names, EggCharacterDb &db)
Recursively replaces the scale and translate information on all of the joints in the char_data hierar...
Definition: eggRetargetAnim.cxx:135
EggComponentData::has_model
bool has_model(int model_index) const
Returns true if the component has a back pointer to an egg file somewhere for the indicated model,...
Definition: eggComponentData.I:30
dcast.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eggRetargetAnim.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggCharacterData
Represents a single character, as read and collected from several models and animation files.
Definition: eggCharacterData.h:52
EggBackPointer
This stores a pointer from an EggJointData or EggSliderData object back to the referencing data in an...
Definition: eggBackPointer.h:31
compose_matrix.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eggJointData.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ProgramBase::parse_command_line
virtual void parse_command_line(int argc, char **argv)
Dispatches on each of the options on the command line, and passes the remaining parameters to handle_...
Definition: programBase.cxx:274
EggJointPointer
This is a base class for EggJointNodePointer and EggMatrixTablePointer.
Definition: eggJointPointer.h:31
EggData
This is the primary interface into all the egg data, and the root of the egg file structure.
Definition: eggData.h:37
EggJointData
This is one node of a hierarchy of EggJointData nodes, each of which represents a single joint of the...
Definition: eggJointData.h:31
EggJointData::get_frame
LMatrix4d get_frame(int model_index, int n) const
Returns the local transform matrix corresponding to this joint position in the nth frame in the indic...
Definition: eggJointData.cxx:51
EggCharacterData::get_num_frames
int get_num_frames(int model_index) const
Returns the number of frames of animation of the indicated model.
Definition: eggCharacterData.cxx:100
eggCharacterData.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggCharacterDb::set_matrix
void set_matrix(const EggJointPointer *joint, TableType type, int frame, const LMatrix4d &mat)
Stores the matrix for the indicated joint, type, and frame in the database.
Definition: eggCharacterDb.cxx:106
EggRetargetAnim
Retargets one or more animation files from one particular skeleton to a similar, but differently scal...
Definition: eggRetargetAnim.h:33
EggComponentData::get_num_models
int get_num_models() const
Returns the maximum number of back pointers this component may have.
Definition: eggComponentData.I:21
EggCharacterData::get_root_joint
EggJointData * get_root_joint() const
Returns the root joint of the character hierarchy.
Definition: eggCharacterData.I:71
EggCharacterCollection::add_egg
int add_egg(EggData *egg)
Adds a new egg file to the list of models and animation files for this particular character.
Definition: eggCharacterCollection.cxx:67
EggCharacterCollection
Represents a set of characters, as read and collected from possibly several model and/or animation eg...
Definition: eggCharacterCollection.h:32
eggJointPointer.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggComponentData::get_model
EggBackPointer * get_model(int model_index) const
Returns the back pointer to an egg file for the indicated model if it exists, or NULL if it does not.
Definition: eggComponentData.I:42
EggCharacterDb
This class is used during joint optimization or restructuring to store the table of interim joint com...
Definition: eggCharacterDb.h:41
pset< std::string >