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