15 #include "eggJointData.h" 16 #include "eggJointNodePointer.h" 17 #include "eggMatrixTablePointer.h" 23 #include "fftCompressor.h" 41 _has_rest_frame =
false;
42 _rest_frames_differ =
false;
62 return joint->get_frame(n);
83 if (!db.
get_matrix(joint, EggCharacterDb::TT_net_frame, n, mat)) {
89 db.
set_matrix(joint, EggCharacterDb::TT_net_frame, n, mat);
111 if (!db.
get_matrix(joint, EggCharacterDb::TT_net_frame_inv, n, mat)) {
115 db.
set_matrix(joint, EggCharacterDb::TT_net_frame_inv, n, mat);
136 for (
int model_index = 0; model_index < num_models; model_index++) {
139 DCAST_INTO_V(joint,
get_model(model_index));
140 if (joint->
is_of_type(EggJointNodePointer::get_class_type())) {
145 _rest_frames_differ =
false;
160 for (
int model_index = 0; model_index < num_models; model_index++) {
163 DCAST_INTO_V(joint,
get_model(model_index));
168 for (
int model_index = 0; model_index < num_models; model_index++) {
171 DCAST_INTO_V(joint,
get_model(model_index));
172 DCAST_INTO_V(new_joint, new_owner->
get_model(model_index));
201 vector_stdfloat i, j, k, a, b, c, x, y, z;
206 for (
int model_index = 0; model_index < num_models; model_index++) {
210 DCAST_INTO_R(joint, back,
false);
213 for (
int n = 0; n < num_frames; n++) {
215 if (_parent == new_parent) {
234 transform = joint->get_frame(n) * transform;
236 if (!decompose_matrix(transform, scale, shear, hpr, translate)) {
240 i.push_back(scale[0]);
241 j.push_back(scale[1]);
242 k.push_back(scale[2]);
243 a.push_back(shear[0]);
244 b.push_back(shear[1]);
245 c.push_back(shear[2]);
246 hprs.push_back(LCAST(PN_stdfloat, hpr));
247 x.push_back(translate[0]);
248 y.push_back(translate[1]);
249 z.push_back(translate[2]);
271 compressor.
write_hprs(dg, &hprs[0], num_rows);
285 OCompressStream zstr(&sstr,
false);
288 return sstr.str().length();
303 BackPointers::iterator bpi;
304 for (bpi = _back_pointers.begin(); bpi != _back_pointers.end(); ++bpi) {
308 DCAST_INTO_R(joint, back,
false);
315 Children::iterator ci;
316 for (ci = _children.begin(); ci != _children.end(); ++ci) {
334 BackPointers::iterator bpi;
335 for (bpi = _back_pointers.begin(); bpi != _back_pointers.end(); ++bpi) {
339 DCAST_INTO_V(joint, back);
344 Children::iterator ci;
345 for (ci = _children.begin(); ci != _children.end(); ++ci) {
359 BackPointers::iterator bpi;
360 for (bpi = _back_pointers.begin(); bpi != _back_pointers.end(); ++bpi) {
364 DCAST_INTO_V(joint, back);
378 BackPointers::iterator bpi;
379 for (bpi = _back_pointers.begin(); bpi != _back_pointers.end(); ++bpi) {
383 DCAST_INTO_V(joint, back);
397 BackPointers::iterator bpi;
398 for (bpi = _back_pointers.begin(); bpi != _back_pointers.end(); ++bpi) {
402 DCAST_INTO_V(joint, back);
407 Children::iterator ci;
408 for (ci = _children.begin(); ci != _children.end(); ++ci) {
426 DCAST_INTO_V(source_joint, _back_pointers[source_model]);
427 BackPointers::iterator bpi;
428 for (bpi = _back_pointers.begin(); bpi != _back_pointers.end(); ++bpi) {
432 DCAST_INTO_V(joint, back);
438 Children::iterator ci;
439 for (ci = _children.begin(); ci != _children.end(); ++ci) {
453 nassertv(egg_object != (
EggObject *)NULL);
454 if (egg_object->
is_of_type(EggGroup::get_class_type())) {
458 if (!_has_rest_frame) {
460 _has_rest_frame =
true;
467 _rest_frames_differ =
true;
471 }
else if (egg_object->
is_of_type(EggTable::get_class_type())) {
477 nout <<
"Invalid object added to joint for back pointer.\n";
487 write(ostream &out,
int indent_level)
const {
488 indent(out, indent_level)
489 <<
"Joint " << get_name()
492 for (
int model_index = 0; model_index < num_models; model_index++) {
494 out <<
" " << model_index;
499 Children::const_iterator ci;
500 for (ci = _children.begin(); ci != _children.end(); ++ci) {
501 (*ci)->write(out, indent_level + 2);
504 indent(out, indent_level) <<
"}\n";
514 do_begin_reparent() {
515 _got_new_parent_depth =
false;
537 if (_got_new_parent_depth) {
542 _got_new_parent_depth =
true;
543 _new_parent_depth = 0;
546 if (!chain.insert(
this).second) {
550 bool cycle = _new_parent->calc_new_parent_depth(chain);
551 _new_parent_depth = _new_parent->_new_parent_depth + 1;
563 do_begin_compute_reparent() {
564 _got_new_net_frame =
false;
565 _got_new_net_frame_inv =
false;
566 _computed_reparent =
false;
580 if (_computed_reparent) {
586 _computed_reparent =
true;
588 if (_parent == _new_parent) {
603 DCAST_INTO_R(joint, back,
false);
608 transform = _new_parent->get_new_net_frame_inv(model_index, n, db);
618 _new_parent->get_new_net_frame_inv(model_index, n, db);
621 db.
set_matrix(joint, EggCharacterDb::TT_rebuild_frame, n,
622 joint->get_frame(n) * transform);
640 if (_new_parent != NULL && _new_parent->
has_model(model_index)) {
641 DCAST_INTO_R(parent_joint, _new_parent->
get_model(model_index),
false);
646 DCAST_INTO_R(joint,
get_model(model_index),
false);
663 do_finish_reparent() {
665 for (
int model_index = 0; model_index < num_models; model_index++) {
667 if (_new_parent != NULL && _new_parent->
has_model(model_index)) {
668 DCAST_INTO_V(parent_joint, _new_parent->
get_model(model_index));
673 DCAST_INTO_V(joint,
get_model(model_index));
674 joint->do_finish_reparent(parent_joint);
678 _parent = _new_parent;
680 _parent->_children.push_back(
this);
692 make_new_joint(
const string &name) {
694 child->set_name(name);
695 child->_parent =
this;
696 child->_new_parent =
this;
697 _children.push_back(child);
701 for (
int i = 0; i < num_models; i++) {
721 find_joint_exact(
const string &name) {
722 Children::const_iterator ci;
723 for (ci = _children.begin(); ci != _children.end(); ++ci) {
725 if (child->get_name() == name) {
744 find_joint_matches(
const string &name) {
745 Children::const_iterator ci;
746 for (ci = _children.begin(); ci != _children.end(); ++ci) {
778 return is_new_ancestor(child->_new_parent);
791 if (!_got_new_net_frame) {
792 _new_net_frame = get_new_frame(model_index, n, db);
794 _new_net_frame = _new_net_frame * _new_parent->get_new_net_frame(model_index, n, db);
796 _got_new_net_frame =
true;
798 return _new_net_frame;
807 get_new_net_frame_inv(
int model_index,
int n,
EggCharacterDb &db) {
808 if (!_got_new_net_frame_inv) {
809 _new_net_frame_inv.
invert_from(get_new_frame(model_index, n, db));
811 _new_net_frame_inv = _new_parent->get_new_net_frame_inv(model_index, n, db) * _new_net_frame_inv;
813 _got_new_net_frame_inv =
true;
815 return _new_net_frame_inv;
828 do_compute_reparent(model_index, n, db);
839 if (!db.
get_matrix(joint, EggCharacterDb::TT_rebuild_frame, n, mat)) {
841 return joint->get_frame(n);
virtual void quantize_channels(const string &components, double quantum)
Rounds the named components of the transform to the nearest multiple of quantum.
virtual void optimize()
Resets the table before writing to disk so that redundant rows (e.g.
int get_num_frames(int model_index) const
Returns the number of frames of animation for this particular component in the indicated model...
void set_model(int model_index, EggBackPointer *back)
Sets the back_pointer associated with the given model_index.
This is a 4-by-4 transform matrix.
void optimize()
Calls optimize() on all models, and recursively on all joints at this node and below.
bool almost_equal(const LMatrix4d &other, double threshold) const
Returns true if two matrices are memberwise equal within a specified tolerance.
virtual LMatrix4d get_frame(int n) const
Returns the transform matrix corresponding to this joint position in the nth frame.
int get_num_models() const
Returns the maximum number of back pointers this component may have.
void zero_channels(const string &components)
Calls zero_channels() on all models for this joint, but does not recurse downwards.
virtual void zero_channels(const string &components)
Zeroes out the named components of the transform in the animation frames.
EggBackPointer * get_model(int model_index) const
Returns the back pointer to an egg file for the indicated model if it exists, or NULL if it does not...
This class manages a lossy compression and decompression of a stream of floating-point numbers to a d...
This is the base class of both EggJointData and EggSliderData.
LMatrix4d get_net_frame_inv(int model_index, int n, EggCharacterDb &db) const
Returns the inverse of get_net_frame().
This is our own Panda specialization on the default STL vector.
void quantize_channels(const string &components, double quantum)
Calls quantize_channels() on all models for this joint, and then recurses downwards to all joints bel...
void apply_default_pose(int source_model, int frame)
Applies the pose from the indicated frame of the indicated source model_index as the initial pose for...
virtual void move_vertices_to(EggJointPointer *new_joint)
Moves the vertices assigned to this joint into the other joint (which should be of the same type)...
This stores a pointer back to a <Joint> node.
This class is used during joint optimization or restructuring to store the table of interim joint com...
static const LMatrix4d & ident_mat()
Returns an identity matrix.
bool invert_in_place()
Inverts the current matrix.
bool has_rest_frame() const
Returns true if the joint knows its rest frame, false otherwise.
void set_matrix(const EggJointPointer *joint, TableType type, int frame, const LMatrix4d &mat)
Stores the matrix for the indicated joint, type, and frame in the database.
LMatrix4d get_net_frame(int model_index, int n, EggCharacterDb &db) const
Returns the complete transform from the root corresponding to this joint position in the nth frame in...
virtual void apply_default_pose(EggJointPointer *source_joint, int frame)
Applies the pose from the indicated frame of the indicated source joint as the initial pose for this ...
This is a base class for EggJointNodePointer and EggMatrixTablePointer.
bool invert_from(const LMatrix4d &other)
Computes the inverse of the other matrix, and stores the result in this matrix.
void move_vertices_to(EggJointData *new_owner)
Moves the vertices assigned to this joint into the indicated joint, without changing their weight ass...
Represents a set of characters, as read and collected from possibly several model and/or animation eg...
bool matches_name(const string &name) const
Returns true if the indicated name matches any name that was ever matched with this particular joint...
This is the base class for all three-component vectors and points.
bool has_model(int model_index) const
Returns true if the component has a back pointer to an egg file somewhere for the indicated model...
Represents a single character, as read and collected from several models and animation files...
void write_reals(Datagram &datagram, const PN_stdfloat *array, int length)
Writes an array of floating-point numbers to the indicated datagram.
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 ...
const LMatrix4d & get_rest_frame() const
Returns the rest frame of the joint.
This is one node of a hierarchy of EggJointData nodes, each of which represents a single joint of the...
virtual bool do_rebuild(EggCharacterDb &db)
Rebuilds the entire table all at once, based on the frames added by repeated calls to add_rebuild_fra...
virtual void add_back_pointer(int model_index, EggObject *egg_object)
Adds the indicated model joint or anim table to the data.
This stores a pointer back to an EggXfmSAnim table (i.e.
void force_initial_rest_frame()
Forces all of the joints to have the same rest frame value as the first joint read in...
LMatrix4d get_frame(int model_index, int n) const
Returns the local transform matrix corresponding to this joint position in the nth frame in the indic...
void write_hprs(Datagram &datagram, const LVecBase3 *array, int length)
Writes an array of HPR angles to the indicated datagram.
virtual void expose(EggGroup::DCSType dcs_type)
Flags the joint with the indicated DCS flag so that it will be loaded as a separate node in the playe...
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
bool do_rebuild_all(EggCharacterDb &db)
Calls do_rebuild() on all models, and recursively on all joints at this node and below.
This is our own Panda specialization on the default STL set.
TypeHandle is the identifier used to differentiate C++ class types.
This stores a pointer from an EggJointData or EggSliderData object back to the referencing data in an...
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
void expose(EggGroup::DCSType dcs_type=EggGroup::DC_default)
Calls expose() on all models for this joint, but does not recurse downwards.
The highest-level base class in the egg directory.
bool get_matrix(const EggJointPointer *joint, TableType type, int frame, LMatrix4d &mat) const
Looks up the data for the indicated joint, type, and frame, and fills it in result (and returns true)...
static bool is_compression_available()
Returns true if the FFTW library is compiled in, so that this class is actually capable of doing usef...
size_t get_length() const
Returns the number of bytes in the datagram.
const void * get_data() const
Returns a pointer to the beginning of the datagram's data.