15 #include "eggCharacterData.h"
16 #include "eggCharacterCollection.h"
17 #include "eggCharacterDb.h"
18 #include "eggJointData.h"
19 #include "eggSliderData.h"
29 return a->_new_parent_depth < b->_new_parent_depth;
41 _component_names(
"_",
"joint_")
43 _collection = collection;
58 for (si = _sliders.begin(); si != _sliders.end(); ++si) {
77 for (mi = _models.begin(); mi != _models.end(); ++mi) {
78 (*mi)._model_root->set_name(name);
100 m._model_index = model_index;
101 m._model_root = model_root;
102 m._egg_data = egg_data;
103 _models.push_back(m);
118 int max_num_frames = 0;
119 Components::const_iterator ci;
120 for (ci = _components.begin(); ci != _components.end(); ++ci) {
123 if (num_frames > 1) {
128 max_num_frames = max(max_num_frames, num_frames);
133 return max_num_frames;
144 Components::const_iterator ci;
145 for (ci = _components.begin(); ci != _components.end(); ++ci) {
148 if (frame_rate != 0.0) {
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) {
176 if (num_frames > 1 && max_num_frames > 1 &&
177 max_num_frames != num_frames) {
181 any_violations =
true;
183 max_num_frames = max(max_num_frames, num_frames);
186 if (any_violations) {
189 for (ci = _components.begin(); ci != _components.end(); ++ci) {
192 if (num_frames > 1 && max_num_frames != num_frames) {
193 component->
extend_to(model_index, max_num_frames);
198 return !any_violations;
216 InvalidSet invalid_set;
219 Joints::const_iterator ji;
220 for (ji = _joints.begin(); ji != _joints.end(); ++ji) {
222 joint_data->do_begin_reparent();
227 _root_joint->do_begin_reparent();
232 for (ji = _joints.begin(); ji != _joints.end(); ++ji) {
235 if (joint_data->calc_new_parent_depth(chain)) {
236 nout <<
"Cycle detected in parent chain for " << joint_data->get_name()
247 Models::const_iterator mi;
248 for (mi = _models.begin(); mi != _models.end(); ++mi) {
250 int model_index = (*mi)._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++) {
259 for (ji = _joints.begin(); ji != _joints.end(); ++ji) {
261 joint_data->do_begin_compute_reparent();
263 _root_joint->do_begin_compute_reparent();
267 for (ji = _joints.begin(); ji != _joints.end(); ++ji) {
269 if (!joint_data->do_compute_reparent(model_index, f, db)) {
271 invalid_set.insert(joint_data);
277 for (ji = _joints.begin(); ji != _joints.end(); ++ji) {
279 if (!joint_data->do_joint_rebuild(model_index, db)) {
280 invalid_set.insert(joint_data);
286 for (ji = _joints.begin(); ji != _joints.end(); ++ji) {
288 joint_data->do_finish_reparent();
295 InvalidSet::const_iterator si;
296 for (si = invalid_set.begin(); si != invalid_set.end(); ++si) {
302 nout <<
"Warning: reparenting " << joint_data->get_name()
304 if (joint_data->get_parent() == _root_joint) {
307 nout << joint_data->get_parent()->get_name();
309 nout <<
" results in an invalid transform.\n";
313 return invalid_set.empty();
334 Joints::const_iterator ji, jj;
335 for (ji = _joints.begin(); ji != _joints.end(); ++ji) {
341 for (jj = _joints.begin(); jj != _joints.end(); ++jj) {
343 if (possible_parent != joint_data && possible_parent != best_parent &&
344 !joint_data->is_new_ancestor(possible_parent)) {
347 if (score >= 0 && (best_score < 0 || score < best_score)) {
348 best_parent = possible_parent;
356 if (possible_parent != best_parent) {
358 if (score >= 0 && (best_score < 0 || score < best_score)) {
359 best_parent = possible_parent;
365 best_parent != joint_data->_parent) {
366 nout <<
"best parent for " << joint_data->get_name() <<
" is "
367 << best_parent->get_name() <<
"\n";
381 SlidersByName::const_iterator si;
382 si = _sliders_by_name.find(name);
383 if (si != _sliders_by_name.end()) {
398 SlidersByName::const_iterator si;
399 si = _sliders_by_name.find(name);
400 if (si != _sliders_by_name.end()) {
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);
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;
431 mj_frames += num_frames * _joints.size();
436 size_t mb_needed = ((mj_frames * 3 / 1024) *
sizeof(
LMatrix4d)) / 1024;
447 void EggCharacterData::
448 write(ostream &out,
int indent_level)
const {
449 indent(out, indent_level)
450 <<
"Character " << get_name() <<
":\n";
453 Sliders::const_iterator si;
454 for (si = _sliders.begin(); si != _sliders.end(); ++si) {
456 slider->write(out, indent_level + 2);
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...
EggSliderData * make_slider(const string &name)
Returns the slider matching the indicated name.
This is a 4-by-4 transform matrix.
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.
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...
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 >= 0 reflecting the similarity of the current joint'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...
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.
This is our own Panda specialization on the default STL set.
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.