15 #include "eggXfmSAnim.h"
16 #include "eggSAnimData.h"
17 #include "eggXfmAnimData.h"
18 #include "eggParameters.h"
19 #include "config_egg.h"
22 #include "compose_matrix.h"
34 const string EggXfmSAnim::_standard_order_legacy =
"sphrt";
35 const string EggXfmSAnim::_standard_order_hpr_fix =
"srpht";
51 if (convert_from.has_order()) {
52 set_order(convert_from.get_order());
54 if (convert_from.has_fps()) {
55 set_fps(convert_from.
get_fps());
58 const string &contents = convert_from.get_contents();
59 for (
int col = 0; col < convert_from.
get_num_cols(); col++) {
62 for (
int row = 0; row < convert_from.
get_num_rows(); row++) {
76 iterator ci = begin();
78 iterator ci_next = ci;
81 if ((*ci)->is_of_type(EggSAnimData::get_class_type())) {
90 if (sanim->
has_name() && strchr(
"ijk", sanim->get_name()[0]) != NULL) {
96 if (fabs(value - default_value) < egg_parameters->_table_threshold) {
120 normalize_by_rebuilding();
140 normalize_by_rebuilding();
146 normalize_by_expanding();
168 write(ostream &out,
int indent_level)
const {
169 test_under_integrity();
174 indent(out, indent_level + 2) <<
"<Scalar> fps { " <<
get_fps() <<
" }\n";
178 indent(out, indent_level + 2)
179 <<
"<Char*> order { " << get_order() <<
" }\n";
188 memset(tables, 0,
sizeof(
EggSAnimData *) * num_matrix_components);
191 for (ci = begin(); ci != end(); ++ci) {
193 if (child->
is_of_type(EggSAnimData::get_class_type())) {
197 nassertv(sanim->get_name().length() == 1);
198 char name = sanim->get_name()[0];
199 char *p = (
char *)strchr(matrix_component_letters, name);
200 nassertv(p != (
char *)NULL);
201 if (p != (
char *)NULL) {
202 int index = p - matrix_component_letters;
204 tables[index] = sanim;
208 child->write(out, indent_level + 2);
213 for (
int i = 0; i < num_matrix_components; i++) {
215 tables[i]->
write(out, indent_level + 2);
219 indent(out, indent_level) <<
"}\n";
238 CoordinateSystem cs) {
242 bool reverse_roll =
false;
244 if (order ==
"sphrt" && egg_support_old_anims) {
251 string::const_iterator pi;
252 for (pi = order.begin(); pi != order.end(); ++pi) {
280 <<
"Invalid letter in order string: " << *pi <<
"\n";
296 bool found_any =
false;
300 for (ci = begin(); ci != end(); ++ci) {
301 if ((*ci)->is_of_type(EggSAnimData::get_class_type())) {
336 for (ci = begin(); ci != end(); ++ci) {
337 if ((*ci)->is_of_type(EggSAnimData::get_class_type())) {
355 nassertv(sanim->get_name().length() == 1);
357 switch (sanim->get_name()[0]) {
395 translate[0] = value;
399 translate[1] = value;
403 translate[2] = value;
436 double components[num_matrix_components];
437 bool add_ok = decompose_matrix(mat, components, _coordsys);
441 int table_length = -1;
444 for (
int i = 0; i < num_matrix_components; i++) {
445 string name(1, matrix_component_letters[i]);
447 nassertr(child != (
EggNode *)NULL &&
448 child->
is_of_type(EggSAnimData::get_class_type()),
false);
453 if (table_length < 0) {
454 table_length = sanim->get_num_rows();
456 nassertr(sanim->get_num_rows() == table_length,
false);
459 sanim->set_value(row, components[i]);
468 <<
"After set_row(" << row <<
", ...) to:\n";
469 mat.write(egg_cat.warning(
false), 2);
470 egg_cat.warning(
false)
471 <<
"which produces components:\n";
472 for (
int i = 0; i < num_matrix_components; i += 3) {
473 egg_cat.warning(
false)
475 << matrix_component_letters[i]
476 << matrix_component_letters[i + 1]
477 << matrix_component_letters[i + 2]
479 << components[i] <<
" "
480 << components[i + 1] <<
" "
481 << components[i + 2] <<
"\n";
483 egg_cat.warning(
false)
484 <<
"new mat set was:\n";
485 new_mat.write(egg_cat.warning(
false), 2);
526 double components[num_matrix_components];
527 bool add_ok = decompose_matrix(mat, components, _coordsys);
531 for (
int i = 0; i < num_matrix_components; i++) {
532 char name = matrix_component_letters[i];
544 int table_length = -1;
547 for (
int i = 0; i < num_matrix_components; i++) {
548 string name(1, matrix_component_letters[i]);
550 nassertr(child != (
EggNode *)NULL &&
551 child->
is_of_type(EggSAnimData::get_class_type()),
false);
556 if (table_length < 0) {
557 table_length = sanim->get_num_rows();
559 nassertr(sanim->get_num_rows() == table_length,
false);
562 sanim->add_data(components[i]);
568 if (table_length >= 0) {
575 <<
"After add_data():\n";
576 mat.write(egg_cat.warning(
false), 2);
577 egg_cat.warning(
false)
578 <<
"which produces components:\n";
579 for (
int i = 0; i < num_matrix_components; i += 3) {
580 egg_cat.warning(
false)
582 << matrix_component_letters[i]
583 << matrix_component_letters[i + 1]
584 << matrix_component_letters[i + 2]
586 << components[i] <<
" "
587 << components[i + 1] <<
" "
588 << components[i + 2] <<
"\n";
590 egg_cat.warning(
false)
591 <<
"new mat set was:\n";
592 new_mat.write(egg_cat.warning(
false), 2);
610 if (child == (
EggNode *)NULL) {
616 DCAST_INTO_V(sanim, child);
630 nassertv(component >= 0 && component < num_matrix_components);
632 string name(1, matrix_component_letters[component]);
646 CoordinateSystem to_cs) {
658 if (to_cs != CS_default) {
664 for (
int r = 0; r < num_rows; r++) {
666 bool result =
add_data(inv1 * orig_mat * mat);
688 r_mark_coordsys(CoordinateSystem cs) {
703 normalize_by_rebuilding() {
712 for (
int r = 0; r < num_rows; r++) {
734 normalize_by_expanding() {
740 int table_length = 1;
741 string remaining_tables = matrix_component_letters;
743 for (ci = begin(); ci != end(); ++ci) {
744 if ((*ci)->is_of_type(EggSAnimData::get_class_type())) {
747 nassertv(sanim->get_name().length() == 1);
748 char name = sanim->get_name()[0];
749 size_t p = remaining_tables.find(name);
750 nassertv(p != string::npos);
751 remaining_tables[p] =
' ';
755 if (table_length == 1) {
764 if (num_tables < num_matrix_components) {
766 for (
size_t p = 0; p < remaining_tables.length(); p++) {
767 if (remaining_tables[p] !=
' ') {
768 double default_value;
769 switch (remaining_tables[p]) {
780 string name(1, remaining_tables[p]);
789 for (ci = begin(); ci != end(); ++ci) {
790 if ((*ci)->is_of_type(EggSAnimData::get_class_type())) {
794 for (
int i = 1; i < table_length; i++) {
void optimize()
Optimizes the data by collapsing a long table of duplicate values into a single value.
bool add_data(const LMatrix4d &mat)
Adds a new matrix to the table, by adding a new row to each of the subtables.
This is a 4-by-4 transform matrix.
void add_data(double value)
Adds a single element to the table.
void write_header(ostream &out, int indent_level, const char *egg_keyword) const
Writes the first line of the egg object, e.g.
void add_component_data(const string &component_name, double value)
Adds a new row to the named component (one of matrix_component_letters) of the table.
A base class for nodes in the hierarchy that are not leaf nodes.
int get_num_cols() const
Returns the number of columns in the table.
void normalize()
The inverse operation of optimize(), this ensures that all the sub-tables have the same length by dup...
double get_value(int row, int col) const
Returns the value at the indicated row.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
EggNode * find_child(const string &name) const
Returns the child of this node whose name is the indicated string, or NULL if there is no child of th...
Corresponding to an <S$Anim> entry, this stores a single column of numbers, for instance for a morph ...
virtual void write(ostream &out, int indent_level) const
Writes the data to the indicated output stream in Egg format.
static LMatrix4d translate_mat(const LVecBase3d &trans)
Returns a matrix that applies the indicated translation.
double get_fps() const
This is only valid if has_fps() returns true.
bool has_name() const
Returns true if the Namable has a nonempty name set, false if the name is empty.
void set_row(int row, const LVecBase4d &v)
Replaces the indicated row of the matrix.
static const string & get_standard_order()
Returns the standard order of matrix component composition.
static LVector3d forward(CoordinateSystem cs=CS_default)
Returns the forward vector for the given coordinate system.
bool almost_equal(const LMatrix4d &other, double threshold) const
Returns true if two matrices are memberwise equal within a specified tolerance.
int get_num_rows() const
Returns the effective number of rows in the table.
static const LMatrix4d & ident_mat()
Returns an identity matrix.
This corresponds to an <Xfm$Anim_S$> entry, which is a collection of up to nine <S$Anim> entries that...
virtual bool is_anim_matrix() const
Returns true if this node represents a table of animation transformation data, false otherwise...
void steal_children(EggGroupNode &other)
Moves all the children from the other node to this one.
static LMatrix4d rotate_mat_normaxis(double angle, const LVecBase3d &axis, CoordinateSystem cs=CS_default)
Returns a matrix that rotates by the given angle in degrees counterclockwise about the indicated vect...
CoordinateSystem get_coordinate_system() const
Returns the coordinate system this table believes it is defined within.
static LMatrix4d scale_shear_mat(const LVecBase3d &scale, const LVecBase3d &shear, CoordinateSystem cs=CS_default)
Returns a matrix that applies the indicated scale and shear.
Corresponding to an <Xfm$Anim> entry, this stores a two-dimensional table with up to nine columns...
void optimize_to_standard_order()
Optimizes the table by collapsing redundant sub-tables, and simultaneously ensures that the order str...
int get_num_rows() const
Returns the number of rows in the table.
This is the base class for all three-component vectors and points.
void optimize()
Optimizes the table by collapsing redundant sub-tables.
static void compose_with_order(LMatrix4d &mat, const LVecBase3d &scale, const LVecBase3d &shear, const LVecBase3d &hpr, const LVecBase3d &trans, const string &order, CoordinateSystem cs)
Composes a matrix out of the nine individual components, respecting the order string.
static LVector3d right(CoordinateSystem cs=CS_default)
Returns the right vector for the given coordinate system.
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
EggNode * add_child(EggNode *node)
Adds the indicated child to the group and returns it.
virtual void write(ostream &out, int indent_level) const
Writes the data to the indicated output stream in Egg format.
A base class for things that may be directly added into the egg hierarchy.
double get_fps() const
This is only valid if has_fps() returns true.
bool set_value(int row, const LMatrix4d &mat)
Replaces the indicated row of the table with the given matrix.
static LVector3d up(CoordinateSystem cs=CS_default)
Returns the up vector for the given coordinate system.
TypeHandle is the identifier used to differentiate C++ class types.
int get_num_rows() const
Returns the number of rows in the table.
void get_value(int row, LMatrix4d &mat) const
Returns the value of the aggregate row of the table as a matrix.
double get_value(int row) const
Returns the value at the indicated row.