Panda3D
 All Classes Functions Variables Enumerations
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
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...
bool check_num_frames(int model_index)
Walks through each component and ensures that all have the same number of frames of animation (except...
size_t estimate_db_size() const
Returns the estimated amount of memory, in megabytes, that will be required to perform the do_reparen...
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...
double get_frame_rate(int model_index) const
Returns the stated frame rate of the specified model.
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
int get_num_frames(int model_index) const
Returns the number of frames of animation for this particular component in the indicated model...
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...
EggJointData * get_root_joint() const
Returns the root joint of the character hierarchy.
Represents a set of characters, as read and collected from possibly several model and/or animation eg...
EggSliderData * find_slider(const string &name) const
Returns the slider with the indicated name, or NULL if no slider has that name.
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 &gt;= 0 reflecting the similarity of the current joint&#39;s animation (in world space) to t...
This is one node of a hierarchy of EggJointData nodes, each of which represents a single joint of the...
Definition: eggJointData.h:34
virtual EggSliderData * make_slider_data(EggCharacterData *char_data)
Allocates and returns a new EggSliderData structure for the given character.
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
double get_frame_rate(int model_index) const
Returns the number of frames of animation for this particular component in the indicated 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...
int get_num_frames(int model_index) const
Returns the number of frames of animation of the indicated model.
virtual EggJointData * make_joint_data(EggCharacterData *char_data)
Allocates and returns a new EggJointData structure for the given character.