30 add_path_replace_options();
31 add_path_store_options();
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"
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 "
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);
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);
63 void EggRetargetAnim::
65 nassertv(_collection !=
nullptr);
66 nassertv(_collection->get_num_eggs() > 0);
68 if (_reference_filename.empty()) {
69 nout <<
"No reference filename specified.\n";
73 int num_characters = _collection->get_num_characters();
74 if (num_characters != 1) {
75 nout <<
"All animations must have the same character name.\n";
80 PT(
EggData) reference_egg = read_egg(_reference_filename);
81 if (reference_egg ==
nullptr) {
82 nout <<
"Cannot read " << _reference_filename <<
"\n";
89 if (col.
add_egg(reference_egg) < 0) {
90 nout << _reference_filename
91 <<
" does not contain a character model or animation reference.\n";
96 nout <<
"Reference model must contain only one character.\n";
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);
110 int reference_model = _collection->get_first_model_index(reference_egg_index);
112 nout <<
"Processing " << char_data->get_name() <<
"\n";
117 vector_string::const_iterator si;
118 for (si = _keep_joints.begin(); si != _keep_joints.end(); ++si) {
119 keep_names.insert(*si);
124 retarget_anim(char_data, root_joint, reference_model, keep_names, db);
138 if (keep_names.find(joint_data->get_name()) != keep_names.end()) {
144 for (
int i = 0; i < num_models; i++) {
149 nassertv(back !=
nullptr);
151 DCAST_INTO_V(joint, back);
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";
160 for (f = 0; f < num_frames; f++) {
161 LMatrix4d mat = joint_data->
get_frame(i, f);
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);
167 nout <<
"Could not decompose matrix for " << joint_data->get_name()
171 db.
set_matrix(joint, EggCharacterDb::TT_rebuild_frame,
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);
187 int main(
int argc,
char *argv[]) {