00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "eggCharacterCollection.h"
00016 #include "eggCharacterData.h"
00017 #include "eggJointData.h"
00018 #include "eggSliderData.h"
00019
00020 #include "dcast.h"
00021 #include "eggGroup.h"
00022 #include "eggTable.h"
00023 #include "eggPrimitive.h"
00024 #include "eggVertex.h"
00025 #include "eggVertexUV.h"
00026 #include "eggMorphList.h"
00027 #include "eggSAnimData.h"
00028 #include "indirectCompareNames.h"
00029 #include "indent.h"
00030
00031 #include <algorithm>
00032
00033
00034
00035
00036
00037
00038
00039 EggCharacterCollection::
00040 EggCharacterCollection() {
00041 _next_model_index = 0;
00042 }
00043
00044
00045
00046
00047
00048
00049 EggCharacterCollection::
00050 ~EggCharacterCollection() {
00051 Characters::iterator ci;
00052
00053 for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
00054 delete (*ci);
00055 }
00056 }
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 int EggCharacterCollection::
00073 add_egg(EggData *egg) {
00074 _top_egg_nodes.clear();
00075
00076 if (!scan_hierarchy(egg)) {
00077 return -1;
00078 }
00079
00080 int egg_index = _eggs.size();
00081 _eggs.push_back(EggInfo());
00082 EggInfo &egg_info = _eggs.back();
00083 egg_info._egg = egg;
00084 egg_info._first_model_index = 0;
00085
00086
00087
00088 TopEggNodesByName::iterator tni;
00089 for (tni = _top_egg_nodes.begin(); tni != _top_egg_nodes.end(); ++tni) {
00090 string character_name = (*tni).first;
00091 TopEggNodes &top_nodes = (*tni).second;
00092 EggCharacterData *char_data = make_character(character_name);
00093 EggJointData *root_joint = char_data->get_root_joint();
00094
00095 TopEggNodes::iterator ti;
00096 for (ti = top_nodes.begin(); ti != top_nodes.end(); ++ti) {
00097 EggNode *model_root = (*ti).first;
00098 ModelDescription &desc = (*ti).second;
00099
00100 int model_index = _next_model_index++;
00101 if (egg_info._models.empty()) {
00102 egg_info._first_model_index = model_index;
00103 }
00104 egg_info._models.push_back(model_root);
00105
00106 char_data->add_model(model_index, model_root, egg);
00107 nassertr(model_index == (int)_characters_by_model_index.size(), -1);
00108 _characters_by_model_index.push_back(char_data);
00109 root_joint->add_back_pointer(model_index, desc._root_node);
00110
00111 match_egg_nodes(char_data, root_joint, desc._top_nodes,
00112 egg_index, model_index);
00113
00114 scan_for_morphs(model_root, model_index, char_data);
00115 scan_for_sliders(model_root, model_index, char_data);
00116 }
00117 }
00118
00119 return egg_index;
00120 }
00121
00122
00123
00124
00125
00126
00127
00128 EggCharacterData *EggCharacterCollection::
00129 get_character_by_name(const string &character_name) const {
00130 Characters::const_iterator ci;
00131 for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
00132 EggCharacterData *char_data = (*ci);
00133 if (char_data->get_name() == character_name) {
00134 return char_data;
00135 }
00136 }
00137
00138 return (EggCharacterData *)NULL;
00139 }
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151 EggCharacterData *EggCharacterCollection::
00152 make_character_data() {
00153 return new EggCharacterData(this);
00154 }
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 EggJointData *EggCharacterCollection::
00166 make_joint_data(EggCharacterData *char_data) {
00167 return new EggJointData(this, char_data);
00168 }
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179 EggSliderData *EggCharacterCollection::
00180 make_slider_data(EggCharacterData *char_data) {
00181 return new EggSliderData(this, char_data);
00182 }
00183
00184
00185
00186
00187
00188
00189
00190
00191 EggCharacterData *EggCharacterCollection::
00192 make_character(const string &character_name) {
00193
00194
00195 Characters::iterator ci;
00196 for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
00197 EggCharacterData *char_data = (*ci);
00198 if (char_data->get_name() == character_name) {
00199 return char_data;
00200 }
00201 }
00202
00203
00204 EggCharacterData *char_data = make_character_data();
00205 char_data->set_name(character_name);
00206 _characters.push_back(char_data);
00207 return char_data;
00208 }
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 bool EggCharacterCollection::
00223 scan_hierarchy(EggNode *egg_node) {
00224 if (egg_node->is_of_type(EggGroup::get_class_type())) {
00225 EggGroup *group = DCAST(EggGroup, egg_node);
00226 if (group->get_dart_type() != EggGroup::DT_none) {
00227
00228 scan_for_top_joints(group, group, group->get_name());
00229 return true;
00230 }
00231
00232 } else if (egg_node->is_of_type(EggTable::get_class_type())) {
00233 EggTable *table = DCAST(EggTable, egg_node);
00234 if (table->get_table_type() == EggTable::TT_bundle) {
00235
00236 scan_for_top_tables(table, table, table->get_name());
00237 return true;
00238 }
00239 }
00240
00241 bool character_found = false;
00242 if (egg_node->is_of_type(EggGroupNode::get_class_type())) {
00243 EggGroupNode *group = DCAST(EggGroupNode, egg_node);
00244 EggGroupNode::iterator gi;
00245 for (gi = group->begin(); gi != group->end(); ++gi) {
00246 if (scan_hierarchy(*gi)) {
00247 character_found = true;
00248 }
00249 }
00250 }
00251
00252 return character_found;
00253 }
00254
00255
00256
00257
00258
00259
00260
00261
00262 void EggCharacterCollection::
00263 scan_for_top_joints(EggNode *egg_node, EggNode *model_root,
00264 const string &character_name) {
00265 if (egg_node->is_of_type(EggGroup::get_class_type())) {
00266 EggGroup *group = DCAST(EggGroup, egg_node);
00267
00268 if (group->has_lod()) {
00269
00270
00271
00272 model_root = group;
00273 }
00274 if (group->get_group_type() == EggGroup::GT_joint) {
00275
00276 ModelDescription &desc = _top_egg_nodes[character_name][model_root];
00277 desc._root_node = model_root;
00278 desc._top_nodes.push_back(group);
00279 return;
00280 }
00281 }
00282
00283 if (egg_node->is_of_type(EggGroupNode::get_class_type())) {
00284 EggGroupNode *group = DCAST(EggGroupNode, egg_node);
00285 EggGroupNode::iterator gi;
00286 for (gi = group->begin(); gi != group->end(); ++gi) {
00287 scan_for_top_joints(*gi, model_root, character_name);
00288 }
00289 }
00290 }
00291
00292
00293
00294
00295
00296
00297
00298
00299 void EggCharacterCollection::
00300 scan_for_top_tables(EggTable *bundle, EggNode *model_root,
00301 const string &character_name) {
00302
00303
00304 EggGroupNode::iterator gi;
00305 for (gi = bundle->begin(); gi != bundle->end(); ++gi) {
00306 EggNode *child = (*gi);
00307 if (child->is_of_type(EggTable::get_class_type())) {
00308 EggTable *table = DCAST(EggTable, child);
00309 if (table->get_name() == "<skeleton>") {
00310
00311
00312 ModelDescription &desc = _top_egg_nodes[character_name][model_root];
00313 desc._root_node = table;
00314
00315 EggGroupNode::iterator cgi;
00316 for (cgi = table->begin(); cgi != table->end(); ++cgi) {
00317 EggNode *grandchild = (*cgi);
00318 if (grandchild->is_of_type(EggTable::get_class_type())) {
00319 desc._top_nodes.push_back(grandchild);
00320 }
00321 }
00322 }
00323 }
00324 }
00325 }
00326
00327
00328
00329
00330
00331
00332
00333 void EggCharacterCollection::
00334 scan_for_morphs(EggNode *egg_node, int model_index,
00335 EggCharacterData *char_data) {
00336 if (egg_node->is_of_type(EggPrimitive::get_class_type())) {
00337 EggPrimitive *prim = DCAST(EggPrimitive, egg_node);
00338
00339 add_morph_back_pointers(prim, prim, model_index, char_data);
00340
00341
00342 EggPrimitive::const_iterator vi;
00343 for (vi = prim->begin(); vi != prim->end(); ++vi) {
00344 EggVertex *vertex = (*vi);
00345
00346 add_morph_back_pointers(vertex, vertex, model_index, char_data);
00347 add_morph_back_pointers_vertex(vertex, vertex, model_index, char_data);
00348
00349 EggMorphVertexList::const_iterator mvi;
00350 for (mvi = vertex->_dxyzs.begin();
00351 mvi != vertex->_dxyzs.end();
00352 ++mvi) {
00353 const EggMorphVertex &morph = (*mvi);
00354 char_data->make_slider(morph.get_name())->add_back_pointer(model_index, vertex);
00355 }
00356 }
00357 }
00358
00359 if (egg_node->is_of_type(EggGroupNode::get_class_type())) {
00360 EggGroupNode *group = DCAST(EggGroupNode, egg_node);
00361 EggGroupNode::iterator gi;
00362 for (gi = group->begin(); gi != group->end(); ++gi) {
00363 scan_for_morphs(*gi, model_index, char_data);
00364 }
00365 }
00366 }
00367
00368
00369
00370
00371
00372
00373
00374 void EggCharacterCollection::
00375 scan_for_sliders(EggNode *egg_node, int model_index,
00376 EggCharacterData *char_data) {
00377 if (egg_node->is_of_type(EggTable::get_class_type())) {
00378 EggTable *bundle = DCAST(EggTable, egg_node);
00379
00380
00381
00382
00383
00384
00385
00386 EggGroupNode::iterator gi;
00387 for (gi = bundle->begin(); gi != bundle->end(); ++gi) {
00388 EggNode *child = (*gi);
00389 if (child->is_of_type(EggTable::get_class_type())) {
00390 EggTable *table = DCAST(EggTable, child);
00391 if (table->get_name() == "morph") {
00392
00393
00394
00395 EggGroupNode::iterator cgi;
00396 for (cgi = table->begin(); cgi != table->end(); ++cgi) {
00397 EggNode *grandchild = (*cgi);
00398 if (grandchild->is_of_type(EggSAnimData::get_class_type())) {
00399 char_data->make_slider(grandchild->get_name())->add_back_pointer(model_index, grandchild);
00400 }
00401 }
00402 }
00403 }
00404 }
00405 }
00406 }
00407
00408
00409
00410
00411
00412
00413
00414 void EggCharacterCollection::
00415 add_morph_back_pointers(EggAttributes *attrib, EggObject *egg_object,
00416 int model_index, EggCharacterData *char_data) {
00417 EggMorphNormalList::const_iterator mni;
00418 for (mni = attrib->_dnormals.begin();
00419 mni != attrib->_dnormals.end();
00420 ++mni) {
00421 const EggMorphNormal &morph = (*mni);
00422 char_data->make_slider(morph.get_name())->add_back_pointer(model_index, egg_object);
00423 }
00424
00425 EggMorphColorList::const_iterator mci;
00426 for (mci = attrib->_drgbas.begin();
00427 mci != attrib->_drgbas.end();
00428 ++mci) {
00429 const EggMorphColor &morph = (*mci);
00430 char_data->make_slider(morph.get_name())->add_back_pointer(model_index, egg_object);
00431 }
00432 }
00433
00434
00435
00436
00437
00438
00439
00440 void EggCharacterCollection::
00441 add_morph_back_pointers_vertex(EggVertex *vertex, EggObject *egg_object,
00442 int model_index, EggCharacterData *char_data) {
00443 EggVertex::const_uv_iterator ui;
00444 for (ui = vertex->uv_begin(); ui != vertex->uv_end(); ++ui) {
00445 EggVertexUV *vert_uv = (*ui);
00446 EggMorphTexCoordList::const_iterator mti;
00447 for (mti = vert_uv->_duvs.begin();
00448 mti != vert_uv->_duvs.end();
00449 ++mti) {
00450 const EggMorphTexCoord &morph = (*mti);
00451 char_data->make_slider(morph.get_name())->add_back_pointer(model_index, egg_object);
00452 }
00453 }
00454 }
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466 void EggCharacterCollection::
00467 match_egg_nodes(EggCharacterData *char_data, EggJointData *joint_data,
00468 EggNodeList &egg_nodes, int egg_index, int model_index) {
00469
00470
00471 sort(egg_nodes.begin(), egg_nodes.end(), IndirectCompareNames<Namable>());
00472
00473 if (joint_data->_children.empty()) {
00474
00475
00476 EggNodeList::iterator ei;
00477 for (ei = egg_nodes.begin(); ei != egg_nodes.end(); ++ei) {
00478 EggNode *egg_node = (*ei);
00479 EggJointData *data = make_joint_data(char_data);
00480 joint_data->_children.push_back(data);
00481 char_data->_joints.push_back(data);
00482 char_data->_components.push_back(data);
00483 data->_parent = joint_data;
00484 data->_new_parent = joint_data;
00485 found_egg_match(char_data, data, egg_node, egg_index, model_index);
00486 }
00487
00488 } else {
00489
00490
00491
00492 EggNodeList extra_egg_nodes;
00493 EggJointData::Children extra_data;
00494
00495 EggNodeList::iterator ei;
00496 EggJointData::Children::iterator di;
00497
00498 ei = egg_nodes.begin();
00499 di = joint_data->_children.begin();
00500
00501 while (ei != egg_nodes.end() && di != joint_data->_children.end()) {
00502 EggNode *egg_node = (*ei);
00503 EggJointData *data = (*di);
00504
00505 if (egg_node->get_name() < data->get_name()) {
00506
00507 extra_egg_nodes.push_back(egg_node);
00508 ++ei;
00509
00510 } else if (data->get_name() < egg_node->get_name()) {
00511
00512 extra_data.push_back(data);
00513 ++di;
00514
00515 } else {
00516
00517 found_egg_match(char_data, data, egg_node, egg_index, model_index);
00518 ++ei;
00519 ++di;
00520 }
00521 }
00522
00523 while (ei != egg_nodes.end()) {
00524 EggNode *egg_node = (*ei);
00525
00526
00527 extra_egg_nodes.push_back(egg_node);
00528 ++ei;
00529 }
00530
00531 while (di != joint_data->_children.end()) {
00532 EggJointData *data = (*di);
00533
00534
00535 extra_data.push_back(data);
00536 ++di;
00537 }
00538
00539 if (!extra_egg_nodes.empty()) {
00540
00541
00542
00543
00544
00545 EggNodeList more_egg_nodes;
00546
00547 for (ei = extra_egg_nodes.begin(); ei != extra_egg_nodes.end(); ++ei) {
00548 EggNode *egg_node = (*ei);
00549 bool matched = false;
00550 for (di = extra_data.begin(); di != extra_data.end(); ++di) {
00551 EggJointData *data = (*di);
00552 if (data->matches_name(egg_node->get_name())) {
00553 found_egg_match(char_data, data, egg_node, egg_index, model_index);
00554 extra_data.erase(di);
00555 matched = true;
00556 break;
00557 }
00558 }
00559
00560 if (!matched) {
00561
00562 more_egg_nodes.push_back(egg_node);
00563 }
00564 }
00565 extra_egg_nodes.swap(more_egg_nodes);
00566 }
00567
00568 if (!extra_egg_nodes.empty()) {
00569
00570
00571 if (extra_egg_nodes.size() == extra_data.size()) {
00572
00573 size_t i;
00574 for (i = 0; i < extra_egg_nodes.size(); i++) {
00575 EggNode *egg_node = extra_egg_nodes[i];
00576 EggJointData *data = extra_data[i];
00577 found_egg_match(char_data, data, egg_node, egg_index, model_index);
00578 }
00579
00580 } else {
00581
00582 EggNodeList::iterator ei;
00583 for (ei = extra_egg_nodes.begin(); ei != extra_egg_nodes.end(); ++ei) {
00584 EggNode *egg_node = (*ei);
00585 EggJointData *data = make_joint_data(char_data);
00586 joint_data->_children.push_back(data);
00587 char_data->_joints.push_back(data);
00588 char_data->_components.push_back(data);
00589 data->_parent = joint_data;
00590 data->_new_parent = joint_data;
00591 found_egg_match(char_data, data, egg_node, egg_index, model_index);
00592 }
00593 }
00594 }
00595 }
00596
00597
00598
00599 sort(joint_data->_children.begin(), joint_data->_children.end(),
00600 IndirectCompareNames<Namable>());
00601 }
00602
00603
00604
00605
00606
00607
00608
00609
00610 void EggCharacterCollection::
00611 found_egg_match(EggCharacterData *char_data, EggJointData *joint_data,
00612 EggNode *egg_node, int egg_index, int model_index) {
00613 if (egg_node->has_name()) {
00614 joint_data->add_name(egg_node->get_name(), char_data->_component_names);
00615 }
00616 egg_node->set_name(joint_data->get_name());
00617 joint_data->add_back_pointer(model_index, egg_node);
00618
00619 if (egg_node->is_of_type(EggGroupNode::get_class_type())) {
00620 EggGroupNode *group_node = DCAST(EggGroupNode, egg_node);
00621
00622
00623
00624 EggNodeList egg_nodes;
00625
00626
00627
00628
00629 if (egg_node->is_of_type(EggGroup::get_class_type())) {
00630
00631 EggGroupNode::iterator gi;
00632 for (gi = group_node->begin(); gi != group_node->end(); ++gi) {
00633 EggNode *child = (*gi);
00634 if (child->is_of_type(EggGroup::get_class_type())) {
00635 EggGroup *group = DCAST(EggGroup, child);
00636 if (group->get_group_type() == EggGroup::GT_joint) {
00637 egg_nodes.push_back(group);
00638 }
00639 }
00640 }
00641
00642 } else {
00643
00644 EggGroupNode::iterator gi;
00645 for (gi = group_node->begin(); gi != group_node->end(); ++gi) {
00646 EggNode *child = (*gi);
00647 if (child->is_of_type(EggTable::get_class_type())) {
00648 EggTable *table = DCAST(EggTable, child);
00649 if (!(table->get_name() == "xform")) {
00650 egg_nodes.push_back(table);
00651 }
00652 }
00653 }
00654 }
00655
00656 if (!egg_nodes.empty()) {
00657 match_egg_nodes(char_data, joint_data, egg_nodes,
00658 egg_index, model_index);
00659 }
00660 }
00661 }
00662
00663
00664
00665
00666
00667
00668
00669
00670 void EggCharacterCollection::
00671 rename_char(int i, const string &name) {
00672 nassertv(i >= 0 && i < (int)_characters.size());
00673
00674 EggCharacterData *char_data = _characters[i];
00675 if (char_data->get_name() != name) {
00676 nassertv(get_character_by_name(name) == (EggCharacterData *)NULL);
00677 char_data->rename_char(name);
00678 }
00679 }
00680
00681
00682
00683
00684
00685
00686 void EggCharacterCollection::
00687 write(ostream &out, int indent_level) const {
00688 Characters::const_iterator ci;
00689
00690 for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
00691 EggCharacterData *char_data = (*ci);
00692 char_data->write(out, indent_level);
00693 }
00694 }
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710 void EggCharacterCollection::
00711 check_errors(ostream &out, bool force_initial_rest_frame) {
00712 Characters::const_iterator ci;
00713 for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
00714 EggCharacterData *char_data = (*ci);
00715 int num_joints = char_data->get_num_joints();
00716 for (int j = 0; j < num_joints; j++) {
00717 EggJointData *joint_data = char_data->get_joint(j);
00718 if (joint_data->rest_frames_differ()) {
00719 if (force_initial_rest_frame) {
00720 joint_data->force_initial_rest_frame();
00721 out << "Forced rest frames the same for " << joint_data->get_name()
00722 << ".\n";
00723 } else {
00724 out << "Warning: rest frames for " << joint_data->get_name()
00725 << " differ.\n";
00726 }
00727 }
00728 }
00729
00730 int num_models = char_data->get_num_models();
00731 for (int mi = 0; mi < num_models; mi++) {
00732 int model_index = char_data->get_model_index(mi);
00733 if (!char_data->check_num_frames(model_index)) {
00734 out << "Warning: animation from "
00735 << char_data->get_egg_data(model_index)->get_egg_filename().get_basename()
00736 << " had an inconsistent number of frames.\n";
00737 }
00738 }
00739 }
00740 }