00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "animBundleMaker.h"
00016 #include "config_egg2pg.h"
00017
00018 #include "eggTable.h"
00019 #include "eggAnimData.h"
00020 #include "eggSAnimData.h"
00021 #include "eggXfmAnimData.h"
00022 #include "eggXfmSAnim.h"
00023 #include "eggGroupNode.h"
00024 #include "animBundle.h"
00025 #include "animBundleNode.h"
00026 #include "animChannelMatrixXfmTable.h"
00027 #include "animChannelScalarTable.h"
00028
00029
00030
00031
00032
00033
00034 AnimBundleMaker::
00035 AnimBundleMaker(EggTable *root) : _root(root) {
00036 _fps = 0.0f;
00037 _num_frames = 1;
00038
00039 _ok_fps = true;
00040 _ok_num_frames = true;
00041
00042 inspect_tree(root);
00043
00044 if (!_ok_fps) {
00045 egg2pg_cat.warning()
00046 << "AnimBundle " << _root->get_name()
00047 << " specifies contradictory frame rates.\n";
00048 } else if (_fps == 0.0f) {
00049 egg2pg_cat.warning()
00050 << "AnimBundle " << _root->get_name()
00051 << " does not specify a frame rate.\n";
00052 _fps = 24.0f;
00053 }
00054
00055 if (!_ok_num_frames) {
00056 egg2pg_cat.warning()
00057 << "AnimBundle " << _root->get_name()
00058 << " specifies contradictory number of frames.\n";
00059 }
00060 }
00061
00062
00063
00064
00065
00066
00067
00068 AnimBundleNode *AnimBundleMaker::
00069 make_node() {
00070 return new AnimBundleNode(_root->get_name(), make_bundle());
00071 }
00072
00073
00074
00075
00076
00077
00078 AnimBundle *AnimBundleMaker::
00079 make_bundle() {
00080 AnimBundle *bundle = new AnimBundle(_root->get_name(), _fps, _num_frames);
00081
00082 EggTable::const_iterator ci;
00083 for (ci = _root->begin(); ci != _root->end(); ++ci) {
00084 if ((*ci)->is_of_type(EggTable::get_class_type())) {
00085 EggTable *child = DCAST(EggTable, *ci);
00086 build_hierarchy(child, bundle);
00087 }
00088 }
00089
00090 bundle->sort_descendants();
00091
00092 return bundle;
00093 }
00094
00095
00096
00097
00098
00099
00100
00101
00102 void AnimBundleMaker::
00103 inspect_tree(EggNode *egg_node) {
00104 if (egg_node->is_of_type(EggAnimData::get_class_type())) {
00105
00106 EggAnimData *egg_anim = DCAST(EggAnimData, egg_node);
00107 if (egg_anim->has_fps()) {
00108 if (_fps == 0.0f) {
00109 _fps = egg_anim->get_fps();
00110 } else if (_fps != egg_anim->get_fps()) {
00111
00112 _fps = min(_fps, (PN_stdfloat)egg_anim->get_fps());
00113 _ok_fps = false;
00114 }
00115 }
00116 }
00117
00118 if (egg_node->is_of_type(EggXfmSAnim::get_class_type())) {
00119
00120 EggXfmSAnim *egg_anim = DCAST(EggXfmSAnim, egg_node);
00121 if (egg_anim->has_fps()) {
00122 if (_fps == 0.0f) {
00123 _fps = egg_anim->get_fps();
00124 } else if (_fps != egg_anim->get_fps()) {
00125
00126 _fps = min(_fps, (PN_stdfloat)egg_anim->get_fps());
00127 _ok_fps = false;
00128 }
00129 }
00130 }
00131
00132 if (egg_node->is_of_type(EggSAnimData::get_class_type())) {
00133
00134 EggSAnimData *egg_anim = DCAST(EggSAnimData, egg_node);
00135 int num_frames = egg_anim->get_num_rows();
00136
00137 if (num_frames > 1) {
00138 if (_num_frames == 1) {
00139 _num_frames = num_frames;
00140 } else if (_num_frames != num_frames) {
00141
00142 _num_frames = min(_num_frames, num_frames);
00143 _ok_num_frames = false;
00144 }
00145 }
00146 }
00147
00148 if (egg_node->is_of_type(EggXfmAnimData::get_class_type())) {
00149
00150 EggXfmAnimData *egg_anim = DCAST(EggXfmAnimData, egg_node);
00151 int num_frames = egg_anim->get_num_rows();
00152
00153 if (num_frames > 1) {
00154 if (_num_frames == 1) {
00155 _num_frames = num_frames;
00156 } else if (_num_frames != num_frames) {
00157
00158 _num_frames = min(_num_frames, num_frames);
00159 _ok_num_frames = false;
00160 }
00161 }
00162 }
00163
00164 if (egg_node->is_of_type(EggGroupNode::get_class_type())) {
00165
00166 EggGroupNode *group = DCAST(EggGroupNode, egg_node);
00167 EggGroupNode::const_iterator ci;
00168 for (ci = group->begin(); ci != group->end(); ++ci) {
00169 inspect_tree(*ci);
00170 }
00171 }
00172 }
00173
00174
00175
00176
00177
00178
00179
00180
00181 void AnimBundleMaker::
00182 build_hierarchy(EggTable *egg_table, AnimGroup *parent) {
00183 AnimGroup *this_node = NULL;
00184
00185
00186
00187
00188
00189 EggTable::const_iterator ci;
00190 for (ci = egg_table->begin(); ci != egg_table->end(); ++ci) {
00191 if ((*ci)->get_name() == "xform") {
00192 if (this_node == NULL) {
00193 this_node = create_xfm_channel((*ci), egg_table->get_name(), parent);
00194 } else {
00195 egg2pg_cat.warning()
00196 << "Duplicate xform table under node "
00197 << egg_table->get_name() << "\n";
00198 }
00199 }
00200 }
00201
00202
00203
00204 if (this_node == NULL) {
00205 this_node = new AnimGroup(parent, egg_table->get_name());
00206 }
00207
00208
00209
00210 for (ci = egg_table->begin(); ci != egg_table->end(); ++ci) {
00211 if ((*ci)->get_name() == "xform") {
00212
00213 } else if ((*ci)->is_of_type(EggSAnimData::get_class_type())) {
00214 EggSAnimData *egg_anim = DCAST(EggSAnimData, *ci);
00215 create_s_channel(egg_anim, egg_anim->get_name(), this_node);
00216
00217 } else if ((*ci)->is_of_type(EggTable::get_class_type())) {
00218 EggTable *child = DCAST(EggTable, *ci);
00219 build_hierarchy(child, this_node);
00220 }
00221 }
00222 }
00223
00224
00225
00226
00227
00228
00229
00230
00231 AnimChannelScalarTable *AnimBundleMaker::
00232 create_s_channel(EggSAnimData *egg_anim, const string &name,
00233 AnimGroup *parent) {
00234 AnimChannelScalarTable *table
00235 = new AnimChannelScalarTable(parent, name);
00236
00237
00238
00239 PTA_stdfloat new_data = PTA_stdfloat::empty_array(egg_anim->get_num_rows(),
00240 table->get_class_type());
00241 for (int i = 0; i < egg_anim->get_num_rows(); i++) {
00242 new_data[i] = (PN_stdfloat)egg_anim->get_value(i);
00243 }
00244
00245
00246 table->set_table(new_data);
00247
00248 return table;
00249 }
00250
00251
00252
00253
00254
00255
00256
00257
00258 AnimChannelMatrixXfmTable *AnimBundleMaker::
00259 create_xfm_channel(EggNode *egg_node, const string &name,
00260 AnimGroup *parent) {
00261 if (egg_node->is_of_type(EggXfmAnimData::get_class_type())) {
00262 EggXfmAnimData *egg_anim = DCAST(EggXfmAnimData, egg_node);
00263 EggXfmSAnim new_anim(*egg_anim);
00264 return create_xfm_channel(&new_anim, name, parent);
00265
00266 } else if (egg_node->is_of_type(EggXfmSAnim::get_class_type())) {
00267 EggXfmSAnim *egg_anim = DCAST(EggXfmSAnim, egg_node);
00268 return create_xfm_channel(egg_anim, name, parent);
00269 }
00270
00271 egg2pg_cat.warning()
00272 << "Inappropriate node named xform under node "
00273 << name << "\n";
00274 return NULL;
00275 }
00276
00277
00278
00279
00280
00281
00282
00283
00284 AnimChannelMatrixXfmTable *AnimBundleMaker::
00285 create_xfm_channel(EggXfmSAnim *egg_anim, const string &name,
00286 AnimGroup *parent) {
00287
00288
00289 egg_anim->optimize_to_standard_order();
00290
00291 AnimChannelMatrixXfmTable *table
00292 = new AnimChannelMatrixXfmTable(parent, name);
00293
00294
00295
00296
00297
00298 EggXfmSAnim::const_iterator ci;
00299 for (ci = egg_anim->begin(); ci != egg_anim->end(); ++ci) {
00300 if ((*ci)->is_of_type(EggSAnimData::get_class_type())) {
00301 EggSAnimData *child = DCAST(EggSAnimData, *ci);
00302
00303 if (child->get_name().empty()) {
00304 egg2pg_cat.warning()
00305 << "Unnamed subtable of <Xfm$Anim_S$> " << name
00306 << "\n";
00307 } else {
00308 char table_id = child->get_name()[0];
00309
00310 if (child->get_name().length() > 1 ||
00311 !table->is_valid_id(table_id)) {
00312 egg2pg_cat.warning()
00313 << "Unexpected table name " << child->get_name()
00314 << ", child of " << name << "\n";
00315
00316 } else if (table->has_table(table_id)) {
00317 egg2pg_cat.warning()
00318 << "Duplicate table definition for " << table_id
00319 << " under " << name << "\n";
00320
00321 } else {
00322
00323
00324
00325 PTA_stdfloat new_data=PTA_stdfloat::empty_array(child->get_num_rows(),
00326 table->get_class_type());
00327 for (int i = 0; i < child->get_num_rows(); i++) {
00328 new_data[i] = (PN_stdfloat)child->get_value(i);
00329 }
00330
00331
00332 table->set_table(table_id, new_data);
00333 }
00334 }
00335 }
00336 }
00337
00338 return table;
00339 }