38 EggCharacterCollection::
39 EggCharacterCollection() {
40 _next_model_index = 0;
46 EggCharacterCollection::
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;
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);
196 bool EggCharacterCollection::
197 scan_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())) {
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())) {
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;
233 void EggCharacterCollection::
235 const string &character_name) {
236 if (egg_node->
is_of_type(EggGroup::get_class_type())) {
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())) {
256 EggGroupNode::iterator gi;
257 for (gi = group->begin(); gi != group->end(); ++gi) {
258 scan_for_top_joints(*gi, model_root, character_name);
267 void EggCharacterCollection::
269 const string &character_name) {
272 EggGroupNode::iterator gi;
273 for (gi = bundle->begin(); gi != bundle->end(); ++gi) {
275 if (child->
is_of_type(EggTable::get_class_type())) {
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) {
286 if (grandchild->
is_of_type(EggTable::get_class_type())) {
287 desc._top_nodes.push_back(grandchild);
299 void EggCharacterCollection::
300 scan_for_morphs(
EggNode *egg_node,
int model_index,
302 if (egg_node->
is_of_type(EggPrimitive::get_class_type())) {
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) {
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();
320 char_data->
make_slider(morph.get_name())->add_back_pointer(model_index, vertex);
325 if (egg_node->
is_of_type(EggGroupNode::get_class_type())) {
327 EggGroupNode::iterator gi;
328 for (gi = group->begin(); gi != group->end(); ++gi) {
329 scan_for_morphs(*gi, model_index, char_data);
338 void EggCharacterCollection::
339 scan_for_sliders(
EggNode *egg_node,
int model_index,
341 if (egg_node->
is_of_type(EggTable::get_class_type())) {
349 EggGroupNode::iterator gi;
350 for (gi = bundle->begin(); gi != bundle->end(); ++gi) {
352 if (child->
is_of_type(EggTable::get_class_type())) {
354 if (table->get_name() ==
"morph") {
358 EggGroupNode::iterator cgi;
359 for (cgi = table->begin(); cgi != table->end(); ++cgi) {
361 if (grandchild->
is_of_type(EggSAnimData::get_class_type())) {
362 char_data->
make_slider(grandchild->get_name())->add_back_pointer(model_index, grandchild);
375 void EggCharacterCollection::
378 EggMorphNormalList::const_iterator mni;
379 for (mni = attrib->_dnormals.begin();
380 mni != attrib->_dnormals.end();
383 char_data->
make_slider(morph.get_name())->add_back_pointer(model_index, egg_object);
386 EggMorphColorList::const_iterator mci;
387 for (mci = attrib->_drgbas.begin();
388 mci != attrib->_drgbas.end();
391 char_data->
make_slider(morph.get_name())->add_back_pointer(model_index, egg_object);
399 void EggCharacterCollection::
405 EggMorphTexCoordList::const_iterator mti;
406 for (mti = vert_uv->_duvs.begin();
407 mti != vert_uv->_duvs.end();
410 char_data->
make_slider(morph.get_name())->add_back_pointer(model_index, egg_object);
421 void EggCharacterCollection::
423 EggNodeList &egg_nodes,
int egg_index,
int model_index) {
428 if (joint_data->_children.empty()) {
431 EggNodeList::iterator ei;
432 for (ei = egg_nodes.begin(); ei != egg_nodes.end(); ++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;
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()) {
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()) {
482 extra_egg_nodes.push_back(egg_node);
486 while (di != joint_data->_children.end()) {
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) {
503 bool matched =
false;
504 for (di = extra_data.begin(); di != extra_data.end(); ++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];
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) {
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(),
559 void 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())) {
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) {
583 if (child->
is_of_type(EggGroup::get_class_type())) {
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) {
596 if (child->
is_of_type(EggTable::get_class_type())) {
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) {
623 char_data->rename_char(name);
630 void EggCharacterCollection::
631 write(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);
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";
A base class for any of a number of kinds of geometry primitives: polygons, point lights,...
The set of UV's that may or may not be assigned to a vertex.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual EggCharacterData * make_character_data()
Allocates and returns a new EggCharacterData structure.
This is an iterator adaptor that converts any iterator that returns a pair (e.g.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_num_joints() const
Returns the total number of joints in the character joint hierarchy.
void rename_char(int i, const std::string &name)
Renames the ith character to the indicated name.
This is our own Panda specialization on the default STL map.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggJointData * get_root_joint() const
Returns the root joint of the character 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...
EggCharacterData * make_character(const std::string &character_name)
Allocates and returns a new EggCharacterData object representing the named character,...
A base class for nodes in the hierarchy that are not leaf nodes.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_egg_filename
Returns the directory in which the egg file is considered to reside.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This corresponds to a single morph slider control.
int add_egg(EggData *egg)
Adds a new egg file to the list of models and animation files for this particular character.
int get_num_models() const
Returns the total number of models associated with this character.
A single <Dxyz> or <Duv> or some such entry.
This is the primary interface into all the egg data, and the root of the egg file structure.
bool rest_frames_differ() const
Returns true if the rest frames for different models differ in their initial value.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggData * get_egg_data(int n) const
Returns the EggData representing the egg file that defined this particular model.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
The set of attributes that may be applied to vertices as well as polygons, such as surface normal and...
Any one-, two-, three-, or four-component vertex, possibly with attributes such as a normal.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
An STL function object class, this is intended to be used on any ordered collection of pointers to cl...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Represents a single character, as read and collected from several models and animation files.
EggSliderData * make_slider(const std::string &name)
Returns the slider matching the indicated name.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual EggSliderData * make_slider_data(EggCharacterData *char_data)
Allocates and returns a new EggSliderData structure for the given character.
EggJointData * get_joint(int n) const
Returns the nth joint in the character joint hierarchy.
const_uv_iterator uv_begin() const
Returns an iterator that allows walking through the complete set of named UV's on the vertex.
A base class for things that may be directly added into the egg hierarchy.
void force_initial_rest_frame()
Forces all of the joints to have the same rest frame value as the first joint read in.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
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...
bool has_name() const
Returns true if the Namable has a nonempty name set, false if the name is empty.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
The highest-level base class in the egg directory.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual EggJointData * make_joint_data(EggCharacterData *char_data)
Allocates and returns a new EggJointData structure for the given character.
const_uv_iterator uv_end() const
Returns an iterator that allows walking through the complete set of named UV's on the vertex.
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...
int get_model_index(int n) const
Returns the model_index of the nth model associated with this character.