Panda3D
eggCharacterCollection.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file eggCharacterCollection.cxx
10  * @author drose
11  * @date 2001-02-26
12  */
13 
14 #include "eggCharacterCollection.h"
15 #include "eggCharacterData.h"
16 #include "eggJointData.h"
17 #include "eggSliderData.h"
18 
19 #include "dcast.h"
20 #include "eggGroup.h"
21 #include "eggTable.h"
22 #include "eggPrimitive.h"
23 #include "eggVertex.h"
24 #include "eggVertexUV.h"
25 #include "eggMorphList.h"
26 #include "eggSAnimData.h"
27 #include "indirectCompareNames.h"
28 #include "indent.h"
29 
30 #include <algorithm>
31 
32 using std::string;
33 
34 
35 /**
36  *
37  */
38 EggCharacterCollection::
39 EggCharacterCollection() {
40  _next_model_index = 0;
41 }
42 
43 /**
44  *
45  */
46 EggCharacterCollection::
47 ~EggCharacterCollection() {
48  Characters::iterator ci;
49 
50  for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
51  delete (*ci);
52  }
53 }
54 
55 /**
56  * Adds a new egg file to the list of models and animation files for this
57  * particular character.
58  *
59  * Returns the new egg_index if the file is successfully added, or -1 if there
60  * is some problem (for instance, it does not contain a character model or
61  * animation table).
62  *
63  * If the joint hierarchy does not match the existing joint hierarchy, a best
64  * match is attempted.
65  */
68  _top_egg_nodes.clear();
69 
70  if (!scan_hierarchy(egg)) {
71  return -1;
72  }
73 
74  int egg_index = _eggs.size();
75  _eggs.push_back(EggInfo());
76  EggInfo &egg_info = _eggs.back();
77  egg_info._egg = egg;
78  egg_info._first_model_index = 0;
79 
80  // Now, for each model, add an entry in the egg_info and match the joint
81  // hierarchy to the known joints.
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;
86  EggCharacterData *char_data = make_character(character_name);
87  EggJointData *root_joint = char_data->get_root_joint();
88 
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;
93 
94  int model_index = _next_model_index++;
95  if (egg_info._models.empty()) {
96  egg_info._first_model_index = model_index;
97  }
98  egg_info._models.push_back(model_root);
99 
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);
103  root_joint->add_back_pointer(model_index, desc._root_node);
104 
105  match_egg_nodes(char_data, root_joint, desc._top_nodes,
106  egg_index, model_index);
107 
108  scan_for_morphs(model_root, model_index, char_data);
109  scan_for_sliders(model_root, model_index, char_data);
110  }
111  }
112 
113  return egg_index;
114 }
115 
116 /**
117  * Returns the Character with the indicated name, if it exists in the
118  * collection, or NULL if it does not.
119  */
121 get_character_by_name(const string &character_name) const {
122  Characters::const_iterator ci;
123  for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
124  EggCharacterData *char_data = (*ci);
125  if (char_data->get_name() == character_name) {
126  return char_data;
127  }
128  }
129 
130  return nullptr;
131 }
132 
133 
134 /**
135  * Allocates and returns a new EggCharacterData structure. This is primarily
136  * intended as a hook so derived classes can customize the type of
137  * EggCharacterData nodes used to represent the characters in this collection.
138  */
141  return new EggCharacterData(this);
142 }
143 
144 /**
145  * Allocates and returns a new EggJointData structure for the given character.
146  * This is primarily intended as a hook so derived classes can customize the
147  * type of EggJointData nodes used to represent the joint hierarchy.
148  */
151  return new EggJointData(this, char_data);
152 }
153 
154 /**
155  * Allocates and returns a new EggSliderData structure for the given
156  * character. This is primarily intended as a hook so derived classes can
157  * customize the type of EggSliderData nodes used to represent the slider
158  * list.
159  */
162  return new EggSliderData(this, char_data);
163 }
164 
165 /**
166  * Allocates and returns a new EggCharacterData object representing the named
167  * character, if there is not already a character by that name.
168  */
170 make_character(const string &character_name) {
171  // Does the named character exist yet?
172 
173  Characters::iterator ci;
174  for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
175  EggCharacterData *char_data = (*ci);
176  if (char_data->get_name() == character_name) {
177  return char_data;
178  }
179  }
180 
181  // Define a new character.
182  EggCharacterData *char_data = make_character_data();
183  char_data->set_name(character_name);
184  _characters.push_back(char_data);
185  return char_data;
186 }
187 
188 /**
189  * Walks the given egg data's hierarchy, looking for either the start of an
190  * animation channel or the start of a character model. Returns true if
191  * either (or both) is found, false if the model appears to have nothing to do
192  * with characters.
193  *
194  * Fills up the _top_egg_nodes according to the nodes found.
195  */
196 bool EggCharacterCollection::
197 scan_hierarchy(EggNode *egg_node) {
198  if (egg_node->is_of_type(EggGroup::get_class_type())) {
199  EggGroup *group = DCAST(EggGroup, egg_node);
200  if (group->get_dart_type() != EggGroup::DT_none) {
201  // A group with a <Dart> flag begins a character model.
202  scan_for_top_joints(group, group, group->get_name());
203  return true;
204  }
205 
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) {
209  // A <Bundle> begins an animation table.
210  scan_for_top_tables(table, table, table->get_name());
211  return true;
212  }
213  }
214 
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;
222  }
223  }
224  }
225 
226  return character_found;
227 }
228 
229 /**
230  * Once a character model has been found, continue scanning the egg hierarchy
231  * to look for the topmost <Joint> nodes encountered.
232  */
233 void EggCharacterCollection::
234 scan_for_top_joints(EggNode *egg_node, EggNode *model_root,
235  const string &character_name) {
236  if (egg_node->is_of_type(EggGroup::get_class_type())) {
237  EggGroup *group = DCAST(EggGroup, egg_node);
238 
239  if (group->has_lod()) {
240  // This group has an LOD specification; that indicates multiple skeleton
241  // hierarchies for this character, one for each LOD. We call each of
242  // these a separate model.
243  model_root = group;
244  }
245  if (group->get_group_type() == EggGroup::GT_joint) {
246  // A <Joint> node begins a model hierarchy.
247  ModelDescription &desc = _top_egg_nodes[character_name][model_root];
248  desc._root_node = model_root;
249  desc._top_nodes.push_back(group);
250  return;
251  }
252  }
253 
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);
259  }
260  }
261 }
262 
263 /**
264  * Once an animation has been found, continue scanning the egg hierarchy to
265  * look for the topmost <Table> nodes encountered.
266  */
267 void EggCharacterCollection::
268 scan_for_top_tables(EggTable *bundle, EggNode *model_root,
269  const string &character_name) {
270  // We really only need to check the immediate children of the bundle for a
271  // table node called "<skeleton>".
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>") {
278  // Here it is! Now the immediate children of this node are the top
279  // tables.
280  ModelDescription &desc = _top_egg_nodes[character_name][model_root];
281  desc._root_node = table;
282 
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);
288  }
289  }
290  }
291  }
292  }
293 }
294 
295 /**
296  * Go back through a model's hierarchy and look for morph targets on the
297  * vertices and primitives.
298  */
299 void EggCharacterCollection::
300 scan_for_morphs(EggNode *egg_node, int model_index,
301  EggCharacterData *char_data) {
302  if (egg_node->is_of_type(EggPrimitive::get_class_type())) {
303  EggPrimitive *prim = DCAST(EggPrimitive, egg_node);
304  // Check for morphs on the primitive.
305  add_morph_back_pointers(prim, prim, model_index, char_data);
306 
307  // Also check for morphs on each of the prim's vertices.
308  EggPrimitive::const_iterator vi;
309  for (vi = prim->begin(); vi != prim->end(); ++vi) {
310  EggVertex *vertex = (*vi);
311 
312  add_morph_back_pointers(vertex, vertex, model_index, char_data);
313  add_morph_back_pointers_vertex(vertex, vertex, model_index, char_data);
314 
315  EggMorphVertexList::const_iterator mvi;
316  for (mvi = vertex->_dxyzs.begin();
317  mvi != vertex->_dxyzs.end();
318  ++mvi) {
319  const EggMorphVertex &morph = (*mvi);
320  char_data->make_slider(morph.get_name())->add_back_pointer(model_index, vertex);
321  }
322  }
323  }
324 
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);
330  }
331  }
332 }
333 
334 /**
335  * Go back to the animation tables and look for morph slider animation
336  * channels.
337  */
338 void EggCharacterCollection::
339 scan_for_sliders(EggNode *egg_node, int model_index,
340  EggCharacterData *char_data) {
341  if (egg_node->is_of_type(EggTable::get_class_type())) {
342  EggTable *bundle = DCAST(EggTable, egg_node);
343 
344  // We really only need to check the immediate children of the bundle for a
345  // table node called "morph". This is a sibling of "<skeleton>", which we
346  // found a minute ago, but we weren't ready to scan for the morph sliders
347  // at the time, so we have to look again now.
348 
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") {
355  // Here it is! Now the immediate children of this node are all the
356  // slider channels.
357 
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())) {
362  char_data->make_slider(grandchild->get_name())->add_back_pointer(model_index, grandchild);
363  }
364  }
365  }
366  }
367  }
368  }
369 }
370 
371 /**
372  * Adds the back pointers for the kinds of morphs we might find in an
373  * EggAttributes object.
374  */
375 void EggCharacterCollection::
376 add_morph_back_pointers(EggAttributes *attrib, EggObject *egg_object,
377  int model_index, EggCharacterData *char_data) {
378  EggMorphNormalList::const_iterator mni;
379  for (mni = attrib->_dnormals.begin();
380  mni != attrib->_dnormals.end();
381  ++mni) {
382  const EggMorphNormal &morph = (*mni);
383  char_data->make_slider(morph.get_name())->add_back_pointer(model_index, egg_object);
384  }
385 
386  EggMorphColorList::const_iterator mci;
387  for (mci = attrib->_drgbas.begin();
388  mci != attrib->_drgbas.end();
389  ++mci) {
390  const EggMorphColor &morph = (*mci);
391  char_data->make_slider(morph.get_name())->add_back_pointer(model_index, egg_object);
392  }
393 }
394 
395 /**
396  * Adds the back pointers for the kinds of morphs we might find in an
397  * EggVertex object.
398  */
399 void EggCharacterCollection::
400 add_morph_back_pointers_vertex(EggVertex *vertex, EggObject *egg_object,
401  int model_index, EggCharacterData *char_data) {
403  for (ui = vertex->uv_begin(); ui != vertex->uv_end(); ++ui) {
404  EggVertexUV *vert_uv = (*ui);
405  EggMorphTexCoordList::const_iterator mti;
406  for (mti = vert_uv->_duvs.begin();
407  mti != vert_uv->_duvs.end();
408  ++mti) {
409  const EggMorphTexCoord &morph = (*mti);
410  char_data->make_slider(morph.get_name())->add_back_pointer(model_index, egg_object);
411  }
412  }
413 }
414 
415 /**
416  * Attempts to match up the indicated list of egg_nodes with the children of
417  * the given joint_data, by name if possible.
418  *
419  * Also recurses on each matched joint to build up the entire joint hierarchy.
420  */
421 void EggCharacterCollection::
422 match_egg_nodes(EggCharacterData *char_data, EggJointData *joint_data,
423  EggNodeList &egg_nodes, int egg_index, int model_index) {
424  // Sort the list of egg_nodes in order by name. This will make the matching
425  // up by names easier and more reliable.
426  sort(egg_nodes.begin(), egg_nodes.end(), IndirectCompareNames<Namable>());
427 
428  if (joint_data->_children.empty()) {
429  // If the EggJointData has no children yet, we must be the first.
430  // Gleefully define all the joints.
431  EggNodeList::iterator ei;
432  for (ei = egg_nodes.begin(); ei != egg_nodes.end(); ++ei) {
433  EggNode *egg_node = (*ei);
434  EggJointData *data = make_joint_data(char_data);
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);
441  }
442 
443  } else {
444  // The EggJointData already has children; therefore, we have to match our
445  // joints up with the already-existing ones.
446 
447  EggNodeList extra_egg_nodes;
448  EggJointData::Children extra_data;
449 
450  EggNodeList::iterator ei;
451  EggJointData::Children::iterator di;
452 
453  ei = egg_nodes.begin();
454  di = joint_data->_children.begin();
455 
456  while (ei != egg_nodes.end() && di != joint_data->_children.end()) {
457  EggNode *egg_node = (*ei);
458  EggJointData *data = (*di);
459 
460  if (egg_node->get_name() < data->get_name()) {
461  // Here's a joint in the egg file, unmatched in the data.
462  extra_egg_nodes.push_back(egg_node);
463  ++ei;
464 
465  } else if (data->get_name() < egg_node->get_name()) {
466  // Here's a joint in the data, umatched by the egg file.
467  extra_data.push_back(data);
468  ++di;
469 
470  } else {
471  // Hey, these two match! Hooray!
472  found_egg_match(char_data, data, egg_node, egg_index, model_index);
473  ++ei;
474  ++di;
475  }
476  }
477 
478  while (ei != egg_nodes.end()) {
479  EggNode *egg_node = (*ei);
480 
481  // Here's a joint in the egg file, unmatched in the data.
482  extra_egg_nodes.push_back(egg_node);
483  ++ei;
484  }
485 
486  while (di != joint_data->_children.end()) {
487  EggJointData *data = (*di);
488 
489  // Here's a joint in the data, umatched by the egg file.
490  extra_data.push_back(data);
491  ++di;
492  }
493 
494  if (!extra_egg_nodes.empty()) {
495  // If we have some extra egg_nodes, we have to find a place to match
496  // them. (If we only had extra data, we don't care.)
497 
498  // First, check to see if any of the names match any past-used name.
499  EggNodeList more_egg_nodes;
500 
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);
509  matched = true;
510  break;
511  }
512  }
513 
514  if (!matched) {
515  // This joint name was never seen before.
516  more_egg_nodes.push_back(egg_node);
517  }
518  }
519  extra_egg_nodes.swap(more_egg_nodes);
520  }
521 
522  if (!extra_egg_nodes.empty()) {
523  // Ok, we've still got to find a home for these remaining egg_nodes.
524  if (extra_egg_nodes.size() == extra_data.size()) {
525  // Match 'em up one-for-one.
526  size_t i;
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);
531  }
532 
533  } else {
534  // Just tack 'em on the end.
535  EggNodeList::iterator ei;
536  for (ei = extra_egg_nodes.begin(); ei != extra_egg_nodes.end(); ++ei) {
537  EggNode *egg_node = (*ei);
538  EggJointData *data = make_joint_data(char_data);
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);
545  }
546  }
547  }
548  }
549 
550  // Now sort the generated joint data hierarchy by name, just to be sure.
551  sort(joint_data->_children.begin(), joint_data->_children.end(),
553 }
554 
555 /**
556  * Marks a one-to-one association between the indicated EggJointData and the
557  * indicated EggNode, and then recurses below.
558  */
559 void EggCharacterCollection::
560 found_egg_match(EggCharacterData *char_data, EggJointData *joint_data,
561  EggNode *egg_node, int egg_index, int model_index) {
562  if (egg_node->has_name()) {
563  joint_data->add_name(egg_node->get_name(), char_data->_component_names);
564  }
565  egg_node->set_name(joint_data->get_name());
566  joint_data->add_back_pointer(model_index, egg_node);
567 
568  if (egg_node->is_of_type(EggGroupNode::get_class_type())) {
569  EggGroupNode *group_node = DCAST(EggGroupNode, egg_node);
570 
571  // Now consider all the children of egg_node that are themselves joints or
572  // tables.
573  EggNodeList egg_nodes;
574 
575  // Two approaches: either we are scanning a model with joints, or an
576  // animation bundle with tables.
577 
578  if (egg_node->is_of_type(EggGroup::get_class_type())) {
579  // A model with joints.
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);
587  }
588  }
589  }
590 
591  } else {
592  // An animation bundle with tables.
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);
600  }
601  }
602  }
603  }
604 
605  if (!egg_nodes.empty()) {
606  match_egg_nodes(char_data, joint_data, egg_nodes,
607  egg_index, model_index);
608  }
609  }
610 }
611 
612 /**
613  * Renames the ith character to the indicated name. This name must not
614  * already be used by another character in the collection.
615  */
617 rename_char(int i, const string &name) {
618  nassertv(i >= 0 && i < (int)_characters.size());
619 
620  EggCharacterData *char_data = _characters[i];
621  if (char_data->get_name() != name) {
622  nassertv(get_character_by_name(name) == nullptr);
623  char_data->rename_char(name);
624  }
625 }
626 
627 /**
628  *
629  */
630 void EggCharacterCollection::
631 write(std::ostream &out, int indent_level) const {
632  Characters::const_iterator ci;
633 
634  for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
635  EggCharacterData *char_data = (*ci);
636  char_data->write(out, indent_level);
637  }
638 }
639 
640 /**
641  * Can be called after the collection has been completely filled up with egg
642  * files to output any messages from warning conditions that have been
643  * detected, such as inconsistent animation tables.
644  *
645  * In addition to reporting this errors, calling this function will also
646  * ensure that they are all repaired. Pass force_initial_rest_frame as true
647  * to also force rest frames from different models to be the same if they are
648  * initially different.
649  */
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) {
654  EggCharacterData *char_data = (*ci);
655  int num_joints = char_data->get_num_joints();
656  for (int j = 0; j < num_joints; j++) {
657  EggJointData *joint_data = char_data->get_joint(j);
658  if (joint_data->rest_frames_differ()) {
659  if (force_initial_rest_frame) {
660  joint_data->force_initial_rest_frame();
661  out << "Forced rest frames the same for " << joint_data->get_name()
662  << ".\n";
663  } else {
664  out << "Warning: rest frames for " << joint_data->get_name()
665  << " differ.\n";
666  }
667  }
668  }
669 
670  int num_models = char_data->get_num_models();
671  for (int mi = 0; mi < num_models; mi++) {
672  int model_index = char_data->get_model_index(mi);
673  if (!char_data->check_num_frames(model_index)) {
674  out << "Warning: animation from "
675  << char_data->get_egg_data(model_index)->get_egg_filename().get_basename()
676  << " had an inconsistent number of frames.\n";
677  }
678  }
679  }
680 }
eggTable.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggCharacterData::make_slider
EggSliderData * make_slider(const std::string &name)
Returns the slider matching the indicated name.
Definition: eggCharacterData.cxx:356
eggPrimitive.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pvector< EggJointData * >
eggCharacterCollection.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggJointData::force_initial_rest_frame
void force_initial_rest_frame()
Forces all of the joints to have the same rest frame value as the first joint read in.
Definition: eggJointData.cxx:121
EggJointData::add_back_pointer
virtual void add_back_pointer(int model_index, EggObject *egg_object)
Adds the indicated model joint or anim table to the data.
Definition: eggJointData.cxx:417
pmap
This is our own Panda specialization on the default STL map.
Definition: pmap.h:49
dcast.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggCharacterCollection::make_slider_data
virtual EggSliderData * make_slider_data(EggCharacterData *char_data)
Allocates and returns a new EggSliderData structure for the given character.
Definition: eggCharacterCollection.cxx:161
EggCharacterData
Represents a single character, as read and collected from several models and animation files.
Definition: eggCharacterData.h:52
eggSAnimData.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
IndirectCompareNames
An STL function object class, this is intended to be used on any ordered collection of pointers to cl...
Definition: indirectCompareNames.h:26
EggTable
This corresponds to a.
Definition: eggTable.h:27
EggGroupNode
A base class for nodes in the hierarchy that are not leaf nodes.
Definition: eggGroupNode.h:46
EggCharacterData::add_model
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...
Definition: eggCharacterData.cxx:85
EggPrimitive
A base class for any of a number of kinds of geometry primitives: polygons, point lights,...
Definition: eggPrimitive.h:47
EggCharacterCollection::EggInfo
Definition: eggCharacterCollection.h:62
eggJointData.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggData::get_egg_filename
get_egg_filename
Returns the directory in which the egg file is considered to reside.
Definition: eggData.h:74
EggCharacterData::get_joint
EggJointData * get_joint(int n) const
Returns the nth joint in the character joint hierarchy.
Definition: eggCharacterData.I:110
EggCharacterCollection::make_joint_data
virtual EggJointData * make_joint_data(EggCharacterData *char_data)
Allocates and returns a new EggJointData structure for the given character.
Definition: eggCharacterCollection.cxx:150
EggCharacterCollection::check_errors
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...
Definition: eggCharacterCollection.cxx:651
EggData
This is the primary interface into all the egg data, and the root of the egg file structure.
Definition: eggData.h:37
EggJointData
This is one node of a hierarchy of EggJointData nodes, each of which represents a single joint of the...
Definition: eggJointData.h:31
EggVertex
Any one-, two-, three-, or four-component vertex, possibly with attributes such as a normal.
Definition: eggVertex.h:39
eggVertex.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eggSliderData.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggVertex::uv_end
const_uv_iterator uv_end() const
Returns an iterator that allows walking through the complete set of named UV's on the vertex.
Definition: eggVertex.I:242
EggJointData::rest_frames_differ
bool rest_frames_differ() const
Returns true if the rest frames for different models differ in their initial value.
Definition: eggJointData.I:69
EggVertexUV
The set of UV's that may or may not be assigned to a vertex.
Definition: eggVertexUV.h:29
second_of_pair_iterator
This is an iterator adaptor that converts any iterator that returns a pair (e.g.
Definition: iterator_types.h:43
eggVertexUV.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggCharacterData::rename_char
void rename_char(const std::string &name)
Renames all of the models in the character data to the indicated name.
Definition: eggCharacterData.cxx:66
Namable::has_name
bool has_name() const
Returns true if the Namable has a nonempty name set, false if the name is empty.
Definition: namable.I:44
eggCharacterData.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggCharacterCollection::rename_char
void rename_char(int i, const std::string &name)
Renames the ith character to the indicated name.
Definition: eggCharacterCollection.cxx:617
EggCharacterCollection::make_character_data
virtual EggCharacterData * make_character_data()
Allocates and returns a new EggCharacterData structure.
Definition: eggCharacterCollection.cxx:140
EggSliderData
This corresponds to a single morph slider control.
Definition: eggSliderData.h:28
eggMorphList.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggComponentData::add_name
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.
Definition: eggComponentData.cxx:56
EggCharacterData::get_model_index
int get_model_index(int n) const
Returns the model_index of the nth model associated with this character.
Definition: eggCharacterData.I:37
EggCharacterData::check_num_frames
bool check_num_frames(int model_index)
Walks through each component and ensures that all have the same number of frames of animation (except...
Definition: eggCharacterData.cxx:144
EggVertex::uv_begin
const_uv_iterator uv_begin() const
Returns an iterator that allows walking through the complete set of named UV's on the vertex.
Definition: eggVertex.I:220
EggCharacterData::get_num_joints
int get_num_joints() const
Returns the total number of joints in the character joint hierarchy.
Definition: eggCharacterData.I:101
EggCharacterCollection::make_character
EggCharacterData * make_character(const std::string &character_name)
Allocates and returns a new EggCharacterData object representing the named character,...
Definition: eggCharacterCollection.cxx:170
EggSliderData::add_back_pointer
virtual void add_back_pointer(int model_index, EggObject *egg_object)
Adds the indicated vertex, primitive, or morph table to the data.
Definition: eggSliderData.cxx:57
EggCharacterData::get_egg_data
EggData * get_egg_data(int n) const
Returns the EggData representing the egg file that defined this particular model.
Definition: eggCharacterData.I:59
EggCharacterData::get_root_joint
EggJointData * get_root_joint() const
Returns the root joint of the character hierarchy.
Definition: eggCharacterData.I:71
EggCharacterCollection::add_egg
int add_egg(EggData *egg)
Adds a new egg file to the list of models and animation files for this particular character.
Definition: eggCharacterCollection.cxx:67
EggMorph
A single <Dxyz> or <Duv> or some such entry.
Definition: eggMorph.h:30
EggCharacterCollection::get_character_by_name
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...
Definition: eggCharacterCollection.cxx:121
indent.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggCharacterData::get_num_models
int get_num_models() const
Returns the total number of models associated with this character.
Definition: eggCharacterData.I:22
EggObject
The highest-level base class in the egg directory.
Definition: eggObject.h:29
EggNode
A base class for things that may be directly added into the egg hierarchy.
Definition: eggNode.h:35
EggGroup
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
Definition: eggGroup.h:34
eggGroup.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggAttributes
The set of attributes that may be applied to vertices as well as polygons, such as surface normal and...
Definition: eggAttributes.h:33
TypedObject::is_of_type
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:28
indirectCompareNames.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.