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();
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())) {
375 void EggCharacterCollection::
378 EggMorphNormalList::const_iterator mni;
379 for (mni = attrib->_dnormals.begin();
380 mni != attrib->_dnormals.end();
386 EggMorphColorList::const_iterator mci;
387 for (mci = attrib->_drgbas.begin();
388 mci != attrib->_drgbas.end();
399 void EggCharacterCollection::
405 EggMorphTexCoordList::const_iterator mti;
406 for (mti = vert_uv->_duvs.begin();
407 mti != vert_uv->_duvs.end();
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) {
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);
651 check_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.
A base class for nodes in the hierarchy that are not leaf nodes.
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 single <Dxyz> or <Duv> or some such entry.
A base class for things that may be directly added into the egg hierarchy.
The highest-level base class in the egg directory.
A base class for any of a number of kinds of geometry primitives: polygons, point lights,...
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.
The set of UV's that may or may not be assigned to a vertex.
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.
An STL function object class, this is intended to be used on any ordered collection of pointers to cl...
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.
This is our own Panda specialization on the default STL map.
This is an iterator adaptor that converts any iterator that returns a pair (e.g.
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.