Panda3D
eggCharacterData.cxx
1 // Filename: eggCharacterData.cxx
2 // Created by: drose (23Feb01)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "eggCharacterData.h"
16 #include "eggCharacterCollection.h"
17 #include "eggCharacterDb.h"
18 #include "eggJointData.h"
19 #include "eggSliderData.h"
20 #include "indent.h"
21 
22 #include <algorithm>
23 
24 // An STL function object to sort the joint list in order from highest
25 // to lowest in the new hierarchy. Used in do_reparent().
27 public:
28  bool operator()(const EggJointData *a, const EggJointData *b) const {
29  return a->_new_parent_depth < b->_new_parent_depth;
30  }
31 };
32 
33 
34 ////////////////////////////////////////////////////////////////////
35 // Function: EggCharacterData::Constructor
36 // Access: Public
37 // Description:
38 ////////////////////////////////////////////////////////////////////
39 EggCharacterData::
40 EggCharacterData(EggCharacterCollection *collection) :
41  _component_names("_", "joint_")
42 {
43  _collection = collection;
44  _root_joint = _collection->make_joint_data(this);
45  // The fictitious root joint is not added to the _components list.
46 }
47 
48 ////////////////////////////////////////////////////////////////////
49 // Function: EggCharacterData::Destructor
50 // Access: Public, Virtual
51 // Description:
52 ////////////////////////////////////////////////////////////////////
53 EggCharacterData::
54 ~EggCharacterData() {
55  delete _root_joint;
56 
57  Sliders::iterator si;
58  for (si = _sliders.begin(); si != _sliders.end(); ++si) {
59  EggSliderData *slider = (*si);
60  delete slider;
61  }
62 }
63 
64 ////////////////////////////////////////////////////////////////////
65 // Function: EggCharacterData::rename_char
66 // Access: Public
67 // Description: Renames all of the models in the character data to
68 // the indicated name. This is the name that is used to
69 // identify unique skeleton hierarchies; if you set two
70 // different models to the same name, they will be
71 // loaded together as if they are expected to have the
72 // same skeleton hierarchy.
73 ////////////////////////////////////////////////////////////////////
75 rename_char(const string &name) {
76  Models::iterator mi;
77  for (mi = _models.begin(); mi != _models.end(); ++mi) {
78  (*mi)._model_root->set_name(name);
79  }
80 
81  set_name(name);
82 }
83 
84 ////////////////////////////////////////////////////////////////////
85 // Function: EggCharacterData::add_model
86 // Access: Public
87 // Description: Indicates that the given model_index (with the
88 // indicated model_root) is associated with this
89 // character. This is normally called by the
90 // EggCharacterCollection class as new models are
91 // discovered.
92 //
93 // A "model" here is either a character model (or one
94 // LOD of a character model), or a character animation
95 // file: in either case, a hierarchy of joints.
96 ////////////////////////////////////////////////////////////////////
98 add_model(int model_index, EggNode *model_root, EggData *egg_data) {
99  Model m;
100  m._model_index = model_index;
101  m._model_root = model_root;
102  m._egg_data = egg_data;
103  _models.push_back(m);
104 }
105 
106 ////////////////////////////////////////////////////////////////////
107 // Function: EggCharacterData::get_num_frames
108 // Access: Public
109 // Description: Returns the number of frames of animation of the
110 // indicated model. This is more reliable than asking a
111 // particular joint or slider of the animation for its
112 // number of frames, since a particular joint may have
113 // only 1 frame (if it is unanimated), even though the
114 // overall animation has many frames.
115 ////////////////////////////////////////////////////////////////////
117 get_num_frames(int model_index) const {
118  int max_num_frames = 0;
119  Components::const_iterator ci;
120  for (ci = _components.begin(); ci != _components.end(); ++ci) {
121  EggComponentData *component = (*ci);
122  int num_frames = component->get_num_frames(model_index);
123  if (num_frames > 1) {
124  // We have a winner. Assume all other components will be
125  // similar.
126  return num_frames;
127  }
128  max_num_frames = max(max_num_frames, num_frames);
129  }
130 
131  // Every component had either 1 frame or 0 frames. Return the
132  // maximum of these.
133  return max_num_frames;
134 }
135 
136 ////////////////////////////////////////////////////////////////////
137 // Function: EggCharacterData::get_frame_rate
138 // Access: Public
139 // Description: Returns the stated frame rate of the specified model.
140 // Similar to get_num_frames().
141 ////////////////////////////////////////////////////////////////////
142 double EggCharacterData::
143 get_frame_rate(int model_index) const {
144  Components::const_iterator ci;
145  for (ci = _components.begin(); ci != _components.end(); ++ci) {
146  EggComponentData *component = (*ci);
147  double frame_rate = component->get_frame_rate(model_index);
148  if (frame_rate != 0.0) {
149  // We have a winner. Assume all other components will be
150  // similar.
151  return frame_rate;
152  }
153  }
154 
155  return 0.0;
156 }
157 
158 ////////////////////////////////////////////////////////////////////
159 // Function: EggCharacterData::check_num_frames
160 // Access: Public
161 // Description: Walks through each component and ensures that all
162 // have the same number of frames of animation (except
163 // for those that contain 0 or 1 frames, of course).
164 // Returns true if all are valid, false if there is a
165 // discreprency (in which case the shorter component are
166 // extended).
167 ////////////////////////////////////////////////////////////////////
169 check_num_frames(int model_index) {
170  int max_num_frames = 0;
171  bool any_violations = false;
172  Components::const_iterator ci;
173  for (ci = _components.begin(); ci != _components.end(); ++ci) {
174  EggComponentData *component = (*ci);
175  int num_frames = component->get_num_frames(model_index);
176  if (num_frames > 1 && max_num_frames > 1 &&
177  max_num_frames != num_frames) {
178  // If we have two different opinions about the number of frames
179  // (other than 0 or 1), we have a discrepency. This is an error
180  // condition.
181  any_violations = true;
182  }
183  max_num_frames = max(max_num_frames, num_frames);
184  }
185 
186  if (any_violations) {
187  // Now go back through and force all components to the appropriate
188  // length.
189  for (ci = _components.begin(); ci != _components.end(); ++ci) {
190  EggComponentData *component = (*ci);
191  int num_frames = component->get_num_frames(model_index);
192  if (num_frames > 1 && max_num_frames != num_frames) {
193  component->extend_to(model_index, max_num_frames);
194  }
195  }
196  }
197 
198  return !any_violations;
199 }
200 
201 ////////////////////////////////////////////////////////////////////
202 // Function: EggCharacterData::do_reparent
203 // Access: Public
204 // Description: Begins the process of restructuring the joint
205 // hierarchy according to the previous calls to
206 // reparent_to() on various joints. This will reparent
207 // the joint hierachy in all models as requested, while
208 // adjusting the transforms as appropriate so that each
209 // joint retains the same net transform across all
210 // frames that it had before the operation. Returns
211 // true on success, false on failure.
212 ////////////////////////////////////////////////////////////////////
215  typedef pset<EggJointData *> InvalidSet;
216  InvalidSet invalid_set;
217 
218  // To begin, make sure the list of new_children is accurate.
219  Joints::const_iterator ji;
220  for (ji = _joints.begin(); ji != _joints.end(); ++ji) {
221  EggJointData *joint_data = (*ji);
222  joint_data->do_begin_reparent();
223  }
224  // We also need to clear the children on the root joint, but the
225  // root joint doesn't get any of the other operations (including
226  // finish_reparent) applied to it.
227  _root_joint->do_begin_reparent();
228 
229 
230  // Now, check for cycles in the new parenting hierarchy, and also
231  // sort the joints in order from top to bottom in the new hierarchy.
232  for (ji = _joints.begin(); ji != _joints.end(); ++ji) {
233  EggJointData *joint_data = (*ji);
234  pset<EggJointData *> chain;
235  if (joint_data->calc_new_parent_depth(chain)) {
236  nout << "Cycle detected in parent chain for " << joint_data->get_name()
237  << "!\n";
238  return false;
239  }
240  }
241  sort(_joints.begin(), _joints.end(), OrderJointsByNewDepth());
242 
243  // Now compute the new transforms for the joints' new positions.
244  // This is done recursively through the new parent hierarchy, so we
245  // can take advantage of caching the net value for a particular
246  // frame.
247  Models::const_iterator mi;
248  for (mi = _models.begin(); mi != _models.end(); ++mi) {
249  EggCharacterDb db;
250  int model_index = (*mi)._model_index;
251  int num_frames = get_num_frames(model_index);
252  nout << " computing " << (mi - _models.begin()) + 1
253  << " of " << _models.size()
254  << ": " << (*mi)._egg_data->get_egg_filename()
255  << " (" << num_frames << " frames)\n";
256  for (int f = 0; f < num_frames; f++) {
257  // First, walk through all the joints and flush the computed net
258  // transforms from before.
259  for (ji = _joints.begin(); ji != _joints.end(); ++ji) {
260  EggJointData *joint_data = (*ji);
261  joint_data->do_begin_compute_reparent();
262  }
263  _root_joint->do_begin_compute_reparent();
264 
265  // Now go back through and compute the reparented transforms,
266  // caching net transforms as necessary.
267  for (ji = _joints.begin(); ji != _joints.end(); ++ji) {
268  EggJointData *joint_data = (*ji);
269  if (!joint_data->do_compute_reparent(model_index, f, db)) {
270  // Oops, we got an invalid transform.
271  invalid_set.insert(joint_data);
272  }
273  }
274  }
275 
276  // Finally, apply the computations to the joints.
277  for (ji = _joints.begin(); ji != _joints.end(); ++ji) {
278  EggJointData *joint_data = (*ji);
279  if (!joint_data->do_joint_rebuild(model_index, db)) {
280  invalid_set.insert(joint_data);
281  }
282  }
283  }
284 
285  // Now remove all of the old children and add in the new children.
286  for (ji = _joints.begin(); ji != _joints.end(); ++ji) {
287  EggJointData *joint_data = (*ji);
288  joint_data->do_finish_reparent();
289  }
290 
291  // Report the set of joints that failed. It really shouldn't be
292  // possible for any joints to fail, so if you see anything reported
293  // here, something went wrong at a fundamental level. Perhaps a
294  // problem with decompose_matrix().
295  InvalidSet::const_iterator si;
296  for (si = invalid_set.begin(); si != invalid_set.end(); ++si) {
297  EggJointData *joint_data = (*si);
298  // Don't bother reporting joints that no longer have a parent,
299  // since we don't care about joints that are now outside the
300  // hierarchy.
301  if (joint_data->get_parent() != (EggJointData *)NULL) {
302  nout << "Warning: reparenting " << joint_data->get_name()
303  << " to ";
304  if (joint_data->get_parent() == _root_joint) {
305  nout << "the root";
306  } else {
307  nout << joint_data->get_parent()->get_name();
308  }
309  nout << " results in an invalid transform.\n";
310  }
311  }
312 
313  return invalid_set.empty();
314 }
315 
316 ////////////////////////////////////////////////////////////////////
317 // Function: EggCharacterData::choose_optimal_hierarchy
318 // Access: Public
319 // Description: Chooses the best possible parent joint for each of
320 // the joints in the hierarchy, based on the score
321 // computed by EggJointData::score_reparent_to(). This
322 // is a fairly expensive operation that involves lots of
323 // recomputing of transforms across the hierarchy.
324 //
325 // The joints are not actually reparented yet, but the
326 // new_parent of each joint is set. Call do_reparent()
327 // to actually perform the suggested reparenting
328 // operation.
329 ////////////////////////////////////////////////////////////////////
332  EggCharacterDb db;
333 
334  Joints::const_iterator ji, jj;
335  for (ji = _joints.begin(); ji != _joints.end(); ++ji) {
336  EggJointData *joint_data = (*ji);
337 
338  EggJointData *best_parent = joint_data->get_parent();
339  int best_score = joint_data->score_reparent_to(best_parent, db);
340 
341  for (jj = _joints.begin(); jj != _joints.end(); ++jj) {
342  EggJointData *possible_parent = (*jj);
343  if (possible_parent != joint_data && possible_parent != best_parent &&
344  !joint_data->is_new_ancestor(possible_parent)) {
345 
346  int score = joint_data->score_reparent_to(possible_parent, db);
347  if (score >= 0 && (best_score < 0 || score < best_score)) {
348  best_parent = possible_parent;
349  best_score = score;
350  }
351  }
352  }
353 
354  // Also consider reparenting the node to the root.
355  EggJointData *possible_parent = get_root_joint();
356  if (possible_parent != best_parent) {
357  int score = joint_data->score_reparent_to(possible_parent, db);
358  if (score >= 0 && (best_score < 0 || score < best_score)) {
359  best_parent = possible_parent;
360  best_score = score;
361  }
362  }
363 
364  if (best_parent != (EggJointData *)NULL &&
365  best_parent != joint_data->_parent) {
366  nout << "best parent for " << joint_data->get_name() << " is "
367  << best_parent->get_name() << "\n";
368  joint_data->reparent_to(best_parent);
369  }
370  }
371 }
372 
373 ////////////////////////////////////////////////////////////////////
374 // Function: EggCharacterData::find_slider
375 // Access: Public
376 // Description: Returns the slider with the indicated name, or NULL
377 // if no slider has that name.
378 ////////////////////////////////////////////////////////////////////
380 find_slider(const string &name) const {
381  SlidersByName::const_iterator si;
382  si = _sliders_by_name.find(name);
383  if (si != _sliders_by_name.end()) {
384  return (*si).second;
385  }
386 
387  return NULL;
388 }
389 
390 ////////////////////////////////////////////////////////////////////
391 // Function: EggCharacterData::make_slider
392 // Access: Public
393 // Description: Returns the slider matching the indicated name. If
394 // no such slider exists already, creates a new one.
395 ////////////////////////////////////////////////////////////////////
397 make_slider(const string &name) {
398  SlidersByName::const_iterator si;
399  si = _sliders_by_name.find(name);
400  if (si != _sliders_by_name.end()) {
401  return (*si).second;
402  }
403 
404  EggSliderData *slider = _collection->make_slider_data(this);
405  slider->set_name(name);
406  _sliders_by_name.insert(SlidersByName::value_type(name, slider));
407  _sliders.push_back(slider);
408  _components.push_back(slider);
409  return slider;
410 }
411 
412 ////////////////////////////////////////////////////////////////////
413 // Function: EggCharacterData::estimate_db_size
414 // Access: Public
415 // Description: Returns the estimated amount of memory, in megabytes,
416 // that will be required to perform the do_reparent()
417 // operation. This is used mainly be EggCharacterDb to
418 // decide up front whether to store this data in-RAM or
419 // on-disk.
420 ////////////////////////////////////////////////////////////////////
421 size_t EggCharacterData::
423  // Count how much memory we will need to store the interim
424  // transforms. This is models * joints * frames * 3 *
425  // sizeof(LMatrix4d).
426  size_t mj_frames = 0;
427  Models::const_iterator mi;
428  for (mi = _models.begin(); mi != _models.end(); ++mi) {
429  int model_index = (*mi)._model_index;
430  size_t num_frames = (size_t)get_num_frames(model_index);
431  mj_frames += num_frames * _joints.size();
432  }
433 
434  // We do this operation a bit carefully, to guard against integer
435  // overflow.
436  size_t mb_needed = ((mj_frames * 3 / 1024) * sizeof(LMatrix4d)) / 1024;
437 
438  return mb_needed;
439 }
440 
441 
442 ////////////////////////////////////////////////////////////////////
443 // Function: EggCharacterData::write
444 // Access: Public, Virtual
445 // Description:
446 ////////////////////////////////////////////////////////////////////
447 void EggCharacterData::
448 write(ostream &out, int indent_level) const {
449  indent(out, indent_level)
450  << "Character " << get_name() << ":\n";
451  get_root_joint()->write(out, indent_level + 2);
452 
453  Sliders::const_iterator si;
454  for (si = _sliders.begin(); si != _sliders.end(); ++si) {
455  EggSliderData *slider = (*si);
456  slider->write(out, indent_level + 2);
457  }
458 }
void reparent_to(EggJointData *new_parent)
Indicates an intention to change the parent of this joint to the indicated joint, or NULL to remove i...
Definition: eggJointData.I:112
int get_num_frames(int model_index) const
Returns the number of frames of animation for this particular component in the indicated model...
EggSliderData * make_slider(const string &name)
Returns the slider matching the indicated name.
This is a 4-by-4 transform matrix.
Definition: lmatrix.h:4716
bool do_reparent()
Begins the process of restructuring the joint hierarchy according to the previous calls to reparent_t...
int get_num_frames(int model_index) const
Returns the number of frames of animation of the indicated model.
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 * find_slider(const string &name) const
Returns the slider with the indicated name, or NULL if no slider has that name.
void extend_to(int model_index, int num_frames) const
Extends the number of frames in the indicated model (presumably an animation table model) to the give...
void rename_char(const string &name)
Renames all of the models in the character data to the indicated name.
This corresponds to a single morph slider control.
Definition: eggSliderData.h:31
This is the primary interface into all the egg data, and the root of the egg file structure...
Definition: eggData.h:41
This is the base class of both EggJointData and EggSliderData.
This class is used during joint optimization or restructuring to store the table of interim joint com...
Represents a set of characters, as read and collected from possibly several model and/or animation eg...
void choose_optimal_hierarchy()
Chooses the best possible parent joint for each of the joints in the hierarchy, based on the score co...
int score_reparent_to(EggJointData *new_parent, EggCharacterDb &db)
Computes a score >= 0 reflecting the similarity of the current joint&#39;s animation (in world space) to ...
This is one node of a hierarchy of EggJointData nodes, each of which represents a single joint of the...
Definition: eggJointData.h:34
double get_frame_rate(int model_index) const
Returns the number of frames of animation for this particular component in the indicated model...
A base class for things that may be directly added into the egg hierarchy.
Definition: eggNode.h:38
This is our own Panda specialization on the default STL set.
Definition: pset.h:52
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...
double get_frame_rate(int model_index) const
Returns the stated frame rate of the specified model.
size_t estimate_db_size() const
Returns the estimated amount of memory, in megabytes, that will be required to perform the do_reparen...
virtual EggJointData * make_joint_data(EggCharacterData *char_data)
Allocates and returns a new EggJointData structure for the given character.