30 const string EggXfmSAnim::_standard_order =
"srpht";
42 if (convert_from.has_order()) {
43 set_order(convert_from.get_order());
45 if (convert_from.has_fps()) {
46 set_fps(convert_from.
get_fps());
49 const string &contents = convert_from.get_contents();
50 for (
int col = 0; col < convert_from.
get_num_cols(); col++) {
53 for (
int row = 0; row < convert_from.
get_num_rows(); row++) {
64 iterator ci = begin();
66 iterator ci_next = ci;
69 if ((*ci)->is_of_type(EggSAnimData::get_class_type())) {
78 if (sanim->
has_name() && strchr(
"ijk", sanim->get_name()[0]) !=
nullptr) {
84 if (fabs(value - default_value) < egg_parameters->_table_threshold) {
103 normalize_by_rebuilding();
120 normalize_by_rebuilding();
126 normalize_by_expanding();
143 write(std::ostream &out,
int indent_level)
const {
144 test_under_integrity();
149 indent(out, indent_level + 2) <<
"<Scalar> fps { " <<
get_fps() <<
" }\n";
153 indent(out, indent_level + 2)
154 <<
"<Char*> order { " << get_order() <<
" }\n";
162 memset(tables, 0,
sizeof(
EggSAnimData *) * num_matrix_components);
165 for (ci = begin(); ci != end(); ++ci) {
167 if (child->
is_of_type(EggSAnimData::get_class_type())) {
171 nassertv(sanim->get_name().length() == 1);
172 char name = sanim->get_name()[0];
173 char *p = (
char *)strchr(matrix_component_letters, name);
174 nassertv(p !=
nullptr);
176 int index = p - matrix_component_letters;
177 nassertv(tables[index] ==
nullptr);
178 tables[index] = sanim;
182 child->write(out, indent_level + 2);
187 for (
int i = 0; i < num_matrix_components; i++) {
188 if (tables[i] !=
nullptr) {
189 tables[i]->
write(out, indent_level + 2);
193 indent(out, indent_level) <<
"}\n";
204 const LVecBase3d &scale,
205 const LVecBase3d &shear,
206 const LVecBase3d &hpr,
207 const LVecBase3d &trans,
209 CoordinateSystem cs) {
211 mat = LMatrix4d::ident_mat();
213 bool reverse_roll =
false;
215 if (order ==
"sphrt" && egg_support_old_anims) {
222 string::const_iterator pi;
223 for (pi = order.begin(); pi != order.end(); ++pi) {
226 mat = mat * LMatrix4d::scale_shear_mat(scale, shear, cs);
230 mat = mat * LMatrix4d::rotate_mat_normaxis(hpr[0], LVector3d::up(cs), cs);
234 mat = mat * LMatrix4d::rotate_mat_normaxis(hpr[1], LVector3d::right(cs), cs);
239 mat = mat * LMatrix4d::rotate_mat_normaxis(-hpr[2], LVector3d::forward(cs), cs);
241 mat = mat * LMatrix4d::rotate_mat_normaxis(hpr[2], LVector3d::forward(cs), cs);
246 mat = mat * LMatrix4d::translate_mat(trans);
251 <<
"Invalid letter in order string: " << *pi <<
"\n";
264 bool found_any =
false;
268 for (ci = begin(); ci != end(); ++ci) {
269 if ((*ci)->is_of_type(EggSAnimData::get_class_type())) {
294 LVector3d scale(1.0, 1.0, 1.0);
295 LVector3d shear(0.0, 0.0, 0.0);
296 LVector3d hpr(0.0, 0.0, 0.0);
297 LVector3d translate(0.0, 0.0, 0.0);
300 for (ci = begin(); ci != end(); ++ci) {
301 if ((*ci)->is_of_type(EggSAnimData::get_class_type())) {
318 nassertv(sanim->get_name().length() == 1);
320 switch (sanim->get_name()[0]) {
358 translate[0] = value;
362 translate[1] = value;
366 translate[2] = value;
371 nassert_raise(
"invalid name in child table");
395 double components[num_matrix_components];
396 bool add_ok = decompose_matrix(mat, components, _coordsys);
400 int table_length = -1;
403 for (
int i = 0; i < num_matrix_components; i++) {
404 string name(1, matrix_component_letters[i]);
406 nassertr(child !=
nullptr &&
407 child->
is_of_type(EggSAnimData::get_class_type()),
false);
412 if (table_length < 0) {
413 table_length = sanim->get_num_rows();
415 nassertr(sanim->get_num_rows() == table_length,
false);
418 sanim->set_value(row, components[i]);
425 if (!new_mat.almost_equal(mat, 0.005)) {
427 <<
"After set_row(" << row <<
", ...) to:\n";
428 mat.write(egg_cat.warning(
false), 2);
429 egg_cat.warning(
false)
430 <<
"which produces components:\n";
431 for (
int i = 0; i < num_matrix_components; i += 3) {
432 egg_cat.warning(
false)
434 << matrix_component_letters[i]
435 << matrix_component_letters[i + 1]
436 << matrix_component_letters[i + 2]
438 << components[i] <<
" " 439 << components[i + 1] <<
" " 440 << components[i + 2] <<
"\n";
442 egg_cat.warning(
false)
443 <<
"new mat set was:\n";
444 new_mat.write(egg_cat.warning(
false), 2);
477 double components[num_matrix_components];
478 bool add_ok = decompose_matrix(mat, components, _coordsys);
482 for (
int i = 0; i < num_matrix_components; i++) {
483 char name = matrix_component_letters[i];
495 int table_length = -1;
498 for (
int i = 0; i < num_matrix_components; i++) {
499 string name(1, matrix_component_letters[i]);
501 nassertr(child !=
nullptr &&
502 child->
is_of_type(EggSAnimData::get_class_type()),
false);
507 if (table_length < 0) {
508 table_length = sanim->get_num_rows();
510 nassertr(sanim->get_num_rows() == table_length,
false);
513 sanim->add_data(components[i]);
519 if (table_length >= 0) {
524 if (!new_mat.almost_equal(mat, 0.005)) {
526 <<
"After add_data():\n";
527 mat.write(egg_cat.warning(
false), 2);
528 egg_cat.warning(
false)
529 <<
"which produces components:\n";
530 for (
int i = 0; i < num_matrix_components; i += 3) {
531 egg_cat.warning(
false)
533 << matrix_component_letters[i]
534 << matrix_component_letters[i + 1]
535 << matrix_component_letters[i + 2]
537 << components[i] <<
" " 538 << components[i + 1] <<
" " 539 << components[i + 2] <<
"\n";
541 egg_cat.warning(
false)
542 <<
"new mat set was:\n";
543 new_mat.write(egg_cat.warning(
false), 2);
559 if (child ==
nullptr) {
565 DCAST_INTO_V(sanim, child);
576 nassertv(component >= 0 && component < num_matrix_components);
578 string name(1, matrix_component_letters[component]);
588 r_transform(
const LMatrix4d &mat,
const LMatrix4d &inv,
589 CoordinateSystem to_cs) {
592 LMatrix4d inv1 = inv;
593 inv1.set_row(3, LVector3d(0.0, 0.0, 0.0));
601 if (to_cs != CS_default) {
607 for (
int r = 0; r < num_rows; r++) {
609 bool result =
add_data(inv1 * orig_mat * mat);
627 r_mark_coordsys(CoordinateSystem cs) {
638 normalize_by_rebuilding() {
647 for (
int r = 0; r < num_rows; r++) {
665 normalize_by_expanding() {
670 int table_length = 1;
671 string remaining_tables = matrix_component_letters;
673 for (ci = begin(); ci != end(); ++ci) {
674 if ((*ci)->is_of_type(EggSAnimData::get_class_type())) {
677 nassertv(sanim->get_name().length() == 1);
678 char name = sanim->get_name()[0];
679 size_t p = remaining_tables.find(name);
680 nassertv(p != string::npos);
681 remaining_tables[p] =
' ';
685 if (table_length == 1) {
694 if (num_tables < num_matrix_components) {
696 for (
size_t p = 0; p < remaining_tables.length(); p++) {
697 if (remaining_tables[p] !=
' ') {
698 double default_value;
699 switch (remaining_tables[p]) {
710 string name(1, remaining_tables[p]);
719 for (ci = begin(); ci != end(); ++ci) {
720 if ((*ci)->is_of_type(EggSAnimData::get_class_type())) {
724 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.
static void compose_with_order(LMatrix4d &mat, const LVecBase3d &scale, const LVecBase3d &shear, const LVecBase3d &hpr, const LVecBase3d &trans, const std::string &order, CoordinateSystem cs)
Composes a matrix out of the nine individual components, respecting the order string.
int get_num_cols() const
Returns the number of columns in the table.
int get_num_rows() const
Returns the number of rows in the table.
void write_header(std::ostream &out, int indent_level, const char *egg_keyword) const
Writes the first line of the egg object, e.g.
bool add_data(const LMatrix4d &mat)
Adds a new matrix to the table, by adding a new row to each of the subtables.
void add_data(double value)
Adds a single element to the table.
virtual void write(std::ostream &out, int indent_level) const
Writes the data to the indicated output stream in Egg format.
A base class for nodes in the hierarchy that are not leaf nodes.
void normalize()
The inverse operation of optimize(), this ensures that all the sub-tables have the same length by dup...
Corresponding to an <S$Anim> entry, this stores a single column of numbers, for instance for a morph ...
CoordinateSystem get_coordinate_system() const
Returns the coordinate system this table believes it is defined within.
double get_value(int row) const
Returns the value at the indicated row.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void write(std::ostream &out, int indent_level) const
Writes the data to the indicated output stream in Egg format.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
double get_value(int row, int col) const
Returns the value at the indicated row.
This corresponds to an <Xfm$Anim_S$> entry, which is a collection of up to nine <S$Anim> entries that...
double get_fps() const
This is only valid if has_fps() returns true.
void steal_children(EggGroupNode &other)
Moves all the children from the other node to this one.
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...
void optimize()
Optimizes the table by collapsing redundant sub-tables.
void get_value(int row, LMatrix4d &mat) const
Returns the value of the aggregate row of the table as a matrix.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggNode * add_child(EggNode *node)
Adds the indicated child to the group and returns it.
void add_component_data(const std::string &component_name, double value)
Adds a new row to the named component (one of matrix_component_letters) of the table.
int get_num_rows() const
Returns the effective number of rows in the table.
A base class for things that may be directly added into the egg hierarchy.
virtual bool is_anim_matrix() const
Returns true if this node represents a table of animation transformation data, false otherwise.
double get_fps() const
This is only valid if has_fps() returns true.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_num_rows() const
Returns the number of rows in the table.
bool set_value(int row, const LMatrix4d &mat)
Replaces the indicated row of the table with the given matrix.
bool has_name() const
Returns true if the Namable has a nonempty name set, false if the name is empty.
static const std::string & get_standard_order()
Returns the standard order of matrix component composition.
TypeHandle is the identifier used to differentiate C++ class types.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggNode * find_child(const std::string &name) const
Returns the child of this node whose name is the indicated string, or NULL if there is no child of th...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.