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())) {
293 get_value(
int row, LMatrix4d &mat)
const {
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");
392 set_value(
int row,
const LMatrix4d &mat) {
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) {
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) {
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++) {
double get_fps() const
This is only valid if has_fps() returns true.
void add_data(double value)
Adds a single element to the table.
A base class for nodes in the hierarchy that are not leaf nodes.
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...
EggNode * add_child(EggNode *node)
Adds the indicated child to the group and returns it.
void steal_children(EggGroupNode &other)
Moves all the children from the other node to this one.
void write_header(std::ostream &out, int indent_level, const char *egg_keyword) const
Writes the first line of the egg object, e.g.
A base class for things that may be directly added into the egg hierarchy.
Corresponding to an <S$Anim> entry, this stores a single column of numbers, for instance for a morph ...
double get_value(int row) const
Returns the value at the indicated row.
void optimize()
Optimizes the data by collapsing a long table of duplicate values into a single value.
int get_num_rows() const
Returns the number of rows in the table.
virtual void write(std::ostream &out, int indent_level) const
Writes the data to the indicated output stream in Egg format.
void set_value(int row, double value)
Changes the value at the indicated row.
Corresponding to an <Xfm$Anim> entry, this stores a two-dimensional table with up to nine columns,...
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.
double get_value(int row, int col) const
Returns the value at the indicated row.
CoordinateSystem get_coordinate_system() const
Returns the coordinate system this table believes it is defined within.
This corresponds to an <Xfm$Anim_S$> entry, which is a collection of up to nine <S$Anim> entries that...
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.
virtual void write(std::ostream &out, int indent_level) const
Writes the data to the indicated output stream in Egg format.
int get_num_rows() const
Returns the effective number of rows in the table.
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.
virtual bool is_anim_matrix() const
Returns true if this node represents a table of animation transformation data, false otherwise.
bool add_data(const LMatrix4d &mat)
Adds a new matrix to the table, by adding a new row to each of the subtables.
void get_value(int row, LMatrix4d &mat) const
Returns the value of the aggregate row of the table as a matrix.
bool set_value(int row, const LMatrix4d &mat)
Replaces the indicated row of the table with the given matrix.
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.
void normalize()
The inverse operation of optimize(), this ensures that all the sub-tables have the same length by dup...
double get_fps() const
This is only valid if has_fps() returns true.
static const std::string & get_standard_order()
Returns the standard order of matrix component composition.
bool has_name() const
Returns true if the Namable has a nonempty name set, false if the name is empty.
TypeHandle is the identifier used to differentiate C++ class types.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.