38EggCharacterCollection::
39EggCharacterCollection() {
40 _next_model_index = 0;
46EggCharacterCollection::
47~EggCharacterCollection() {
48 Characters::iterator ci;
50 for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
68 _top_egg_nodes.clear();
70 if (!scan_hierarchy(egg)) {
74 int egg_index = _eggs.size();
76 EggInfo &egg_info = _eggs.back();
78 egg_info._first_model_index = 0;
82 TopEggNodesByName::iterator tni;
83 for (tni = _top_egg_nodes.begin(); tni != _top_egg_nodes.end(); ++tni) {
84 string character_name = (*tni).first;
85 TopEggNodes &top_nodes = (*tni).second;
89 TopEggNodes::iterator ti;
90 for (ti = top_nodes.begin(); ti != top_nodes.end(); ++ti) {
91 EggNode *model_root = (*ti).first;
92 ModelDescription &desc = (*ti).second;
94 int model_index = _next_model_index++;
95 if (egg_info._models.empty()) {
96 egg_info._first_model_index = model_index;
98 egg_info._models.push_back(model_root);
100 char_data->
add_model(model_index, model_root, egg);
101 nassertr(model_index == (
int)_characters_by_model_index.size(), -1);
102 _characters_by_model_index.push_back(char_data);
105 match_egg_nodes(char_data, root_joint, desc._top_nodes,
106 egg_index, model_index);
108 scan_for_morphs(model_root, model_index, char_data);
109 scan_for_sliders(model_root, model_index, char_data);
122 Characters::const_iterator ci;
123 for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
125 if (char_data->get_name() == character_name) {
173 Characters::iterator ci;
174 for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
176 if (char_data->get_name() == character_name) {
183 char_data->set_name(character_name);
184 _characters.push_back(char_data);
196bool EggCharacterCollection::
197scan_hierarchy(
EggNode *egg_node) {
198 if (egg_node->
is_of_type(EggGroup::get_class_type())) {
200 if (group->get_dart_type() != EggGroup::DT_none) {
202 scan_for_top_joints(group, group, group->get_name());
206 }
else if (egg_node->
is_of_type(EggTable::get_class_type())) {
207 EggTable *table = DCAST(EggTable, egg_node);
208 if (table->get_table_type() == EggTable::TT_bundle) {
210 scan_for_top_tables(table, table, table->get_name());
215 bool character_found =
false;
216 if (egg_node->
is_of_type(EggGroupNode::get_class_type())) {
217 EggGroupNode *group = DCAST(EggGroupNode, egg_node);
218 EggGroupNode::iterator gi;
219 for (gi = group->begin(); gi != group->end(); ++gi) {
220 if (scan_hierarchy(*gi)) {
221 character_found =
true;
226 return character_found;
233void EggCharacterCollection::
235 const string &character_name) {
236 if (egg_node->
is_of_type(EggGroup::get_class_type())) {
237 EggGroup *group = DCAST(EggGroup, egg_node);
239 if (group->has_lod()) {
245 if (group->get_group_type() == EggGroup::GT_joint) {
247 ModelDescription &desc = _top_egg_nodes[character_name][model_root];
248 desc._root_node = model_root;
249 desc._top_nodes.push_back(group);
254 if (egg_node->
is_of_type(EggGroupNode::get_class_type())) {
255 EggGroupNode *group = DCAST(EggGroupNode, egg_node);
256 EggGroupNode::iterator gi;
257 for (gi = group->begin(); gi != group->end(); ++gi) {
258 scan_for_top_joints(*gi, model_root, character_name);
267void EggCharacterCollection::
269 const string &character_name) {
272 EggGroupNode::iterator gi;
273 for (gi = bundle->begin(); gi != bundle->end(); ++gi) {
274 EggNode *child = (*gi);
275 if (child->
is_of_type(EggTable::get_class_type())) {
276 EggTable *table = DCAST(EggTable, child);
277 if (table->get_name() ==
"<skeleton>") {
280 ModelDescription &desc = _top_egg_nodes[character_name][model_root];
281 desc._root_node = table;
283 EggGroupNode::iterator cgi;
284 for (cgi = table->begin(); cgi != table->end(); ++cgi) {
285 EggNode *grandchild = (*cgi);
286 if (grandchild->
is_of_type(EggTable::get_class_type())) {
287 desc._top_nodes.push_back(grandchild);
299void EggCharacterCollection::
300scan_for_morphs(
EggNode *egg_node,
int model_index,
302 if (egg_node->
is_of_type(EggPrimitive::get_class_type())) {
303 EggPrimitive *prim = DCAST(EggPrimitive, egg_node);
305 add_morph_back_pointers(prim, prim, model_index, char_data);
308 EggPrimitive::const_iterator vi;
309 for (vi = prim->begin(); vi != prim->end(); ++vi) {
310 EggVertex *vertex = (*vi);
312 add_morph_back_pointers(vertex, vertex, model_index, char_data);
313 add_morph_back_pointers_vertex(vertex, vertex, model_index, char_data);
315 EggMorphVertexList::const_iterator mvi;
316 for (mvi = vertex->_dxyzs.begin();
317 mvi != vertex->_dxyzs.end();
319 const EggMorphVertex &morph = (*mvi);
325 if (egg_node->
is_of_type(EggGroupNode::get_class_type())) {
326 EggGroupNode *group = DCAST(EggGroupNode, egg_node);
327 EggGroupNode::iterator gi;
328 for (gi = group->begin(); gi != group->end(); ++gi) {
329 scan_for_morphs(*gi, model_index, char_data);
338void EggCharacterCollection::
339scan_for_sliders(
EggNode *egg_node,
int model_index,
341 if (egg_node->
is_of_type(EggTable::get_class_type())) {
342 EggTable *bundle = DCAST(EggTable, egg_node);
349 EggGroupNode::iterator gi;
350 for (gi = bundle->begin(); gi != bundle->end(); ++gi) {
351 EggNode *child = (*gi);
352 if (child->
is_of_type(EggTable::get_class_type())) {
353 EggTable *table = DCAST(EggTable, child);
354 if (table->get_name() ==
"morph") {
358 EggGroupNode::iterator cgi;
359 for (cgi = table->begin(); cgi != table->end(); ++cgi) {
360 EggNode *grandchild = (*cgi);
361 if (grandchild->
is_of_type(EggSAnimData::get_class_type())) {
375void EggCharacterCollection::
378 EggMorphNormalList::const_iterator mni;
379 for (mni = attrib->_dnormals.begin();
380 mni != attrib->_dnormals.end();
382 const EggMorphNormal &morph = (*mni);
386 EggMorphColorList::const_iterator mci;
387 for (mci = attrib->_drgbas.begin();
388 mci != attrib->_drgbas.end();
390 const EggMorphColor &morph = (*mci);
399void EggCharacterCollection::
402 EggVertex::const_uv_iterator ui;
404 EggVertexUV *vert_uv = (*ui);
405 EggMorphTexCoordList::const_iterator mti;
406 for (mti = vert_uv->_duvs.begin();
407 mti != vert_uv->_duvs.end();
409 const EggMorphTexCoord &morph = (*mti);
421void EggCharacterCollection::
423 EggNodeList &egg_nodes,
int egg_index,
int model_index) {
426 sort(egg_nodes.begin(), egg_nodes.end(), IndirectCompareNames<Namable>());
428 if (joint_data->_children.empty()) {
431 EggNodeList::iterator ei;
432 for (ei = egg_nodes.begin(); ei != egg_nodes.end(); ++ei) {
433 EggNode *egg_node = (*ei);
435 joint_data->_children.push_back(data);
436 char_data->_joints.push_back(data);
437 char_data->_components.push_back(data);
438 data->_parent = joint_data;
439 data->_new_parent = joint_data;
440 found_egg_match(char_data, data, egg_node, egg_index, model_index);
447 EggNodeList extra_egg_nodes;
448 EggJointData::Children extra_data;
450 EggNodeList::iterator ei;
451 EggJointData::Children::iterator di;
453 ei = egg_nodes.begin();
454 di = joint_data->_children.begin();
456 while (ei != egg_nodes.end() && di != joint_data->_children.end()) {
457 EggNode *egg_node = (*ei);
458 EggJointData *data = (*di);
460 if (egg_node->get_name() < data->get_name()) {
462 extra_egg_nodes.push_back(egg_node);
465 }
else if (data->get_name() < egg_node->get_name()) {
467 extra_data.push_back(data);
472 found_egg_match(char_data, data, egg_node, egg_index, model_index);
478 while (ei != egg_nodes.end()) {
479 EggNode *egg_node = (*ei);
482 extra_egg_nodes.push_back(egg_node);
486 while (di != joint_data->_children.end()) {
487 EggJointData *data = (*di);
490 extra_data.push_back(data);
494 if (!extra_egg_nodes.empty()) {
499 EggNodeList more_egg_nodes;
501 for (ei = extra_egg_nodes.begin(); ei != extra_egg_nodes.end(); ++ei) {
502 EggNode *egg_node = (*ei);
503 bool matched =
false;
504 for (di = extra_data.begin(); di != extra_data.end(); ++di) {
505 EggJointData *data = (*di);
506 if (data->matches_name(egg_node->get_name())) {
507 found_egg_match(char_data, data, egg_node, egg_index, model_index);
508 extra_data.erase(di);
516 more_egg_nodes.push_back(egg_node);
519 extra_egg_nodes.swap(more_egg_nodes);
522 if (!extra_egg_nodes.empty()) {
524 if (extra_egg_nodes.size() == extra_data.size()) {
527 for (i = 0; i < extra_egg_nodes.size(); i++) {
528 EggNode *egg_node = extra_egg_nodes[i];
529 EggJointData *data = extra_data[i];
530 found_egg_match(char_data, data, egg_node, egg_index, model_index);
535 EggNodeList::iterator ei;
536 for (ei = extra_egg_nodes.begin(); ei != extra_egg_nodes.end(); ++ei) {
537 EggNode *egg_node = (*ei);
539 joint_data->_children.push_back(data);
540 char_data->_joints.push_back(data);
541 char_data->_components.push_back(data);
542 data->_parent = joint_data;
543 data->_new_parent = joint_data;
544 found_egg_match(char_data, data, egg_node, egg_index, model_index);
551 sort(joint_data->_children.begin(), joint_data->_children.end(),
552 IndirectCompareNames<Namable>());
559void EggCharacterCollection::
561 EggNode *egg_node,
int egg_index,
int model_index) {
563 joint_data->
add_name(egg_node->get_name(), char_data->_component_names);
565 egg_node->set_name(joint_data->get_name());
568 if (egg_node->
is_of_type(EggGroupNode::get_class_type())) {
569 EggGroupNode *group_node = DCAST(EggGroupNode, egg_node);
573 EggNodeList egg_nodes;
578 if (egg_node->
is_of_type(EggGroup::get_class_type())) {
580 EggGroupNode::iterator gi;
581 for (gi = group_node->begin(); gi != group_node->end(); ++gi) {
582 EggNode *child = (*gi);
583 if (child->
is_of_type(EggGroup::get_class_type())) {
584 EggGroup *group = DCAST(EggGroup, child);
585 if (group->get_group_type() == EggGroup::GT_joint) {
586 egg_nodes.push_back(group);
593 EggGroupNode::iterator gi;
594 for (gi = group_node->begin(); gi != group_node->end(); ++gi) {
595 EggNode *child = (*gi);
596 if (child->
is_of_type(EggTable::get_class_type())) {
597 EggTable *table = DCAST(EggTable, child);
598 if (!(table->get_name() ==
"xform")) {
599 egg_nodes.push_back(table);
605 if (!egg_nodes.empty()) {
606 match_egg_nodes(char_data, joint_data, egg_nodes,
607 egg_index, model_index);
618 nassertv(i >= 0 && i < (
int)_characters.size());
621 if (char_data->get_name() != name) {
630void EggCharacterCollection::
631write(std::ostream &out,
int indent_level)
const {
632 Characters::const_iterator ci;
634 for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
636 char_data->write(out, indent_level);
651check_errors(std::ostream &out,
bool force_initial_rest_frame) {
652 Characters::const_iterator ci;
653 for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
656 for (
int j = 0; j < num_joints; j++) {
659 if (force_initial_rest_frame) {
661 out <<
"Forced rest frames the same for " << joint_data->get_name()
664 out <<
"Warning: rest frames for " << joint_data->get_name()
671 for (
int mi = 0; mi < num_models; mi++) {
674 out <<
"Warning: animation from "
676 <<
" had an inconsistent number of frames.\n";
The set of attributes that may be applied to vertices as well as polygons, such as surface normal and...
EggCharacterData * make_character(const std::string &character_name)
Allocates and returns a new EggCharacterData object representing the named character,...
virtual EggSliderData * make_slider_data(EggCharacterData *char_data)
Allocates and returns a new EggSliderData structure for the given character.
int add_egg(EggData *egg)
Adds a new egg file to the list of models and animation files for this particular character.
virtual EggJointData * make_joint_data(EggCharacterData *char_data)
Allocates and returns a new EggJointData structure for the given character.
void check_errors(std::ostream &out, bool force_initial_rest_frame)
Can be called after the collection has been completely filled up with egg files to output any message...
void rename_char(int i, const std::string &name)
Renames the ith character to the indicated name.
virtual EggCharacterData * make_character_data()
Allocates and returns a new EggCharacterData structure.
EggCharacterData * get_character_by_name(const std::string &character_name) const
Returns the Character with the indicated name, if it exists in the collection, or NULL if it does not...
Represents a single character, as read and collected from several models and animation files.
EggJointData * get_root_joint() const
Returns the root joint of the character hierarchy.
int get_model_index(int n) const
Returns the model_index of the nth model associated with this character.
EggData * get_egg_data(int n) const
Returns the EggData representing the egg file that defined this particular model.
EggJointData * get_joint(int n) const
Returns the nth joint in the character joint hierarchy.
bool check_num_frames(int model_index)
Walks through each component and ensures that all have the same number of frames of animation (except...
EggSliderData * make_slider(const std::string &name)
Returns the slider matching the indicated name.
int get_num_models() const
Returns the total number of models associated with this character.
void add_model(int model_index, EggNode *model_root, EggData *egg_data)
Indicates that the given model_index (with the indicated model_root) is associated with this characte...
void rename_char(const std::string &name)
Renames all of the models in the character data to the indicated name.
int get_num_joints() const
Returns the total number of joints in the character joint hierarchy.
void add_name(const std::string &name, NameUniquifier &uniquifier)
Adds the indicated name to the set of names that this component can be identified with.
This is the primary interface into all the egg data, and the root of the egg file structure.
get_egg_filename
Returns the directory in which the egg file is considered to reside.
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
This is one node of a hierarchy of EggJointData nodes, each of which represents a single joint of the...
virtual void add_back_pointer(int model_index, EggObject *egg_object)
Adds the indicated model joint or anim table to the data.
bool rest_frames_differ() const
Returns true if the rest frames for different models differ in their initial value.
void force_initial_rest_frame()
Forces all of the joints to have the same rest frame value as the first joint read in.
A base class for things that may be directly added into the egg hierarchy.
The highest-level base class in the egg directory.
This corresponds to a single morph slider control.
virtual void add_back_pointer(int model_index, EggObject *egg_object)
Adds the indicated vertex, primitive, or morph table to the data.
This corresponds to a a <Bundle> entry.
Any one-, two-, three-, or four-component vertex, possibly with attributes such as a normal.
const_uv_iterator uv_end() const
Returns an iterator that allows walking through the complete set of named UV's on the vertex.
const_uv_iterator uv_begin() const
Returns an iterator that allows walking through the complete set of named UV's on the vertex.
bool has_name() const
Returns true if the Namable has a nonempty name set, false if the name is empty.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.