15 #include "eggRetargetAnim.h" 18 #include "eggJointData.h" 19 #include "eggCharacterCollection.h" 20 #include "eggCharacterData.h" 21 #include "eggCharacterDb.h" 22 #include "eggJointPointer.h" 24 #include "compose_matrix.h" 34 add_path_replace_options();
35 add_path_store_options();
37 set_program_brief(
"remove transformations from animation data in .egg files");
38 set_program_description
39 (
"egg-retarget-anim reads a character model and its associated animation " 40 "files, and removes the translations and scales from the animation " 41 "files, replacing them with the translations and scales from the " 42 "rest position of the character model.\n\n" 44 "This allows an animation that was generated for a model with one " 45 "skeleton to be played successfully on a model with a different " 46 "skeleton, provided that both skeletons have the same hierarchy and " 47 "differ only in scales and/or translations of the various joints, " 48 "and that scales and translations are not part of the per-frame " 53 "Read the reference model from the indicated egg file. All of the " 54 "animations will be retargeted to match the indicated file.",
55 &EggRetargetAnim::dispatch_filename, NULL, &_reference_filename);
58 (
"keep",
"joint[,joint...]", 0,
59 "Preserve the full animation on the named joint(s). This is especially " 60 "appropriate for the root joint.",
61 &EggRetargetAnim::dispatch_vector_string_comma, NULL, &_keep_joints);
69 void EggRetargetAnim::
72 nassertv(_collection->get_num_eggs() > 0);
74 if (_reference_filename.empty()) {
75 nout <<
"No reference filename specified.\n";
79 int num_characters = _collection->get_num_characters();
80 if (num_characters != 1) {
81 nout <<
"All animations must have the same character name.\n";
87 PT(
EggData) reference_egg = read_egg(_reference_filename);
88 if (reference_egg == (
EggData *)NULL) {
89 nout <<
"Cannot read " << _reference_filename <<
"\n";
96 if (col.
add_egg(reference_egg) < 0) {
97 nout << _reference_filename
98 <<
" does not contain a character model or animation reference.\n";
103 nout <<
"Reference model must contain only one character.\n";
112 _collection->rename_char(0, ref_name);
113 int reference_egg_index = _collection->add_egg(reference_egg);
114 nassertv(reference_egg_index > 0);
115 nassertv(_collection->get_num_characters() == 1);
117 int reference_model = _collection->get_first_model_index(reference_egg_index);
119 nout <<
"Processing " << char_data->get_name() <<
"\n";
124 vector_string::const_iterator si;
125 for (si = _keep_joints.begin(); si != _keep_joints.end(); ++si) {
126 keep_names.insert(*si);
131 retarget_anim(char_data, root_joint, reference_model, keep_names, db);
148 if (keep_names.find(joint_data->get_name()) != keep_names.end()) {
154 for (
int i = 0; i < num_models; i++) {
161 DCAST_INTO_V(joint, back);
164 LVecBase3d ref_scale, ref_shear, ref_hpr, ref_translate;
165 if (!decompose_matrix(ref, ref_scale, ref_shear, ref_hpr, ref_translate)) {
166 nout <<
"Could not decompose rest frame for " 167 << joint_data->get_name() <<
"\n";
170 for (f = 0; f < num_frames; f++) {
174 if (decompose_matrix(mat, scale, shear, hpr, translate)) {
175 compose_matrix(mat, ref_scale, ref_shear, hpr, ref_translate);
177 nout <<
"Could not decompose matrix for " << joint_data->get_name()
181 db.
set_matrix(joint, EggCharacterDb::TT_rebuild_frame,
189 int num_children = joint_data->get_num_children();
190 for (
int i = 0; i < num_children; i++) {
191 EggJointData *next_joint_data = joint_data->get_child(i);
192 retarget_anim(char_data, next_joint_data, reference_model, keep_names, db);
197 int main(
int argc,
char *argv[]) {
void retarget_anim(EggCharacterData *char_data, EggJointData *joint_data, int reference_model, const pset< string > &keep_names, EggCharacterDb &db)
Recursively replaces the scale and translate information on all of the joints in the char_data hierar...
This is a 4-by-4 transform matrix.
EggJointData * get_root_joint() const
Returns the root joint of the character hierarchy.
int get_num_frames(int model_index) const
Returns the number of frames of animation of the indicated model.
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_...
int get_num_models() const
Returns the maximum number of back pointers this component may have.
int add_egg(EggData *egg)
Adds a new egg file to the list of models and animation files for this particular character...
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...
This is the primary interface into all the egg data, and the root of the egg file structure...
int get_num_characters() const
Returns the number of separate Characters that have been discovered in the various egg files added to...
This class is used during joint optimization or restructuring to store the table of interim joint com...
Retargets one or more animation files from one particular skeleton to a similar, but differently scal...
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.
This is a base class for EggJointNodePointer and EggMatrixTablePointer.
EggCharacterData * get_character(int i) const
Returns the ith character in the collection.
Represents a set of characters, as read and collected from possibly several model and/or animation eg...
This is the base class for all three-component vectors and points.
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...
Represents a single character, as read and collected from several models and animation files...
This is one node of a hierarchy of EggJointData nodes, each of which represents a single joint of the...
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...
bool do_rebuild_all(EggCharacterDb &db)
Calls do_rebuild() on all models, and recursively on all joints at this node and below.
This stores a pointer from an EggJointData or EggSliderData object back to the referencing data in an...