From 344ca11ffd2e7e7f2f7c5cb416df02f0faac526f Mon Sep 17 00:00:00 2001 From: David Rose Date: Wed, 23 Jul 2003 23:03:04 +0000 Subject: [PATCH] add explicit support for shear to the scene graph --- panda/src/chan/animChannel.cxx | 11 +- panda/src/chan/animChannelMatrixXfmTable.I | 8 +- panda/src/chan/animChannelMatrixXfmTable.cxx | 129 ++++---- panda/src/chan/animChannelMatrixXfmTable.h | 15 +- panda/src/chan/movingPartMatrix.cxx | 18 +- panda/src/chan/movingPartMatrix.h | 2 +- panda/src/char/characterJoint.cxx | 1 - panda/src/doc/eggSyntax.txt | 7 +- panda/src/egg/config_egg.cxx | 4 +- panda/src/egg/config_egg.h | 4 +- panda/src/egg/eggXfmAnimData.cxx | 35 ++- panda/src/egg/eggXfmAnimData.h | 2 +- panda/src/egg/eggXfmSAnim.cxx | 287 ++++++++---------- panda/src/egg/eggXfmSAnim.h | 3 +- panda/src/gobj/lens.cxx | 8 +- panda/src/linmath/compose_matrix.cxx | 9 +- panda/src/linmath/compose_matrix.h | 13 +- panda/src/linmath/compose_matrix_src.I | 167 ++++++---- panda/src/linmath/compose_matrix_src.cxx | 73 +++-- panda/src/linmath/compose_matrix_src.h | 61 ++-- panda/src/linmath/lmatrix3_src.I | 51 ++-- panda/src/linmath/lmatrix3_src.cxx | 71 +++++ panda/src/linmath/lmatrix3_src.h | 18 +- panda/src/linmath/lmatrix4_src.I | 70 ++--- panda/src/linmath/lmatrix4_src.h | 18 +- panda/src/mathutil/fftCompressor.cxx | 60 ++-- panda/src/mathutil/fftCompressor.h | 10 +- .../parametrics/parametricCurveCollection.cxx | 10 +- panda/src/pgraph/config_pgraph.cxx | 6 - panda/src/pgraph/config_pgraph.h | 1 - panda/src/pgraph/nodePath.I | 58 ++++ panda/src/pgraph/nodePath.cxx | 270 ++++++++++++---- panda/src/pgraph/nodePath.h | 40 ++- panda/src/pgraph/transformState.I | 83 ++++- panda/src/pgraph/transformState.cxx | 87 ++++-- panda/src/pgraph/transformState.h | 56 ++-- panda/src/putil/bam.h | 5 +- panda/src/shader/planarReflector.cxx | 1 - panda/src/shader/spheretexReflector.cxx | 1 - panda/src/text/textNode.cxx | 5 +- panda/src/tform/driveInterface.cxx | 9 +- panda/src/tform/trackball.cxx | 46 +-- pandatool/src/egg-optchar/eggOptchar.cxx | 10 +- .../src/eggcharbase/eggCharacterData.cxx | 6 +- .../src/eggcharbase/eggMatrixTablePointer.cxx | 6 +- pandatool/src/mayaegg/mayaToEggConverter.cxx | 2 +- 46 files changed, 1192 insertions(+), 665 deletions(-) diff --git a/panda/src/chan/animChannel.cxx b/panda/src/chan/animChannel.cxx index 9941afc91f..429fc85c3f 100644 --- a/panda/src/chan/animChannel.cxx +++ b/panda/src/chan/animChannel.cxx @@ -19,7 +19,7 @@ #include "animChannel.h" -#include +#include "compose_matrix.h" // Tell GCC that we'll take care of the instantiation explicitly here. #ifdef __GNUC__ @@ -33,9 +33,9 @@ //////////////////////////////////////////////////////////////////// void ACMatrixSwitchType:: output_value(ostream &out, const ACMatrixSwitchType::ValueType &value) { - LVecBase3f scale, hpr, translate; - if (decompose_matrix(value, scale, hpr, translate)) { - if (!scale.almost_equal(LVecBase3f(1.0f,1.0f,1.0f))) { + LVecBase3f scale, shear, hpr, translate; + if (decompose_matrix(value, scale, shear, hpr, translate)) { + if (!scale.almost_equal(LVecBase3f(1.0f, 1.0f, 1.0f))) { if (IS_NEARLY_EQUAL(scale[0], scale[1]) && IS_NEARLY_EQUAL(scale[1], scale[2])) { out << " scale " << scale[0]; @@ -43,6 +43,9 @@ output_value(ostream &out, const ACMatrixSwitchType::ValueType &value) { out << " scale " << scale; } } + if (!shear.almost_equal(LVecBase3f(0.0f, 0.0f, 0.0f))) { + out << " shear " << shear; + } if (!hpr.almost_equal(LVecBase3f(0.0f, 0.0f, 0.0f))) { out << " hpr " << hpr; diff --git a/panda/src/chan/animChannelMatrixXfmTable.I b/panda/src/chan/animChannelMatrixXfmTable.I index d79fd264d6..a3874d6f76 100644 --- a/panda/src/chan/animChannelMatrixXfmTable.I +++ b/panda/src/chan/animChannelMatrixXfmTable.I @@ -77,11 +77,12 @@ clear_table(char table_id) { // Access: Protected, Static // Description: Returns the table ID associated with the indicated // table index number. This is the letter 'i', 'j', -// 'k', 'h', 'p', 'r', 'x', 'y', or 'z'. +// 'k', 'a', 'b', 'c', 'h', 'p', 'r', 'x', 'y', or 'z'. //////////////////////////////////////////////////////////////////// INLINE char AnimChannelMatrixXfmTable:: get_table_id(int table_index) { - return _table_ids[table_index]; + nassertr(table_index >= 0 && table_index < num_matrix_components, '\0'); + return matrix_component_letters[table_index]; } @@ -93,6 +94,7 @@ get_table_id(int table_index) { //////////////////////////////////////////////////////////////////// INLINE float AnimChannelMatrixXfmTable:: get_default_value(int table_index) { - return _default_values[table_index]; + nassertr(table_index >= 0 && table_index < num_matrix_components, 0.0); + return matrix_component_defaults[table_index]; } diff --git a/panda/src/chan/animChannelMatrixXfmTable.cxx b/panda/src/chan/animChannelMatrixXfmTable.cxx index 9a37fd9988..47acf583cb 100644 --- a/panda/src/chan/animChannelMatrixXfmTable.cxx +++ b/panda/src/chan/animChannelMatrixXfmTable.cxx @@ -21,24 +21,16 @@ #include "animBundle.h" #include "config_chan.h" -#include -#include -#include -#include -#include -#include -#include +#include "compose_matrix.h" +#include "indent.h" +#include "datagram.h" +#include "datagramIterator.h" +#include "bamReader.h" +#include "bamWriter.h" +#include "fftCompressor.h" TypeHandle AnimChannelMatrixXfmTable::_type_handle; -const char -AnimChannelMatrixXfmTable::_table_ids[AnimChannelMatrixXfmTable::num_tables] = -{ 'i', 'j', 'k', 'h', 'p', 'r', 'x', 'y', 'z' }; - -const float -AnimChannelMatrixXfmTable::_default_values[AnimChannelMatrixXfmTable::num_tables] = -{ 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - //////////////////////////////////////////////////////////////////// // Function: AnimChannelMatrixXfmTable::Constructor // Access: Public @@ -66,7 +58,7 @@ AnimChannelMatrixXfmTable(void) //////////////////////////////////////////////////////////////////// bool AnimChannelMatrixXfmTable:: has_changed(int last_frame, int this_frame) { - for (int i = 0; i < num_tables; i++) { + for (int i = 0; i < num_matrix_components; i++) { if (_tables[i].size() > 1) { if (_tables[i][last_frame % _tables[i].size()] != _tables[i][this_frame % _tables[i].size()]) { @@ -85,9 +77,9 @@ has_changed(int last_frame, int this_frame) { //////////////////////////////////////////////////////////////////// void AnimChannelMatrixXfmTable:: get_value(int frame, LMatrix4f &mat) { - float components[num_tables]; + float components[num_matrix_components]; - for (int i = 0; i < num_tables; i++) { + for (int i = 0; i < num_matrix_components; i++) { if (_tables[i].empty()) { components[i] = get_default_value(i); } else { @@ -106,12 +98,12 @@ get_value(int frame, LMatrix4f &mat) { //////////////////////////////////////////////////////////////////// void AnimChannelMatrixXfmTable:: get_value_no_scale(int frame, LMatrix4f &mat) { - float components[num_tables]; + float components[num_matrix_components]; components[0] = 1.0f; components[1] = 1.0f; components[2] = 1.0f; - for (int i = 3; i < num_tables; i++) { + for (int i = 3; i < num_matrix_components; i++) { if (_tables[i].empty()) { components[i] = get_default_value(i); } else { @@ -147,7 +139,7 @@ get_scale(int frame, float scale[3]) { //////////////////////////////////////////////////////////////////// void AnimChannelMatrixXfmTable:: clear_all_tables() { - for (int i = 0; i < num_tables; i++) { + for (int i = 0; i < num_matrix_components; i++) { _tables[i] = NULL; } } @@ -191,7 +183,7 @@ write(ostream &out, int indent_level) const { // Write a list of all the sub-tables that have data. bool found_any = false; - for (int i = 0; i < num_tables; i++) { + for (int i = 0; i < num_matrix_components; i++) { if (!_tables[i].empty()) { out << get_table_id(i) << _tables[i].size(); found_any = true; @@ -216,12 +208,12 @@ write(ostream &out, int indent_level) const { // Function: AnimChannelMatrixXfmTable::get_table_index // Access: Protected, Static // Description: Returns the table index number, a value between 0 and -// num_tables, that corresponds to the indicate table +// num_matrix_components, that corresponds to the indicate table // id. Returns -1 if the table id is invalid. //////////////////////////////////////////////////////////////////// int AnimChannelMatrixXfmTable:: get_table_index(char table_id) { - for (int i = 0; i < num_tables; i++) { + for (int i = 0; i < num_matrix_components; i++) { if (table_id == get_table_id(i)) { return i; } @@ -237,8 +229,7 @@ get_table_index(char table_id) { // the particular object to a Datagram //////////////////////////////////////////////////////////////////// void AnimChannelMatrixXfmTable:: -write_datagram(BamWriter *manager, Datagram &me) -{ +write_datagram(BamWriter *manager, Datagram &me) { AnimChannelMatrix::write_datagram(manager, me); if (compress_channels && !FFTCompressor::is_compression_available()) { @@ -250,7 +241,7 @@ write_datagram(BamWriter *manager, Datagram &me) me.add_bool(compress_channels); if (!compress_channels) { // Write out everything uncompressed, as a stream of floats. - for(int i = 0; i < num_tables; i++) { + for (int i = 0; i < num_matrix_components; i++) { me.add_uint16(_tables[i].size()); for(int j = 0; j < (int)_tables[i].size(); j++) { me.add_float32(_tables[i][j]); @@ -264,9 +255,9 @@ write_datagram(BamWriter *manager, Datagram &me) compressor.set_quality(compress_chan_quality); compressor.write_header(me); - // First, write out the scales. + // First, write out the scales and shears. int i; - for(i = 0; i < 3; i++) { + for (i = 0; i < 6; i++) { compressor.write_reals(me, _tables[i], _tables[i].size()); } @@ -274,18 +265,18 @@ write_datagram(BamWriter *manager, Datagram &me) // a HPR array. vector_LVecBase3f hprs; int hprs_length = - max(max(_tables[3].size(), _tables[4].size()), _tables[5].size()); + max(max(_tables[6].size(), _tables[7].size()), _tables[8].size()); hprs.reserve(hprs_length); for (i = 0; i < hprs_length; i++) { - float h = _tables[3].empty() ? 0.0f : _tables[3][i % _tables[3].size()]; - float p = _tables[4].empty() ? 0.0f : _tables[4][i % _tables[4].size()]; - float r = _tables[5].empty() ? 0.0f : _tables[5][i % _tables[5].size()]; + float h = _tables[6].empty() ? 0.0f : _tables[6][i % _tables[6].size()]; + float p = _tables[7].empty() ? 0.0f : _tables[7][i % _tables[7].size()]; + float r = _tables[8].empty() ? 0.0f : _tables[8][i % _tables[8].size()]; hprs.push_back(LVecBase3f(h, p, r)); } compressor.write_hprs(me, &hprs[0], hprs_length); // And now the translations. - for(i = 6; i < 9; i++) { + for(i = 9; i < num_matrix_components; i++) { compressor.write_reals(me, _tables[i], _tables[i].size()); } } @@ -300,21 +291,26 @@ write_datagram(BamWriter *manager, Datagram &me) // place //////////////////////////////////////////////////////////////////// void AnimChannelMatrixXfmTable:: -fillin(DatagramIterator& scan, BamReader* manager) -{ +fillin(DatagramIterator &scan, BamReader *manager) { AnimChannelMatrix::fillin(scan, manager); bool wrote_compressed = scan.get_bool(); if (!wrote_compressed) { // Regular floats. - for(int i = 0; i < num_tables; i++) { - int size = scan.get_uint16(); - PTA_float ind_table; - for(int j = 0; j < size; j++) { - ind_table.push_back(scan.get_float32()); + for (int i = 0; i < num_matrix_components; i++) { + if (manager->get_file_minor_ver() < 6 && i >= 3 && i < 6) { + // Old bam files didn't store a shear component. + _tables[i].clear(); + + } else { + int size = scan.get_uint16(); + PTA_float ind_table; + for (int j = 0; j < size; j++) { + ind_table.push_back(scan.get_float32()); + } + _tables[i] = ind_table; } - _tables[i] = ind_table; } } else { @@ -330,32 +326,45 @@ fillin(DatagramIterator& scan, BamReader* manager) compressor.read_header(scan); int i; - // First, read in the scales. - for(i = 0; i < 3; i++) { - PTA_float ind_table=PTA_float::empty_array(0); + // First, read in the scales and shears. + for (i = 0; i < 3; i++) { + PTA_float ind_table = PTA_float::empty_array(0); compressor.read_reals(scan, ind_table.v()); _tables[i] = ind_table; } + if (manager->get_file_minor_ver() < 6) { + // Old bam files didn't store a shear. + _tables[3].clear(); + _tables[4].clear(); + _tables[5].clear(); + + } else { + for (i = 3; i < 6; i++) { + PTA_float ind_table = PTA_float::empty_array(0); + compressor.read_reals(scan, ind_table.v()); + _tables[i] = ind_table; + } + } // Read in the HPR array and store it back in the joint angles. vector_LVecBase3f hprs; compressor.read_hprs(scan, hprs); - PTA_float h_table=PTA_float::empty_array(hprs.size()); - PTA_float p_table=PTA_float::empty_array(hprs.size()); - PTA_float r_table=PTA_float::empty_array(hprs.size()); + PTA_float h_table = PTA_float::empty_array(hprs.size()); + PTA_float p_table = PTA_float::empty_array(hprs.size()); + PTA_float r_table = PTA_float::empty_array(hprs.size()); for (i = 0; i < (int)hprs.size(); i++) { h_table[i] = hprs[i][0]; p_table[i] = hprs[i][1]; r_table[i] = hprs[i][2]; } - _tables[3] = h_table; - _tables[4] = p_table; - _tables[5] = r_table; + _tables[6] = h_table; + _tables[7] = p_table; + _tables[8] = r_table; // Now read in the translations. - for (i = 6; i < 9; i++) { - PTA_float ind_table=PTA_float::empty_array(0); + for (i = 9; i < num_matrix_components; i++) { + PTA_float ind_table = PTA_float::empty_array(0); compressor.read_reals(scan, ind_table.v()); _tables[i] = ind_table; } @@ -365,11 +374,11 @@ fillin(DatagramIterator& scan, BamReader* manager) //////////////////////////////////////////////////////////////////// // Function: AnimChannelMatrixXfmTable::make_AnimChannelMatrixXfmTable // Access: Protected -// Description: Factory method to generate a AnimChannelMatrixXfmTable object +// Description: Factory method to generate an +// AnimChannelMatrixXfmTable object. //////////////////////////////////////////////////////////////////// -TypedWritable* AnimChannelMatrixXfmTable:: -make_AnimChannelMatrixXfmTable(const FactoryParams ¶ms) -{ +TypedWritable *AnimChannelMatrixXfmTable:: +make_AnimChannelMatrixXfmTable(const FactoryParams ¶ms) { AnimChannelMatrixXfmTable *me = new AnimChannelMatrixXfmTable; DatagramIterator scan; BamReader *manager; @@ -382,11 +391,11 @@ make_AnimChannelMatrixXfmTable(const FactoryParams ¶ms) //////////////////////////////////////////////////////////////////// // Function: AnimChannelMatrixXfmTable::register_with_factory // Access: Public, Static -// Description: Factory method to generate a AnimChannelMatrixXfmTable object +// Description: Factory method to generate an +// AnimChannelMatrixXfmTable object. //////////////////////////////////////////////////////////////////// void AnimChannelMatrixXfmTable:: -register_with_read_factory(void) -{ +register_with_read_factory() { BamReader::get_factory()->register_factory(get_class_type(), make_AnimChannelMatrixXfmTable); } diff --git a/panda/src/chan/animChannelMatrixXfmTable.h b/panda/src/chan/animChannelMatrixXfmTable.h index fd5ef87aea..c59ac3eff5 100644 --- a/panda/src/chan/animChannelMatrixXfmTable.h +++ b/panda/src/chan/animChannelMatrixXfmTable.h @@ -19,12 +19,13 @@ #ifndef ANIMCHANNELMATRIXXFMTABLE_H #define ANIMCHANNELMATRIXXFMTABLE_H -#include +#include "pandabase.h" #include "animChannel.h" -#include -#include +#include "pointerToArray.h" +#include "pta_float.h" +#include "compose_matrix.h" //////////////////////////////////////////////////////////////////// // Class : AnimChannelMatrixXfmTable @@ -59,13 +60,7 @@ protected: static int get_table_index(char table_id); INLINE static float get_default_value(int table_index); - enum { num_tables = 9 }; - - CPTA_float _tables[num_tables]; - -private: - static const char _table_ids[num_tables]; - static const float _default_values[num_tables]; + CPTA_float _tables[num_matrix_components]; public: static void register_with_read_factory(void); diff --git a/panda/src/chan/movingPartMatrix.cxx b/panda/src/chan/movingPartMatrix.cxx index 717436f051..a9e4e3eb63 100644 --- a/panda/src/chan/movingPartMatrix.cxx +++ b/panda/src/chan/movingPartMatrix.cxx @@ -19,11 +19,11 @@ #include "movingPartMatrix.h" -#include -#include -#include -#include -#include +#include "compose_matrix.h" +#include "datagram.h" +#include "datagramIterator.h" +#include "bamReader.h" +#include "bamWriter.h" // Tell GCC that we'll take care of the instantiation explicitly here. #ifdef __GNUC__ @@ -93,6 +93,8 @@ get_blend_value(const PartBundle *root) { // resulting matrix to eliminate artificially-introduced scales, // and then reapply the scales. + // Perhaps we should treat shear the same as a scale here? + _value = 0.0f; LVector3f scale(0.0f, 0.0f, 0.0f); float net = 0.0f; @@ -124,9 +126,9 @@ get_blend_value(const PartBundle *root) { // Now rebuild the matrix with the correct scale values. - LVector3f false_scale, hpr, translate; - decompose_matrix(_value, false_scale, hpr, translate); - compose_matrix(_value, scale, hpr, translate); + LVector3f false_scale, shear, hpr, translate; + decompose_matrix(_value, false_scale, shear, hpr, translate); + compose_matrix(_value, scale, shear, hpr, translate); } } } diff --git a/panda/src/chan/movingPartMatrix.h b/panda/src/chan/movingPartMatrix.h index edacd41add..8f55a356f5 100644 --- a/panda/src/chan/movingPartMatrix.h +++ b/panda/src/chan/movingPartMatrix.h @@ -19,7 +19,7 @@ #ifndef MOVINGPARTMATRIX_H #define MOVINGPARTMATRIX_H -#include +#include "pandabase.h" #include "movingPart.h" #include "animChannel.h" diff --git a/panda/src/char/characterJoint.cxx b/panda/src/char/characterJoint.cxx index eb88b47489..a608b553d3 100644 --- a/panda/src/char/characterJoint.cxx +++ b/panda/src/char/characterJoint.cxx @@ -19,7 +19,6 @@ #include "characterJoint.h" #include "config_char.h" -#include "compose_matrix.h" #include "datagram.h" #include "datagramIterator.h" #include "bamReader.h" diff --git a/panda/src/doc/eggSyntax.txt b/panda/src/doc/eggSyntax.txt index 42f561f31f..b93bbb0a9e 100644 --- a/panda/src/doc/eggSyntax.txt +++ b/panda/src/doc/eggSyntax.txt @@ -1227,18 +1227,19 @@ GROUPING ENTRIES name { fps { 24 } order { sphrt } - contents { ijkphrxyz } + contents { ijkabcphrxyz } { values } } This is a table of matrix transforms, one per frame, such as may be applied to a joint. The "contents" string consists of a subset - of the letters "ijkphrxyz", where each letter corresponds to a + of the letters "ijkabcphrxyz", where each letter corresponds to a column of the table; is a list of numbers of length(contents) * num_frames. Each letter of the contents string corresponds to a type of transformation: i, j, k - scale in x, y, z directions, respectively + a, b, c - shear in xy, xz, and yz planes, respectively p, h, r - rotate by pitch, heading, roll x, y, z - translate in x, y, z directions @@ -1248,7 +1249,7 @@ GROUPING ENTRIES string. The order the transforms are applied is defined by the order string: - s - all scale transforms + s - all scale and shear transforms p, h, r - individual rotate transforms t - all translation transforms diff --git a/panda/src/egg/config_egg.cxx b/panda/src/egg/config_egg.cxx index 03e1be86de..1e6e2ed83b 100644 --- a/panda/src/egg/config_egg.cxx +++ b/panda/src/egg/config_egg.cxx @@ -51,8 +51,8 @@ #include "eggXfmAnimData.h" #include "eggXfmSAnim.h" -#include -#include +#include "dconfig.h" +#include "get_config_path.h" Configure(config_egg); NotifyCategoryDef(egg, ""); diff --git a/panda/src/egg/config_egg.h b/panda/src/egg/config_egg.h index 795b3c4fd7..6cc57eb2ac 100644 --- a/panda/src/egg/config_egg.h +++ b/panda/src/egg/config_egg.h @@ -19,8 +19,8 @@ #ifndef CONFIG_EGG_H #define CONFIG_EGG_H -#include -#include +#include "pandabase.h" +#include "notifyCategoryProxy.h" class DSearchPath; diff --git a/panda/src/egg/eggXfmAnimData.cxx b/panda/src/egg/eggXfmAnimData.cxx index 726438624b..7aded58277 100644 --- a/panda/src/egg/eggXfmAnimData.cxx +++ b/panda/src/egg/eggXfmAnimData.cxx @@ -22,10 +22,10 @@ #include "eggMiscFuncs.h" #include "config_egg.h" -#include -#include -#include -#include +#include "indent.h" +#include "luse.h" +#include "lmatrix.h" +#include "compose_matrix.h" TypeHandle EggXfmAnimData::_type_handle; @@ -94,6 +94,7 @@ EggXfmAnimData(const EggXfmSAnim &convert_from) void EggXfmAnimData:: get_value(int row, LMatrix4d &mat) const { LVector3d scale(1.0, 1.0, 1.0); + LVector3d shear(0.0, 0.0, 0.0); LVector3d hpr(0.0, 0.0, 0.0); LVector3d translate(0.0, 0.0, 0.0); @@ -113,6 +114,18 @@ get_value(int row, LMatrix4d &mat) const { scale[2] = value; break; + case 'a': + shear[0] = value; + break; + + case 'b': + shear[1] = value; + break; + + case 'c': + shear[2] = value; + break; + case 'h': hpr[0] = value; break; @@ -143,8 +156,8 @@ get_value(int row, LMatrix4d &mat) const { } } - // So now we've got the nine components; build a matrix. - EggXfmSAnim::compose_with_order(mat, scale, hpr, translate, get_order(), + // So now we've got the twelve components; build a matrix. + EggXfmSAnim::compose_with_order(mat, scale, shear, hpr, translate, get_order(), _coordsys); } @@ -221,26 +234,28 @@ r_transform(const LMatrix4d &mat, const LMatrix4d &inv, egg_cat.error() << "Transform from " << _coordsys << " to " << to_cs << " failed!\n"; - LVector3d scale, hpr, trans; - bool d = decompose_matrix(orig_mat, scale, hpr, trans, _coordsys); + LVector3d scale, shear, hpr, trans; + bool d = decompose_matrix(orig_mat, scale, shear, hpr, trans, _coordsys); egg_cat.error(false) << "orig:\n" << orig_mat << "d = " << d << "\n scale: " << scale + << "\n shear: " << shear << "\n hpr: " << hpr << "\n trans: " << trans << "\n"; LMatrix4d new_mat = inv1 * orig_mat * mat; - d = decompose_matrix(new_mat, scale, hpr, trans, to_cs); + d = decompose_matrix(new_mat, scale, shear, hpr, trans, to_cs); egg_cat.error(false) << "new:\n" << new_mat << "d = " << d << "\n scale: " << scale + << "\n shear: " << shear << "\n hpr: " << hpr << "\n trans: " << trans << "\n"; } - // If this assertion fails, we attempted to transform by a skew + // If this assertion fails, we attempted to transform by non-affine // matrix or some such thing that cannot be represented in an anim // file. nassertv(result); diff --git a/panda/src/egg/eggXfmAnimData.h b/panda/src/egg/eggXfmAnimData.h index a1caae8733..6a5e3179ee 100644 --- a/panda/src/egg/eggXfmAnimData.h +++ b/panda/src/egg/eggXfmAnimData.h @@ -19,7 +19,7 @@ #ifndef EGGXFMANIMDATA_H #define EGGXFMANIMDATA_H -#include +#include "pandabase.h" #include "eggAnimData.h" #include "eggXfmSAnim.h" diff --git a/panda/src/egg/eggXfmSAnim.cxx b/panda/src/egg/eggXfmSAnim.cxx index 6077f6d0ed..a3010ee2d5 100644 --- a/panda/src/egg/eggXfmSAnim.cxx +++ b/panda/src/egg/eggXfmSAnim.cxx @@ -37,11 +37,6 @@ TypeHandle EggXfmSAnim::_type_handle; const string EggXfmSAnim::_standard_order_legacy = "sphrt"; const string EggXfmSAnim::_standard_order_hpr_fix = "srpht"; -// These are the table ID's of all tables we support, in the order we -// expect to write them to the egg file. -const string EggXfmSAnim::_table_ids = "ijkhprxyz"; -const int EggXfmSAnim::_num_table_ids = 9; - //////////////////////////////////////////////////////////////////// // Function: EggXfmSAnim::Conversion constructor @@ -181,8 +176,8 @@ write(ostream &out, int indent_level) const { // write out all the non-table children first, then write out the // table children in our expected order. (Normally there are only // table children.) - EggSAnimData *tables[_num_table_ids]; - memset(tables, 0, sizeof(EggSAnimData *) * _num_table_ids); + EggSAnimData *tables[num_matrix_components]; + memset(tables, 0, sizeof(EggSAnimData *) * num_matrix_components); const_iterator ci; for (ci = begin(); ci != end(); ++ci) { @@ -193,9 +188,10 @@ write(ostream &out, int indent_level) const { // Each child SAnimData table should have a one-letter name. nassertv(sanim->get_name().length() == 1); char name = sanim->get_name()[0]; - size_t index = _table_ids.find(name); - nassertv(index != string::npos); - if (index != string::npos) { + char *p = strchr(matrix_component_letters, name); + nassertv(p != (char *)NULL); + if (p != (char *)NULL) { + int index = p - matrix_component_letters; nassertv(tables[index] == (EggSAnimData *)NULL); tables[index] = sanim; } @@ -206,7 +202,7 @@ write(ostream &out, int indent_level) const { } // Now write out the table children in our normal order. - for (int i = 0; i < _num_table_ids; i++) { + for (int i = 0; i < num_matrix_components; i++) { if (tables[i] != (EggSAnimData *)NULL) { tables[i]->write(out, indent_level + 2); } @@ -227,6 +223,7 @@ write(ostream &out, int indent_level) const { void EggXfmSAnim:: compose_with_order(LMatrix4d &mat, const LVecBase3d &scale, + const LVecBase3d &shear, const LVecBase3d &hpr, const LVecBase3d &trans, const string &order, @@ -247,7 +244,7 @@ compose_with_order(LMatrix4d &mat, for (pi = order.begin(); pi != order.end(); ++pi) { switch (*pi) { case 's': - mat = mat * LMatrix4d::scale_mat(scale); + mat = mat * LMatrix4d::scale_shear_mat(scale, shear, cs); break; case 'h': @@ -318,11 +315,12 @@ get_num_rows() const { // table of matrices. It is an error to call this if // any SAnimData children of this node have an improper // name (e.g. not a single letter, or not one of -// "ijkhprxyz"). +// "ijkabchprxyz"). //////////////////////////////////////////////////////////////////// void EggXfmSAnim:: get_value(int row, LMatrix4d &mat) const { LVector3d scale(1.0, 1.0, 1.0); + LVector3d shear(0.0, 0.0, 0.0); LVector3d hpr(0.0, 0.0, 0.0); LVector3d translate(0.0, 0.0, 0.0); @@ -361,6 +359,18 @@ get_value(int row, LMatrix4d &mat) const { scale[2] = value; break; + case 'a': + shear[0] = value; + break; + + case 'b': + shear[1] = value; + break; + + case 'c': + shear[2] = value; + break; + case 'h': hpr[0] = value; break; @@ -393,7 +403,7 @@ get_value(int row, LMatrix4d &mat) const { } // So now we've got the nine components; build a matrix. - compose_with_order(mat, scale, hpr, translate, get_order(), _coordsys); + compose_with_order(mat, scale, shear, hpr, translate, get_order(), _coordsys); } //////////////////////////////////////////////////////////////////// @@ -407,90 +417,69 @@ get_value(int row, LMatrix4d &mat) const { // normalize() first if you are not sure. // // The return value is true if the matrix can be -// decomposed and stored as scale, rotate, and -// translate, or false otherwise. +// decomposed and stored as scale, shear, rotate, and +// translate, or false otherwise. The data is set in +// either case. //////////////////////////////////////////////////////////////////// bool EggXfmSAnim:: set_value(int row, const LMatrix4d &mat) { nassertr(get_order() == get_standard_order(), false); - LVector3d scale, hpr, translate; - bool result = decompose_matrix(mat, scale, hpr, translate, _coordsys); - if (!result) { - return false; - } + double components[num_matrix_components]; + bool add_ok = decompose_matrix(mat, components, _coordsys); // Sanity check our sub-tables. #ifndef NDEBUG int table_length = -1; - int num_tables = 0; #endif - const_iterator ci; - for (ci = begin(); ci != end(); ++ci) { - if ((*ci)->is_of_type(EggSAnimData::get_class_type())) { - EggSAnimData *sanim = DCAST(EggSAnimData, *ci); + for (int i = 0; i < num_matrix_components; i++) { + string name(1, matrix_component_letters[i]); + EggNode *child = find_child(name); + nassertr(child != (EggNode *)NULL && + child->is_of_type(EggSAnimData::get_class_type()), false); + EggSAnimData *sanim = DCAST(EggSAnimData, child); #ifndef NDEBUG - num_tables++; - - // Each table must have the same length. - if (table_length < 0) { - table_length = sanim->get_num_rows(); - } else { - nassertr(sanim->get_num_rows() == table_length, false); - } -#endif - - // Each child SAnimData table should have a one-letter name. - nassertr(sanim->get_name().length() == 1, false); - - switch (sanim->get_name()[0]) { - case 'i': - sanim->set_value(row, scale[0]); - break; - - case 'j': - sanim->set_value(row, scale[1]); - break; - - case 'k': - sanim->set_value(row, scale[2]); - break; - - case 'h': - sanim->set_value(row, hpr[0]); - break; - - case 'p': - sanim->set_value(row, hpr[1]); - break; - - case 'r': - sanim->set_value(row, hpr[2]); - break; - - case 'x': - sanim->set_value(row, translate[0]); - break; - - case 'y': - sanim->set_value(row, translate[1]); - break; - - case 'z': - sanim->set_value(row, translate[2]); - break; - - default: - // One of the child tables had an invalid name. - nassertr(false, false); - } + // Each table must have the same length. + if (table_length < 0) { + table_length = sanim->get_num_rows(); + } else { + nassertr(sanim->get_num_rows() == table_length, false); } +#endif + sanim->set_value(row, components[i]); } - nassertr(num_tables == 9, false); - return true; +#ifndef NDEBUG + // Sanity check the result. + LMatrix4d new_mat; + get_value(row, new_mat); + if (!new_mat.almost_equal(mat, 0.005)) { + egg_cat.warning() + << "After set_row(" << row << ", ...) to:\n"; + mat.write(egg_cat.warning(false), 2); + egg_cat.warning(false) + << "which produces components:\n"; + for (int i = 0; i < num_matrix_components; i += 3) { + egg_cat.warning(false) + << " " + << matrix_component_letters[i] + << matrix_component_letters[i + 1] + << matrix_component_letters[i + 2] + << ": " + << components[i] << " " + << components[i + 1] << " " + << components[i + 2] << "\n"; + } + egg_cat.warning(false) + << "new mat set was:\n"; + new_mat.write(egg_cat.warning(false), 2); + return false; + } +#endif + + return add_ok; } //////////////////////////////////////////////////////////////////// @@ -504,14 +493,13 @@ set_value(int row, const LMatrix4d &mat) { // table of matrices. It is an error to call this if // any SAnimData children of this node have an improper // name (e.g. not a single letter, or not one of -// "ijkhprxyz"). +// "ijkabchprxyz"). // // This function has the further requirement that all // nine of the subtables must exist and be of the same // length. Furthermore, the order string must be the -// standard order string, "ijkrphxyz", which matches the -// system compose_matrix() and decompose_matrix() -// functions. +// standard order string, which matches the system +// compose_matrix() and decompose_matrix() functions. // // Thus, you probably cannot take an existing // EggXfmSAnim object and start adding matrices to the @@ -521,21 +509,20 @@ set_value(int row, const LMatrix4d &mat) { // you on an existing EggXfmSAnim. // // This function may fail silently if the matrix cannot -// be decomposed into scale, rotate, and translate. In -// this case, the closest approximation is added to the -// table, and false is returned. +// be decomposed into scale, shear, rotate, and +// translate. In this case, the closest approximation +// is added to the table, and false is returned. //////////////////////////////////////////////////////////////////// bool EggXfmSAnim:: add_data(const LMatrix4d &mat) { - LVector3d scale, hpr, translate; - bool add_ok = decompose_matrix(mat, scale, hpr, translate, _coordsys); + double components[num_matrix_components]; + bool add_ok = decompose_matrix(mat, components, _coordsys); if (empty()) { - // If we have no children, create all nine tables now. - for (string::const_iterator p = _table_ids.begin(); - p != _table_ids.end(); - ++p) { - EggSAnimData *sanim = new EggSAnimData(string(1, *p)); + // If we have no children, create all twelve tables now. + for (int i = 0; i < num_matrix_components; i++) { + char name = matrix_component_letters[i]; + EggSAnimData *sanim = new EggSAnimData(string(1, name)); add_child(sanim); } @@ -547,73 +534,57 @@ add_data(const LMatrix4d &mat) { #ifndef NDEBUG int table_length = -1; - int num_tables = 0; #endif - const_iterator ci; - for (ci = begin(); ci != end(); ++ci) { - if ((*ci)->is_of_type(EggSAnimData::get_class_type())) { - EggSAnimData *sanim = DCAST(EggSAnimData, *ci); + for (int i = 0; i < num_matrix_components; i++) { + string name(1, matrix_component_letters[i]); + EggNode *child = find_child(name); + nassertr(child != (EggNode *)NULL && + child->is_of_type(EggSAnimData::get_class_type()), false); + EggSAnimData *sanim = DCAST(EggSAnimData, child); #ifndef NDEBUG - num_tables++; - - // Each table must have the same length. - if (table_length < 0) { - table_length = sanim->get_num_rows(); - } else { - nassertr(sanim->get_num_rows() == table_length, false); - } -#endif - - // Each child SAnimData table should have a one-letter name. - nassertr(sanim->get_name().length() == 1, false); - - switch (sanim->get_name()[0]) { - case 'i': - sanim->add_data(scale[0]); - break; - - case 'j': - sanim->add_data(scale[1]); - break; - - case 'k': - sanim->add_data(scale[2]); - break; - - case 'h': - sanim->add_data(hpr[0]); - break; - - case 'p': - sanim->add_data(hpr[1]); - break; - - case 'r': - sanim->add_data(hpr[2]); - break; - - case 'x': - sanim->add_data(translate[0]); - break; - - case 'y': - sanim->add_data(translate[1]); - break; - - case 'z': - sanim->add_data(translate[2]); - break; - - default: - // One of the child tables had an invalid name. - nassertr(false, false); - } + // Each table must have the same length. + if (table_length < 0) { + table_length = sanim->get_num_rows(); + } else { + nassertr(sanim->get_num_rows() == table_length, false); } +#endif + sanim->add_data(components[i]); } - nassertr(num_tables == 9, false); +#ifndef NDEBUG + // Sanity check the result. + LMatrix4d new_mat; + if (table_length >= 0) { + get_value(table_length, new_mat); + } else { + get_value(0, new_mat); + } + if (!new_mat.almost_equal(mat, 0.005)) { + egg_cat.warning() + << "After add_data():\n"; + mat.write(egg_cat.warning(false), 2); + egg_cat.warning(false) + << "which produces components:\n"; + for (int i = 0; i < num_matrix_components; i += 3) { + egg_cat.warning(false) + << " " + << matrix_component_letters[i] + << matrix_component_letters[i + 1] + << matrix_component_letters[i + 2] + << ": " + << components[i] << " " + << components[i + 1] << " " + << components[i + 2] << "\n"; + } + egg_cat.warning(false) + << "new mat set was:\n"; + new_mat.write(egg_cat.warning(false), 2); + return false; + } +#endif return add_ok; } @@ -723,7 +694,7 @@ normalize_by_expanding() { // are. int num_tables = 0; int table_length = 1; - string remaining_tables = "ijkhprxyz"; + string remaining_tables = matrix_component_letters; for (ci = begin(); ci != end(); ++ci) { if ((*ci)->is_of_type(EggSAnimData::get_class_type())) { @@ -746,7 +717,7 @@ normalize_by_expanding() { } } - if (num_tables < 9) { + if (num_tables < num_matrix_components) { // Create new, default, children for each table we lack. for (size_t p = 0; p < remaining_tables.length(); p++) { if (remaining_tables[p] != ' ') { diff --git a/panda/src/egg/eggXfmSAnim.h b/panda/src/egg/eggXfmSAnim.h index f899e3ef13..f15e7d7f64 100644 --- a/panda/src/egg/eggXfmSAnim.h +++ b/panda/src/egg/eggXfmSAnim.h @@ -71,6 +71,7 @@ public: static void compose_with_order(LMatrix4d &mat, const LVecBase3d &scale, + const LVecBase3d &shear, const LVecBase3d &hpr, const LVecBase3d &trans, const string &order, @@ -94,8 +95,6 @@ private: static const string _standard_order_legacy; static const string _standard_order_hpr_fix; - static const string _table_ids; - static const int _num_table_ids; public: diff --git a/panda/src/gobj/lens.cxx b/panda/src/gobj/lens.cxx index e35ee5ace2..f77f726458 100644 --- a/panda/src/gobj/lens.cxx +++ b/panda/src/gobj/lens.cxx @@ -1275,8 +1275,8 @@ void Lens:: compute_view_hpr() { if ((_user_flags & UF_view_hpr) == 0) { const LMatrix4f &view_mat = get_view_mat(); - LVecBase3f scale, translate; - decompose_matrix(view_mat, scale, _view_hpr, translate, _cs); + LVecBase3f scale, shear, translate; + decompose_matrix(view_mat, scale, shear, _view_hpr, translate, _cs); } adjust_comp_flags(0, CF_view_hpr); } @@ -1371,7 +1371,9 @@ compute_lens_mat() { if ((_user_flags & UF_view_mat) == 0) { if ((_user_flags & UF_view_hpr) != 0) { compose_matrix(_lens_mat, - LVecBase3f(1.0f, 1.0f, 1.0f), _view_hpr, + LVecBase3f(1.0f, 1.0f, 1.0f), + LVecBase3f(0.0f, 0.0f, 0.0f), + _view_hpr, LVecBase3f(0.0f, 0.0f, 0.0f), _cs); } else if ((_user_flags & UF_view_vector) != 0) { diff --git a/panda/src/linmath/compose_matrix.cxx b/panda/src/linmath/compose_matrix.cxx index 69292bfe22..7db46dcf1a 100644 --- a/panda/src/linmath/compose_matrix.cxx +++ b/panda/src/linmath/compose_matrix.cxx @@ -27,5 +27,10 @@ #include "compose_matrix_src.cxx" -const char * const matrix_components = "ijkhprxyz"; -const int num_matrix_components = 9; +const char * const matrix_component_letters = "ijkabchprxyz"; +const double matrix_component_defaults[num_matrix_components] = { + 1.0, 1.0, 1.0, + 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0 +}; diff --git a/panda/src/linmath/compose_matrix.h b/panda/src/linmath/compose_matrix.h index 3eba888bc6..83d99031c2 100644 --- a/panda/src/linmath/compose_matrix.h +++ b/panda/src/linmath/compose_matrix.h @@ -44,17 +44,18 @@ #include "lvec2_ops.h" #include "lvec3_ops.h" +// These define the standard one-letter names for the components in +// the array-accepting forms of compose_matrix() and +// decompose_matrix(). +static const int num_matrix_components = 12; +EXPCL_PANDA extern const char * const matrix_component_letters; +EXPCL_PANDA extern const double matrix_component_defaults[num_matrix_components]; + #include "fltnames.h" #include "compose_matrix_src.h" #include "dblnames.h" #include "compose_matrix_src.h" -// These define the standard one-letter names for the components in -// the array-accepting forms of compose_matrix() and -// decompose_matrix(). -EXPCL_PANDA extern const char * const matrix_components; -EXPCL_PANDA extern const int num_matrix_components; - #endif diff --git a/panda/src/linmath/compose_matrix_src.I b/panda/src/linmath/compose_matrix_src.I index 5817dbb885..eb931f2ded 100644 --- a/panda/src/linmath/compose_matrix_src.I +++ b/panda/src/linmath/compose_matrix_src.I @@ -17,6 +17,103 @@ //////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////// +// Function: compose_matrix +// Description: Computes the 4x4 matrix according to scale, shear, +// rotation, and translation. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH void +compose_matrix(FLOATNAME(LMatrix4) &mat, + const FLOATNAME(LVecBase3) &scale, + const FLOATNAME(LVecBase3) &shear, + const FLOATNAME(LVecBase3) &hpr, + const FLOATNAME(LVecBase3) &translate, + CoordinateSystem cs) { + FLOATNAME(LMatrix3) upper3; + compose_matrix(upper3, scale, shear, hpr, cs); + mat = FLOATNAME(LMatrix4)(upper3, translate); +} + +INLINE_LINMATH void +compose_matrix(FLOATNAME(LMatrix4) &mat, + const FLOATTYPE components[num_matrix_components], + CoordinateSystem cs) { + FLOATNAME(LVector3) scale(components[0], + components[1], + components[2]); + FLOATNAME(LVector3) shear(components[3], + components[4], + components[5]); + FLOATNAME(LVector3) hpr(components[6], + components[7], + components[8]); + FLOATNAME(LVector3) translate(components[9], + components[10], + components[11]); + compose_matrix(mat, scale, shear, hpr, translate, cs); +} + + +//////////////////////////////////////////////////////////////////// +// Function: decompose_matrix +// Description: Extracts out the components of an affine matrix. +// Returns true if the scale, shear, hpr, and translate +// completely describe the matrix, or false if the +// matrix is not affine. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH bool +decompose_matrix(const FLOATNAME(LMatrix4) &mat, + FLOATNAME(LVecBase3) &scale, + FLOATNAME(LVecBase3) &shear, + FLOATNAME(LVecBase3) &hpr, + FLOATNAME(LVecBase3) &translate, + CoordinateSystem cs) { + // Get the translation first. + mat.get_row3(translate,3); + if (!decompose_matrix(mat.get_upper_3(), scale, shear, hpr, cs)) { + return false; + } +#ifndef NDEBUG + return mat.get_col(3).almost_equal(FLOATNAME(LVecBase4)(0.0, 0.0, 0.0, 1.0)); +#else + return true; +#endif +} + +INLINE_LINMATH bool +decompose_matrix(const FLOATNAME(LMatrix4) &mat, + FLOATTYPE components[num_matrix_components], + CoordinateSystem cs) { + FLOATNAME(LVector3) scale, shear, hpr, translate; + bool result = decompose_matrix(mat, scale, shear, hpr, translate, cs); + components[0] = scale[0]; + components[1] = scale[1]; + components[2] = scale[2]; + components[3] = shear[0]; + components[4] = shear[1]; + components[5] = shear[2]; + components[6] = hpr[0]; + components[7] = hpr[1]; + components[8] = hpr[2]; + components[9] = translate[0]; + components[10] = translate[1]; + components[11] = translate[2]; + return result; +} + + + +// The following functions are deprecated; they have been replaced +// with new versions, above, that accept a shear component as well. + +INLINE EXPCL_PANDA void +compose_matrix(FLOATNAME(LMatrix3) &mat, + const FLOATNAME(LVecBase3) &scale, + const FLOATNAME(LVecBase3) &hpr, + CoordinateSystem cs) { + compose_matrix(mat, scale, FLOATNAME(LVecBase3)(0, 0, 0), hpr, cs); +} + //////////////////////////////////////////////////////////////////// // Function: compose_matrix // Description: Computes the 4x4 matrix according to scale, rotation, @@ -33,20 +130,16 @@ compose_matrix(FLOATNAME(LMatrix4) &mat, mat = FLOATNAME(LMatrix4)(upper3, translate); } -INLINE_LINMATH void -compose_matrix(FLOATNAME(LMatrix4) &mat, - const FLOATTYPE components[9], - CoordinateSystem cs) { - FLOATNAME(LVector3) scale(components[0], - components[1], - components[2]); - FLOATNAME(LVector3) hpr(components[3], - components[4], - components[5]); - FLOATNAME(LVector3) translate(components[6], - components[7], - components[8]); - compose_matrix(mat, scale, hpr, translate, cs); +INLINE EXPCL_PANDA bool +decompose_matrix(const FLOATNAME(LMatrix3) &mat, + FLOATNAME(LVecBase3) &scale, + FLOATNAME(LVecBase3) &hpr, + CoordinateSystem cs) { + FLOATNAME(LVecBase3) shear; + if (!decompose_matrix(mat, scale, shear, hpr, cs)) { + return false; + } + return shear.almost_equal(FLOATNAME(LVecBase3)::zero()); } @@ -68,49 +161,3 @@ decompose_matrix(const FLOATNAME(LMatrix4) &mat, mat.get_row3(translate,3); return decompose_matrix(mat.get_upper_3(), scale, hpr, cs); } - -//////////////////////////////////////////////////////////////////// -// Function: decompose_matrix -// Description: Extracts out the components of an affine matrix. -// Returns true if the scale, hpr, translate -// completely describe the matrix, or false if there is -// also a shear component or if the matrix is not -// affine. -// -// This flavor of the function accepts an expected roll -// amount. This amount will be used as the roll -// component, rather than attempting to determine roll -// by examining the matrix; this helps alleviate roll -// instability due to roundoff errors or gimbal lock. -//////////////////////////////////////////////////////////////////// -INLINE_LINMATH bool -decompose_matrix(const FLOATNAME(LMatrix4) &mat, - FLOATNAME(LVecBase3) &scale, - FLOATNAME(LVecBase3) &hpr, - FLOATNAME(LVecBase3) &translate, - FLOATTYPE roll, - CoordinateSystem cs) { - // Get the translation first. - mat.get_row3(translate,3); - return decompose_matrix(mat.get_upper_3(), scale, hpr, roll, cs); -} - -INLINE_LINMATH bool -decompose_matrix(const FLOATNAME(LMatrix4) &mat, - FLOATTYPE components[9], - CoordinateSystem cs) { - FLOATNAME(LVector3) scale, hpr, translate; - if (!decompose_matrix(mat, scale, hpr, translate, cs)) { - return false; - } - components[0] = scale[0]; - components[1] = scale[1]; - components[2] = scale[2]; - components[3] = hpr[0]; - components[4] = hpr[1]; - components[5] = hpr[2]; - components[6] = translate[0]; - components[7] = translate[1]; - components[8] = translate[2]; - return true; -} diff --git a/panda/src/linmath/compose_matrix_src.cxx b/panda/src/linmath/compose_matrix_src.cxx index 1efcc5a59f..a140966925 100644 --- a/panda/src/linmath/compose_matrix_src.cxx +++ b/panda/src/linmath/compose_matrix_src.cxx @@ -19,11 +19,13 @@ //////////////////////////////////////////////////////////////////// // Function: compose_matrix -// Description: Computes the 3x3 matrix from scale and rotation. +// Description: Computes the 3x3 matrix from scale, shear, and +// rotation. //////////////////////////////////////////////////////////////////// void compose_matrix(FLOATNAME(LMatrix3) &mat, const FLOATNAME(LVecBase3) &scale, + const FLOATNAME(LVecBase3) &shear, const FLOATNAME(LVecBase3) &hpr, CoordinateSystem cs) { @@ -31,16 +33,18 @@ compose_matrix(FLOATNAME(LMatrix3) &mat, // as default until legacy tools are fixed to work with correct way if (temp_hpr_fix) { - mat.scale_multiply(scale, - FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[2], FLOATNAME(LVector3)::forward(cs), cs) * - FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[1], FLOATNAME(LVector3)::right(cs), cs) * - FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[0], FLOATNAME(LVector3)::up(cs), cs)); + mat = + FLOATNAME(LMatrix3)::scale_shear_mat(scale, shear, cs) * + FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[2], FLOATNAME(LVector3)::forward(cs), cs) * + FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[1], FLOATNAME(LVector3)::right(cs), cs) * + FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[0], FLOATNAME(LVector3)::up(cs), cs); } else { - mat.scale_multiply(scale, - FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[1], FLOATNAME(LVector3)::right(cs), cs) * - FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[0], FLOATNAME(LVector3)::up(cs), cs) * - FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[2], FLOATNAME(LVector3)::back(cs), cs)); + mat = + FLOATNAME(LMatrix3)::scale_shear_mat(scale, shear, cs) * + FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[1], FLOATNAME(LVector3)::right(cs), cs) * + FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[0], FLOATNAME(LVector3)::up(cs), cs) * + FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[2], FLOATNAME(LVector3)::back(cs), cs); } } @@ -511,13 +515,15 @@ unwind_zup_rotation(FLOATNAME(LMatrix3) &mat, FLOATNAME(LVecBase3) &hpr, //////////////////////////////////////////////////////////////////// // Function: decompose_matrix // Description: Extracts out the components of a 3x3 rotation matrix. -// Returns true if the scale and hpr completely describe -// the matrix, or false if there is also a shear -// component or if the matrix is not affine. +// Returns true if successful, or false if there was an +// error. Since a 3x3 matrix always contains an affine +// transform, this should succeed in the normal case; +// singular transforms are not treated as an error. //////////////////////////////////////////////////////////////////// bool decompose_matrix(const FLOATNAME(LMatrix3) &mat, FLOATNAME(LVecBase3) &scale, + FLOATNAME(LVecBase3) &shear, FLOATNAME(LVecBase3) &hpr, CoordinateSystem cs) { if (cs == CS_default) { @@ -595,29 +601,28 @@ decompose_matrix(const FLOATNAME(LMatrix3) &mat, << "after unwind, mat is " << new_mat << "\n"; } - scale[0] = new_mat._m.m._00; - scale[1] = new_mat._m.m._11; - scale[2] = new_mat._m.m._22; - /* - if (is_left_handed) { - scale[0] = -new_mat._m.m._00; - scale[1] = -new_mat._m.m._11; - } - */ - - bool has_no_shear = - (fabs(new_mat(0, 1)) + fabs(new_mat(0, 2)) + - fabs(new_mat(1, 0)) + fabs(new_mat(1, 2)) + - fabs(new_mat(2, 0)) + fabs(new_mat(2, 1))) < 0.0001; + scale.set(new_mat(0, 0), new_mat(1, 1), new_mat(2, 2)); - /* - if (!has_no_shear) { - linmath_cat.info() << "shear:\n"; - new_mat.write(linmath_cat.info(false), 2); + // Normalize the scale out of the shear components, and return the + // shear. + if (scale[0] != 0.0) { + new_mat(0, 1) /= scale[0]; + new_mat(0, 2) /= scale[0]; } - */ + if (scale[1] != 0.0) { + new_mat(1, 0) /= scale[1]; + new_mat(1, 2) /= scale[1]; + } + if (scale[2] != 0.0) { + new_mat(2, 0) /= scale[2]; + new_mat(2, 1) /= scale[2]; + } + + shear.set(new_mat(0, 1) + new_mat(1, 0), + new_mat(2, 0) + new_mat(0, 2), + new_mat(2, 1) + new_mat(1, 2)); - return has_no_shear; + return true; } //////////////////////////////////////////////////////////////////// @@ -632,6 +637,10 @@ decompose_matrix(const FLOATNAME(LMatrix3) &mat, // component, rather than attempting to determine roll // by examining the matrix; this helps alleviate roll // instability due to roundoff errors or gimbal lock. +// +// This function is deprecated and will soon be removed, +// especially when the need for temp_hpr_fix is +// eliminated. //////////////////////////////////////////////////////////////////// bool decompose_matrix(const FLOATNAME(LMatrix3) &mat, diff --git a/panda/src/linmath/compose_matrix_src.h b/panda/src/linmath/compose_matrix_src.h index 2b9ab60799..b5e70b31e2 100644 --- a/panda/src/linmath/compose_matrix_src.h +++ b/panda/src/linmath/compose_matrix_src.h @@ -19,6 +19,49 @@ BEGIN_PUBLISH EXPCL_PANDA void +compose_matrix(FLOATNAME(LMatrix3) &mat, + const FLOATNAME(LVecBase3) &scale, + const FLOATNAME(LVecBase3) &shear, + const FLOATNAME(LVecBase3) &hpr, + CoordinateSystem cs = CS_default); + +INLINE_LINMATH void +compose_matrix(FLOATNAME(LMatrix4) &mat, + const FLOATNAME(LVecBase3) &scale, + const FLOATNAME(LVecBase3) &shear, + const FLOATNAME(LVecBase3) &hpr, + const FLOATNAME(LVecBase3) &translate, + CoordinateSystem cs = CS_default); + +INLINE_LINMATH void +compose_matrix(FLOATNAME(LMatrix4) &mat, const FLOATTYPE components[num_matrix_components], + CoordinateSystem cs = CS_default); + +EXPCL_PANDA bool +decompose_matrix(const FLOATNAME(LMatrix3) &mat, + FLOATNAME(LVecBase3) &scale, + FLOATNAME(LVecBase3) &shear, + FLOATNAME(LVecBase3) &hpr, + CoordinateSystem cs = CS_default); + +INLINE_LINMATH bool +decompose_matrix(const FLOATNAME(LMatrix4) &mat, + FLOATNAME(LVecBase3) &scale, + FLOATNAME(LVecBase3) &shear, + FLOATNAME(LVecBase3) &hpr, + FLOATNAME(LVecBase3) &translate, + CoordinateSystem cs = CS_default); + +INLINE_LINMATH bool +decompose_matrix(const FLOATNAME(LMatrix4) &mat, FLOATTYPE components[num_matrix_components], + CoordinateSystem CS = CS_default); + + + +// The following functions are deprecated; they have been replaced +// with new versions, above, that accept a shear component as well. + +INLINE EXPCL_PANDA void compose_matrix(FLOATNAME(LMatrix3) &mat, const FLOATNAME(LVecBase3) &scale, const FLOATNAME(LVecBase3) &hpr, @@ -31,11 +74,7 @@ compose_matrix(FLOATNAME(LMatrix4) &mat, const FLOATNAME(LVecBase3) &translate, CoordinateSystem cs = CS_default); -INLINE_LINMATH void -compose_matrix(FLOATNAME(LMatrix4) &mat, const FLOATTYPE components[9], - CoordinateSystem cs = CS_default); - -EXPCL_PANDA bool +INLINE EXPCL_PANDA bool decompose_matrix(const FLOATNAME(LMatrix3) &mat, FLOATNAME(LVecBase3) &scale, FLOATNAME(LVecBase3) &hpr, @@ -55,18 +94,6 @@ decompose_matrix(const FLOATNAME(LMatrix4) &mat, FLOATNAME(LVecBase3) &translate, CoordinateSystem cs = CS_default); -INLINE_LINMATH bool -decompose_matrix(const FLOATNAME(LMatrix4) &mat, - FLOATNAME(LVecBase3) &scale, - FLOATNAME(LVecBase3) &hpr, - FLOATNAME(LVecBase3) &translate, - FLOATTYPE roll, - CoordinateSystem cs); - -INLINE_LINMATH bool -decompose_matrix(const FLOATNAME(LMatrix4) &mat, FLOATTYPE components[9], - CoordinateSystem CS = CS_default); - END_PUBLISH #include "compose_matrix_src.I" diff --git a/panda/src/linmath/lmatrix3_src.I b/panda/src/linmath/lmatrix3_src.I index 58f864d3b9..90fd6ddc59 100644 --- a/panda/src/linmath/lmatrix3_src.I +++ b/panda/src/linmath/lmatrix3_src.I @@ -558,28 +558,6 @@ multiply(const FLOATNAME(LMatrix3) &other1, const FLOATNAME(LMatrix3) &other2) { MATRIX3_PRODUCT((*this),other1,other2); } -// this = scale_mat(scale_vector) * other_mat, efficiently -INLINE_LINMATH void FLOATNAME(LMatrix3):: -scale_multiply(const FLOATNAME(LVecBase3) &scale_vector,const FLOATNAME(LMatrix3) &other_mat) { - #ifdef _DEBUG - assert(&other_mat != this); - #endif - - // optimize for 0.0 or 1.0 factors? - - _m.m._00 = other_mat._m.m._00 * scale_vector._v.v._0; - _m.m._01 = other_mat._m.m._01 * scale_vector._v.v._0; - _m.m._02 = other_mat._m.m._02 * scale_vector._v.v._0; - - _m.m._10 = other_mat._m.m._10 * scale_vector._v.v._1; - _m.m._11 = other_mat._m.m._11 * scale_vector._v.v._1; - _m.m._12 = other_mat._m.m._12 * scale_vector._v.v._1; - - _m.m._20 = other_mat._m.m._20 * scale_vector._v.v._2; - _m.m._21 = other_mat._m.m._21 * scale_vector._v.v._2; - _m.m._22 = other_mat._m.m._22 * scale_vector._v.v._2; -} - //////////////////////////////////////////////////////////////////// // Function: LMatrix3::matrix * scalar // Access: Public @@ -1102,10 +1080,9 @@ scale_mat(FLOATTYPE sx, FLOATTYPE sy, FLOATTYPE sz) { // shear in each of the three planes. //////////////////////////////////////////////////////////////////// INLINE_LINMATH FLOATNAME(LMatrix3) FLOATNAME(LMatrix3):: -shear_mat(const FLOATNAME(LVecBase3) &shear) { - return FLOATNAME(LMatrix3)(1.0f, 0.0f, 0.0f, - shear._v.v._0, 1.0f, 0.0f, - shear._v.v._1, shear._v.v._2, 1.0f); +shear_mat(const FLOATNAME(LVecBase3) &shear, CoordinateSystem cs) { + return scale_shear_mat(FLOATNAME(LVecBase3)(1.0f, 1.0f, 1.0f), + shear, cs); } //////////////////////////////////////////////////////////////////// @@ -1115,10 +1092,24 @@ shear_mat(const FLOATNAME(LVecBase3) &shear) { // shear in each of the three planes. //////////////////////////////////////////////////////////////////// INLINE_LINMATH FLOATNAME(LMatrix3) FLOATNAME(LMatrix3):: -shear_mat(FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz) { - return FLOATNAME(LMatrix3)(1.0f, 0.0f, 0.0f, - shxy, 1.0f, 0.0f, - shxz, shyz, 1.0f); +shear_mat(FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz, CoordinateSystem cs) { + return scale_shear_mat(1.0f, 1.0f, 1.0f, + shxy, shxz, shyz, cs); +} + +//////////////////////////////////////////////////////////////////// +// Function: LMatrix::scale_shear_mat +// Access: Public, Static +// Description: Returns a matrix that applies the indicated +// scale and shear. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH FLOATNAME(LMatrix3) FLOATNAME(LMatrix3):: +scale_shear_mat(FLOATTYPE sx, FLOATTYPE sy, FLOATTYPE sz, + FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz, + CoordinateSystem cs) { + return scale_shear_mat(FLOATNAME(LVecBase3)(sx, sy, sz), + FLOATNAME(LVecBase3)(shxy, shxz, shyz), + cs); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/linmath/lmatrix3_src.cxx b/panda/src/linmath/lmatrix3_src.cxx index bd1d1822df..c2ceaeefed 100644 --- a/panda/src/linmath/lmatrix3_src.cxx +++ b/panda/src/linmath/lmatrix3_src.cxx @@ -49,6 +49,77 @@ const FLOATNAME(LMatrix3) FLOATNAME(LMatrix3)::_lz_to_ry_mat = const FLOATNAME(LMatrix3) FLOATNAME(LMatrix3)::_ly_to_rz_mat = FLOATNAME(LMatrix3)::_flip_z_mat * FLOATNAME(LMatrix3)::_y_to_z_up_mat; + +//////////////////////////////////////////////////////////////////// +// Function: LMatrix::scale_shear_mat +// Access: Public, Static +// Description: Returns a matrix that applies the indicated +// scale and shear. +//////////////////////////////////////////////////////////////////// +FLOATNAME(LMatrix3) FLOATNAME(LMatrix3):: +scale_shear_mat(const FLOATNAME(LVecBase3) &scale, + const FLOATNAME(LVecBase3) &shear, + CoordinateSystem cs) { + if (cs == CS_default) { + cs = default_coordinate_system; + } + + // We have to match the placement of the shear components in the + // matrix to the way we extract out the rotation in + // decompose_matrix(). Therefore, the shear is sensitive to the + // coordinate system. + + switch (cs) { + case CS_zup_right: + if (temp_hpr_fix) { + return FLOATNAME(LMatrix3)(scale._v.v._0, shear._v.v._0 * scale._v.v._0, 0.0f, + 0.0f, scale._v.v._1, 0.0f, + shear._v.v._1 * scale._v.v._2, shear._v.v._2 * scale._v.v._2, scale._v.v._2); + } else { + return FLOATNAME(LMatrix3)(scale._v.v._0, 0.0f, 0.0f, + shear._v.v._0 * scale._v.v._1, scale._v.v._1, 0.0f, + shear._v.v._1 * scale._v.v._2, shear._v.v._2 * scale._v.v._2, scale._v.v._2); + } + + case CS_zup_left: + if (temp_hpr_fix) { + return FLOATNAME(LMatrix3)(scale._v.v._0, shear._v.v._0 * scale._v.v._0, 0.0f, + 0.0f, scale._v.v._1, 0.0f, + -shear._v.v._1 * scale._v.v._2, -shear._v.v._2 * scale._v.v._2, scale._v.v._2); + } else { + return FLOATNAME(LMatrix3)(scale._v.v._0, 0.0f, 0.0f, + shear._v.v._0 * scale._v.v._1, scale._v.v._1, 0.0f, + -shear._v.v._1 * scale._v.v._2, -shear._v.v._2 * scale._v.v._2, scale._v.v._2); + } + + case CS_yup_right: + if (temp_hpr_fix) { + return FLOATNAME(LMatrix3)(scale._v.v._0, 0.0f, shear._v.v._1 * scale._v.v._0, + shear._v.v._0 * scale._v.v._1, scale._v.v._1, shear._v.v._2 * scale._v.v._1, + 0.0f, 0.0f, scale._v.v._2); + } else { + return FLOATNAME(LMatrix3)(scale._v.v._0, 0.0f, 0.0f, + shear._v.v._0 * scale._v.v._1, scale._v.v._1, shear._v.v._2 * scale._v.v._1, + shear._v.v._1 * scale._v.v._2, 0.0f, scale._v.v._2); + } + + case CS_yup_left: + if (temp_hpr_fix) { + return FLOATNAME(LMatrix3)(scale._v.v._0, 0.0f, -shear._v.v._1 * scale._v.v._0, + shear._v.v._0 * scale._v.v._1, scale._v.v._1, -shear._v.v._2 * scale._v.v._1, + 0.0f, 0.0f, scale._v.v._2); + } else { + return FLOATNAME(LMatrix3)(scale._v.v._0, 0.0f, 0.0f, + shear._v.v._0 * scale._v.v._1, scale._v.v._1, -shear._v.v._2 * scale._v.v._1, + -shear._v.v._1 * scale._v.v._2, 0.0f, scale._v.v._2); + } + } + + linmath_cat.error() + << "Invalid coordinate system value!\n"; + return _ident_mat; +} + //////////////////////////////////////////////////////////////////// // Function: LMatrix::convert_mat // Access: Public, Static diff --git a/panda/src/linmath/lmatrix3_src.h b/panda/src/linmath/lmatrix3_src.h index fca0c34107..b882d111a8 100644 --- a/panda/src/linmath/lmatrix3_src.h +++ b/panda/src/linmath/lmatrix3_src.h @@ -99,9 +99,6 @@ PUBLISHED: INLINE_LINMATH FLOATNAME(LMatrix3) operator * (FLOATTYPE scalar) const; INLINE_LINMATH FLOATNAME(LMatrix3) operator / (FLOATTYPE scalar) const; - // this = scale_mat(scale_vector) * other_mat, efficiently - INLINE_LINMATH void scale_multiply(const FLOATNAME(LVecBase3) &scale_vector,const FLOATNAME(LMatrix3) &other_mat); - INLINE_LINMATH FLOATNAME(LMatrix3) &operator += (const FLOATNAME(LMatrix3) &other); INLINE_LINMATH FLOATNAME(LMatrix3) &operator -= (const FLOATNAME(LMatrix3) &other); @@ -158,9 +155,20 @@ PUBLISHED: scale_mat(FLOATTYPE sx, FLOATTYPE sy, FLOATTYPE sz); static INLINE_LINMATH FLOATNAME(LMatrix3) - shear_mat(const FLOATNAME(LVecBase3) &shear); + shear_mat(const FLOATNAME(LVecBase3) &shear, + CoordinateSystem cs = CS_default); static INLINE_LINMATH FLOATNAME(LMatrix3) - shear_mat(FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz); + shear_mat(FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz, + CoordinateSystem cs = CS_default); + + static FLOATNAME(LMatrix3) + scale_shear_mat(const FLOATNAME(LVecBase3) &scale, + const FLOATNAME(LVecBase3) &shear, + CoordinateSystem cs = CS_default); + static INLINE_LINMATH FLOATNAME(LMatrix3) + scale_shear_mat(FLOATTYPE sx, FLOATTYPE sy, FLOATTYPE sz, + FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz, + CoordinateSystem cs = CS_default); static const FLOATNAME(LMatrix3) &convert_mat(CoordinateSystem from, CoordinateSystem to); diff --git a/panda/src/linmath/lmatrix4_src.I b/panda/src/linmath/lmatrix4_src.I index 11def498f6..161937040b 100644 --- a/panda/src/linmath/lmatrix4_src.I +++ b/panda/src/linmath/lmatrix4_src.I @@ -730,31 +730,6 @@ multiply(const FLOATNAME(LMatrix4) &other1, const FLOATNAME(LMatrix4) &other2) { MATRIX4_PRODUCT((*this),other1,other2); } -// this = scale_mat(scale_vector) * other_mat, efficiently -INLINE_LINMATH void FLOATNAME(LMatrix4):: -scale_multiply(const FLOATNAME(LVecBase3) &scale_vector,const FLOATNAME(LMatrix4) &other_mat) { - #ifdef _DEBUG - assert(&other_mat != this); - #endif - - // optimize for 0.0 or 1.0 factors? - - _m.m._00 = other_mat._m.m._00 * scale_vector._v.v._0; - _m.m._01 = other_mat._m.m._01 * scale_vector._v.v._0; - _m.m._02 = other_mat._m.m._02 * scale_vector._v.v._0; - _m.m._03 = other_mat._m.m._03 * scale_vector._v.v._0; - - _m.m._10 = other_mat._m.m._10 * scale_vector._v.v._1; - _m.m._11 = other_mat._m.m._11 * scale_vector._v.v._1; - _m.m._12 = other_mat._m.m._12 * scale_vector._v.v._1; - _m.m._13 = other_mat._m.m._13 * scale_vector._v.v._1; - - _m.m._20 = other_mat._m.m._20 * scale_vector._v.v._2; - _m.m._21 = other_mat._m.m._21 * scale_vector._v.v._2; - _m.m._22 = other_mat._m.m._22 * scale_vector._v.v._2; - _m.m._23 = other_mat._m.m._23 * scale_vector._v.v._2; -} - //////////////////////////////////////////////////////////////////// // Function: LMatrix4::matrix * scalar // Access: Public @@ -1359,11 +1334,9 @@ scale_mat(FLOATTYPE scale) { // shear in each of the three planes. //////////////////////////////////////////////////////////////////// INLINE_LINMATH FLOATNAME(LMatrix4) FLOATNAME(LMatrix4):: -shear_mat(const FLOATNAME(LVecBase3) &shear) { - return FLOATNAME(LMatrix4)(1.0f, 0.0f, 0.0f, 0.0f, - shear._v.v._0, 1.0f, 0.0f, 0.0f, - shear._v.v._1, shear._v.v._2, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f); +shear_mat(const FLOATNAME(LVecBase3) &shear, CoordinateSystem cs) { + return scale_shear_mat(FLOATNAME(LVecBase3)(1.0f, 1.0f, 1.0f), + shear, cs); } //////////////////////////////////////////////////////////////////// @@ -1373,11 +1346,38 @@ shear_mat(const FLOATNAME(LVecBase3) &shear) { // shear in each of the three planes. //////////////////////////////////////////////////////////////////// INLINE_LINMATH FLOATNAME(LMatrix4) FLOATNAME(LMatrix4):: -shear_mat(FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz) { - return FLOATNAME(LMatrix4)(1.0f, 0.0f, 0.0f, 0.0f, - shxy, 1.0f, 0.0f, 0.0f, - shxz, shyz, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f); +shear_mat(FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz, + CoordinateSystem cs) { + return scale_shear_mat(1.0f, 1.0f, 1.0f, + shxy, shxz, shyz, cs); +} + +//////////////////////////////////////////////////////////////////// +// Function: LMatrix::scale_shear_mat +// Access: Public, Static +// Description: Returns a matrix that applies the indicated +// scale and shear. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH FLOATNAME(LMatrix4) FLOATNAME(LMatrix4):: +scale_shear_mat(const FLOATNAME(LVecBase3) &scale, + const FLOATNAME(LVecBase3) &shear, + CoordinateSystem cs) { + return FLOATNAME(LMatrix4)(FLOATNAME(LMatrix3)::scale_shear_mat(scale, shear, cs)); +} + +//////////////////////////////////////////////////////////////////// +// Function: LMatrix::scale_shear_mat +// Access: Public, Static +// Description: Returns a matrix that applies the indicated +// scale and shear. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH FLOATNAME(LMatrix4) FLOATNAME(LMatrix4):: +scale_shear_mat(FLOATTYPE sx, FLOATTYPE sy, FLOATTYPE sz, + FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz, + CoordinateSystem cs) { + return scale_shear_mat(FLOATNAME(LVecBase3)(sx, sy, sz), + FLOATNAME(LVecBase3)(shxy, shxz, shyz), + cs); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/linmath/lmatrix4_src.h b/panda/src/linmath/lmatrix4_src.h index 1567a4e8dc..a2b98de055 100644 --- a/panda/src/linmath/lmatrix4_src.h +++ b/panda/src/linmath/lmatrix4_src.h @@ -104,9 +104,6 @@ PUBLISHED: // this = other1 * other2 INLINE_LINMATH void multiply(const FLOATNAME(LMatrix4) &other1, const FLOATNAME(LMatrix4) &other2); - // this = scale_mat(scale_vector) * other_mat, efficiently - INLINE_LINMATH void scale_multiply(const FLOATNAME(LVecBase3) &scale_vector,const FLOATNAME(LMatrix4) &other_mat); - INLINE_LINMATH FLOATNAME(LMatrix4) operator * (const FLOATNAME(LMatrix4) &other) const; INLINE_LINMATH FLOATNAME(LMatrix4) operator * (FLOATTYPE scalar) const; @@ -153,9 +150,20 @@ PUBLISHED: scale_mat(FLOATTYPE scale); static INLINE_LINMATH FLOATNAME(LMatrix4) - shear_mat(const FLOATNAME(LVecBase3) &shear); + shear_mat(const FLOATNAME(LVecBase3) &shear, + CoordinateSystem cs = CS_default); static INLINE_LINMATH FLOATNAME(LMatrix4) - shear_mat(FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz); + shear_mat(FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz, + CoordinateSystem cs = CS_default); + + static INLINE_LINMATH FLOATNAME(LMatrix4) + scale_shear_mat(const FLOATNAME(LVecBase3) &scale, + const FLOATNAME(LVecBase3) &shear, + CoordinateSystem cs = CS_default); + static INLINE_LINMATH FLOATNAME(LMatrix4) + scale_shear_mat(FLOATTYPE sx, FLOATTYPE sy, FLOATTYPE sz, + FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz, + CoordinateSystem cs = CS_default); INLINE_LINMATH static const FLOATNAME(LMatrix4) &y_to_z_up_mat(); INLINE_LINMATH static const FLOATNAME(LMatrix4) &z_to_y_up_mat(); diff --git a/panda/src/mathutil/fftCompressor.cxx b/panda/src/mathutil/fftCompressor.cxx index 0b138c6e48..8e4fb0c365 100644 --- a/panda/src/mathutil/fftCompressor.cxx +++ b/panda/src/mathutil/fftCompressor.cxx @@ -19,9 +19,9 @@ #include "fftCompressor.h" #include "config_mathutil.h" -#include -#include -#include +#include "datagram.h" +#include "datagramIterator.h" +#include "compose_matrix.h" #include #ifdef HAVE_FFTW @@ -348,7 +348,8 @@ write_hprs(Datagram &datagram, const LVecBase3f *array, int length) { m20, m21, m22; for (int i = 0; i < length; i++) { LMatrix3f mat; - compose_matrix(mat, LVecBase3f(1.0, 1.0, 1.0), array[i]); + compose_matrix(mat, LVecBase3f(1.0, 1.0, 1.0), LVecBase3f(0.0, 0.0, 0.0), + array[i]); m00.push_back(mat(0, 0)); m01.push_back(mat(0, 1)); m02.push_back(mat(0, 2)); @@ -390,7 +391,8 @@ write_hprs(Datagram &datagram, const LVecBase3f *array, int length) { for (int i = 0; i < length; i++) { LMatrix3f mat; - compose_matrix(mat, LVecBase3f(1.0, 1.0, 1.0), array[i]); + compose_matrix(mat, LVecBase3f(1.0, 1.0, 1.0), LVecBase3f(0.0, 0.0, 0.0), + array[i]); if (_transpose_quats) { mat.transpose_in_place(); } @@ -418,31 +420,16 @@ write_hprs(Datagram &datagram, const LVecBase3f *array, int length) { rot.extract_to_matrix(mat2); if (!mat.almost_equal(mat2, 0.0001)) { LVecBase3f hpr1, hpr2; - LVecBase3f scale; - bool d1 = decompose_matrix(mat, scale, hpr1); - bool d2 = decompose_matrix(mat2, scale, hpr2); + LVecBase3f scale, shear; + decompose_matrix(mat, scale, shear, hpr1); + decompose_matrix(mat2, scale, shear, hpr2); mathutil_cat.warning() << "Converted hpr to quaternion incorrectly!\n" - << " Source hpr: " << array[i]; - if (d1) { - mathutil_cat.warning(false) - << ", or " << hpr1 << "\n"; - } else { - mathutil_cat.warning(false) - << ", incorrectly converted to the non-ortho matrix:\n"; - mat2.write(mathutil_cat.warning(false), 4); - } + << " Source hpr: " << array[i] << ", or " << hpr1 << "\n"; mathutil_cat.warning(false) - << " Quaternion: " << rot << "\n"; - if (d2) { - mathutil_cat.warning(false) - << " Which represents: hpr " << hpr2 << " scale " - << scale << "\n"; - } else { - mathutil_cat.warning(false) - << " Which is incorrectly converted to the following non-ortho matrix:\n"; - mat2.write(mathutil_cat.warning(false), 4); - } + << " Quaternion: " << rot << "\n" + << " Which represents: hpr " << hpr2 << " scale " + << scale << "\n"; } } #endif @@ -628,16 +615,9 @@ read_hprs(DatagramIterator &di, vector_LVecBase3f &array) { LMatrix3f mat(m00[i], m01[i], m02[i], m10[i], m11[i], m12[i], m20[i], m21[i], m22[i]); - LVecBase3f scale, hpr; - bool success = decompose_matrix(mat, scale, hpr); - if (success) { - array.push_back(hpr); - } else { - mathutil_cat.error() - << "Unable to decompose matrix:\n"; - mat.write(mathutil_cat.error(false), 2); - array.push_back(LVecBase3f(0.0, 0.0, 0.0)); - } + LVecBase3f scale, shear, hpr; + decompose_matrix(mat, scale, shear, hpr); + array.push_back(hpr); } } @@ -694,10 +674,8 @@ read_hprs(DatagramIterator &di, vector_LVecBase3f &array) { if (_transpose_quats) { mat.transpose_in_place(); } - LVecBase3f scale, hpr; - bool success = decompose_matrix(mat, scale, hpr); - nassertr(success, false); - + LVecBase3f scale, shear, hpr; + decompose_matrix(mat, scale, shear, hpr); array.push_back(hpr); } } diff --git a/panda/src/mathutil/fftCompressor.h b/panda/src/mathutil/fftCompressor.h index d03a4ec7ef..f46e44cc18 100644 --- a/panda/src/mathutil/fftCompressor.h +++ b/panda/src/mathutil/fftCompressor.h @@ -19,12 +19,12 @@ #ifndef FFTCOMPRESSOR_H #define FFTCOMPRESSOR_H -#include +#include "pandabase.h" -#include -#include -#include -#include +#include "pointerToArray.h" +#include "vector_float.h" +#include "vector_double.h" +#include "vector_LVecBase3f.h" class Datagram; class DatagramIterator; diff --git a/panda/src/parametrics/parametricCurveCollection.cxx b/panda/src/parametrics/parametricCurveCollection.cxx index aecd80ae1c..6238d11ef6 100644 --- a/panda/src/parametrics/parametricCurveCollection.cxx +++ b/panda/src/parametrics/parametricCurveCollection.cxx @@ -568,7 +568,10 @@ evaluate(float t, LMatrix4f &result, CoordinateSystem cs) const { return false; } - compose_matrix(result, LVecBase3f(1.0f, 1.0f, 1.0f), hpr, xyz, cs); + compose_matrix(result, + LVecBase3f(1.0f, 1.0f, 1.0f), + LVecBase3f(0.0f, 0.0f, 0.0f), + hpr, xyz, cs); return true; } @@ -935,9 +938,8 @@ determine_hpr(float t, ParametricCurve *xyz_curve, LVecBase3f &hpr) const { LMatrix3f mat; look_at(mat, tangent); - LVecBase3f scale; - decompose_matrix(mat, scale, hpr); - return true; + LVecBase3f scale, shear; + return decompose_matrix(mat, scale, shear, hpr); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/pgraph/config_pgraph.cxx b/panda/src/pgraph/config_pgraph.cxx index 79dadcda63..e5cff482e4 100644 --- a/panda/src/pgraph/config_pgraph.cxx +++ b/panda/src/pgraph/config_pgraph.cxx @@ -110,12 +110,6 @@ const bool paranoid_compose = config_pgraph.GetBool("paranoid-compose", false); // by matrix. const bool compose_componentwise = config_pgraph.GetBool("compose-componentwise", true); -// Set this true to load transforms from bam files as componentwise -// transforms always, even if they were stored as matrix transforms. -// This works around old versions of the egg loader that only stored -// matrix transforms. -const bool bams_componentwise = config_pgraph.GetBool("bams-componentwise", false); - // Set this false to disable TransparencyAttrib::M_dual altogether // (and use M_alpha in its place). const bool m_dual = config_pgraph.GetBool("m-dual", true); diff --git a/panda/src/pgraph/config_pgraph.h b/panda/src/pgraph/config_pgraph.h index ed6be7675d..ef589c16c8 100644 --- a/panda/src/pgraph/config_pgraph.h +++ b/panda/src/pgraph/config_pgraph.h @@ -33,7 +33,6 @@ extern const bool fake_view_frustum_cull; extern const bool unambiguous_graph; extern const bool paranoid_compose; extern const bool compose_componentwise; -extern const bool bams_componentwise; extern const bool m_dual; extern const bool m_dual_opaque; diff --git a/panda/src/pgraph/nodePath.I b/panda/src/pgraph/nodePath.I index b42c953402..19cbf9f2cb 100644 --- a/panda/src/pgraph/nodePath.I +++ b/panda/src/pgraph/nodePath.I @@ -522,6 +522,32 @@ get_sz() const { return get_scale()[2]; } +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_shear +// Access: Published +// Description: Sets the shear component of the transform, +// leaving translation, rotation, and scale untouched. +//////////////////////////////////////////////////////////////////// +INLINE void NodePath:: +set_shear(float shxy, float shxz, float shyz) { + set_shear(LVecBase3f(shxy, shxz, shyz)); +} + +INLINE float NodePath:: +get_shxy() const { + return get_shear()[0]; +} + +INLINE float NodePath:: +get_shxz() const { + return get_shear()[1]; +} + +INLINE float NodePath:: +get_shyz() const { + return get_shear()[2]; +} + //////////////////////////////////////////////////////////////////// // Function: NodePath::set_pos_hpr // Access: Published @@ -705,6 +731,38 @@ get_sz(const NodePath &other) const { return get_scale(other)[2]; } +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_shear +// Access: Published +// Description: Sets the shear component of the transform, +// relative to the other node. +//////////////////////////////////////////////////////////////////// +INLINE void NodePath:: +set_shear(const NodePath &other, float shxy, float shxz, float shyz) { + set_shear(other, LPoint3f(shxy, shxz, shyz)); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePath::get_shear +// Access: Published +// Description: Returns the relative shear of the referenced node +// as seen from the other node. +//////////////////////////////////////////////////////////////////// +INLINE float NodePath:: +get_shxy(const NodePath &other) const { + return get_shear(other)[0]; +} + +INLINE float NodePath:: +get_shxz(const NodePath &other) const { + return get_shear(other)[1]; +} + +INLINE float NodePath:: +get_shyz(const NodePath &other) const { + return get_shear(other)[2]; +} + //////////////////////////////////////////////////////////////////// // Function: NodePath::set_pos_hpr // Access: Published diff --git a/panda/src/pgraph/nodePath.cxx b/panda/src/pgraph/nodePath.cxx index b9450e5897..7eb2fcb58c 100644 --- a/panda/src/pgraph/nodePath.cxx +++ b/panda/src/pgraph/nodePath.cxx @@ -39,7 +39,6 @@ #include "transparencyAttrib.h" #include "materialPool.h" #include "look_at.h" -#include "compose_matrix.h" #include "plist.h" #include "boundingSphere.h" #include "geomNode.h" @@ -692,19 +691,6 @@ get_hpr() const { return transform->get_hpr(); } -//////////////////////////////////////////////////////////////////// -// Function: NodePath::get_hpr -// Access: Published -// Description: Retrieves the rotation component of the transform. -//////////////////////////////////////////////////////////////////// -LVecBase3f NodePath:: -get_hpr(float roll) const { - // This function is deprecated. It used to be a hack to work around - // a problem with decomposing Euler angles, but since we no longer - // depend on decomposing these, we shouldn't need this any more. - return get_hpr(); -} - //////////////////////////////////////////////////////////////////// // Function: NodePath::set_quat // Access: Published @@ -782,6 +768,58 @@ get_scale() const { return transform->get_scale(); } +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_shear +// Access: Published +// Description: Sets the shear component of the transform, +// leaving translation and rotation untouched. +//////////////////////////////////////////////////////////////////// +void NodePath:: +set_shear(const LVecBase3f &shear) { + nassertv_always(!is_empty()); + CPT(TransformState) transform = get_transform(); + set_transform(transform->set_shear(shear)); +} + +void NodePath:: +set_shxy(float shxy) { + nassertv_always(!is_empty()); + CPT(TransformState) transform = get_transform(); + LVecBase3f shear = transform->get_shear(); + shear[0] = shxy; + set_transform(transform->set_shear(shear)); +} + +void NodePath:: +set_shxz(float shxz) { + nassertv_always(!is_empty()); + CPT(TransformState) transform = get_transform(); + LVecBase3f shear = transform->get_shear(); + shear[1] = shxz; + set_transform(transform->set_shear(shear)); +} + +void NodePath:: +set_shyz(float shyz) { + nassertv_always(!is_empty()); + CPT(TransformState) transform = get_transform(); + LVecBase3f shear = transform->get_shear(); + shear[2] = shyz; + set_transform(transform->set_shear(shear)); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePath::get_shear +// Access: Published +// Description: Retrieves the shear component of the transform. +//////////////////////////////////////////////////////////////////// +LVecBase3f NodePath:: +get_shear() const { + nassertr_always(!is_empty(), LVecBase3f(0.0f, 0.0f, 0.0f)); + CPT(TransformState) transform = get_transform(); + return transform->get_shear(); +} + //////////////////////////////////////////////////////////////////// // Function: NodePath::set_pos_hpr // Access: Published @@ -792,8 +830,8 @@ void NodePath:: set_pos_hpr(const LVecBase3f &pos, const LVecBase3f &hpr) { nassertv_always(!is_empty()); CPT(TransformState) transform = get_transform(); - transform = TransformState::make_pos_hpr_scale - (pos, hpr, transform->get_scale()); + transform = TransformState::make_pos_hpr_scale_shear + (pos, hpr, transform->get_scale(), transform->get_shear()); set_transform(transform); } @@ -807,16 +845,16 @@ void NodePath:: set_hpr_scale(const LVecBase3f &hpr, const LVecBase3f &scale) { nassertv_always(!is_empty()); CPT(TransformState) transform = get_transform(); - transform = TransformState::make_pos_hpr_scale - (transform->get_pos(), hpr, scale); + transform = TransformState::make_pos_hpr_scale_shear + (transform->get_pos(), hpr, scale, transform->get_shear()); set_transform(transform); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_pos_hpr_scale // Access: Published -// Description: Completely replaces the transform with new -// translation, rotation, and scale components. +// Description: Replaces the translation, rotation, and scale +// components, implicitly setting shear to 0. //////////////////////////////////////////////////////////////////// void NodePath:: set_pos_hpr_scale(const LVecBase3f &pos, const LVecBase3f &hpr, @@ -829,8 +867,8 @@ set_pos_hpr_scale(const LVecBase3f &pos, const LVecBase3f &hpr, //////////////////////////////////////////////////////////////////// // Function: NodePath::set_pos_quat_scale // Access: Published -// Description: Completely replaces the transform with new -// translation, rotation, and scale components. +// Description: Replaces the translation, rotation, and scale +// components, implicitly setting shear to 0. //////////////////////////////////////////////////////////////////// void NodePath:: set_pos_quat_scale(const LVecBase3f &pos, const LQuaternionf &quat, @@ -840,6 +878,34 @@ set_pos_quat_scale(const LVecBase3f &pos, const LQuaternionf &quat, (pos, quat, scale)); } +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_pos_hpr_scale_shear +// Access: Published +// Description: Completely replaces the transform with new +// translation, rotation, scale, and shear components. +//////////////////////////////////////////////////////////////////// +void NodePath:: +set_pos_hpr_scale_shear(const LVecBase3f &pos, const LVecBase3f &hpr, + const LVecBase3f &scale, const LVecBase3f &shear) { + nassertv_always(!is_empty()); + set_transform(TransformState::make_pos_hpr_scale_shear + (pos, hpr, scale, shear)); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_pos_quat_scale_shear +// Access: Published +// Description: Completely replaces the transform with new +// translation, rotation, scale, and shear components. +//////////////////////////////////////////////////////////////////// +void NodePath:: +set_pos_quat_scale_shear(const LVecBase3f &pos, const LQuaternionf &quat, + const LVecBase3f &scale, const LVecBase3f &shear) { + nassertv_always(!is_empty()); + set_transform(TransformState::make_pos_quat_scale_shear + (pos, quat, scale, shear)); +} + //////////////////////////////////////////////////////////////////// // Function: NodePath::set_mat // Access: Published @@ -900,14 +966,15 @@ set_pos(const NodePath &other, const LVecBase3f &pos) { CPT(TransformState) orig_transform = get_transform(); if (orig_transform->has_components()) { // If we had a componentwise transform before we started, we - // should be careful to preserve the other two components. We + // should be careful to preserve the other three components. We // wouldn't need to do this, except for the possibility of // numerical error or decompose ambiguity. const LVecBase3f &orig_hpr = orig_transform->get_hpr(); const LVecBase3f &orig_scale = orig_transform->get_scale(); + const LVecBase3f &orig_shear = orig_transform->get_shear(); set_transform(other, rel_transform->set_pos(pos)); - set_pos_hpr_scale(get_transform()->get_pos(), orig_hpr, orig_scale); + set_pos_hpr_scale_shear(get_transform()->get_pos(), orig_hpr, orig_scale, orig_shear); } else { // If we didn't have a componentwise transform already, never @@ -967,16 +1034,17 @@ set_hpr(const NodePath &other, const LVecBase3f &hpr) { CPT(TransformState) orig_transform = get_transform(); if (orig_transform->has_components()) { // If we had a componentwise transform before we started, we - // should be careful to preserve the other two components. We + // should be careful to preserve the other three components. We // wouldn't need to do this, except for the possibility of // numerical error or decompose ambiguity. const LVecBase3f &orig_pos = orig_transform->get_pos(); const LVecBase3f &orig_scale = orig_transform->get_scale(); + const LVecBase3f &orig_shear = orig_transform->get_shear(); set_transform(other, rel_transform->set_hpr(hpr)); const TransformState *new_transform = get_transform(); if (new_transform->has_components()) { - set_pos_hpr_scale(orig_pos, new_transform->get_hpr(), orig_scale); + set_pos_hpr_scale_shear(orig_pos, new_transform->get_hpr(), orig_scale, orig_shear); } } else { @@ -1024,22 +1092,6 @@ get_hpr(const NodePath &other) const { return transform->get_hpr(); } -//////////////////////////////////////////////////////////////////// -// Function: NodePath::get_hpr -// Access: Published -// Description: Returns the relative orientation of the bottom node -// as seen from the other node. -//////////////////////////////////////////////////////////////////// -LVecBase3f NodePath:: -get_hpr(const NodePath &other, float roll) const { - // This is still doing it the dumb way, with a decomposition. This - // function is deprecated anyway. - LMatrix4f mat = get_mat(other); - LVector3f scale, hpr, pos; - decompose_matrix(mat, scale, hpr, pos, roll, CS_default); - return hpr; -} - //////////////////////////////////////////////////////////////////// // Function: NodePath::set_quat // Access: Published @@ -1054,16 +1106,17 @@ set_quat(const NodePath &other, const LQuaternionf &quat) { CPT(TransformState) orig_transform = get_transform(); if (orig_transform->has_components()) { // If we had a componentwise transform before we started, we - // should be careful to preserve the other two components. We + // should be careful to preserve the other three components. We // wouldn't need to do this, except for the possibility of // numerical error or decompose ambiguity. const LVecBase3f &orig_pos = orig_transform->get_pos(); const LVecBase3f &orig_scale = orig_transform->get_scale(); + const LVecBase3f &orig_shear = orig_transform->get_shear(); set_transform(other, rel_transform->set_quat(quat)); const TransformState *new_transform = get_transform(); if (new_transform->has_components()) { - set_pos_quat_scale(orig_pos, new_transform->get_quat(), orig_scale); + set_pos_quat_scale_shear(orig_pos, new_transform->get_quat(), orig_scale, orig_shear); } } else { @@ -1100,16 +1153,17 @@ set_scale(const NodePath &other, const LVecBase3f &scale) { CPT(TransformState) orig_transform = get_transform(); if (orig_transform->has_components()) { // If we had a componentwise transform before we started, we - // should be careful to preserve the other two components. We + // should be careful to preserve the other three components. We // wouldn't need to do this, except for the possibility of // numerical error or decompose ambiguity. const LVecBase3f &orig_pos = orig_transform->get_pos(); const LVecBase3f &orig_hpr = orig_transform->get_hpr(); + const LVecBase3f &orig_shear = orig_transform->get_shear(); set_transform(other, rel_transform->set_scale(scale)); const TransformState *new_transform = get_transform(); if (new_transform->has_components()) { - set_pos_hpr_scale(orig_pos, orig_hpr, new_transform->get_scale()); + set_pos_hpr_scale_shear(orig_pos, orig_hpr, new_transform->get_scale(), orig_shear); } } else { @@ -1156,6 +1210,77 @@ get_scale(const NodePath &other) const { return transform->get_scale(); } +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_shear +// Access: Published +// Description: Sets the shear component of the transform, +// relative to the other node. +//////////////////////////////////////////////////////////////////// +void NodePath:: +set_shear(const NodePath &other, const LVecBase3f &shear) { + nassertv_always(!is_empty()); + CPT(TransformState) rel_transform = get_transform(other); + + CPT(TransformState) orig_transform = get_transform(); + if (orig_transform->has_components()) { + // If we had a componentwise transform before we started, we + // should be careful to preserve the other three components. We + // wouldn't need to do this, except for the possibility of + // numerical error or decompose ambiguity. + const LVecBase3f &orig_pos = orig_transform->get_pos(); + const LVecBase3f &orig_hpr = orig_transform->get_hpr(); + const LVecBase3f &orig_scale = orig_transform->get_scale(); + + set_transform(other, rel_transform->set_shear(shear)); + const TransformState *new_transform = get_transform(); + if (new_transform->has_components()) { + set_pos_hpr_scale_shear(orig_pos, orig_hpr, orig_scale, new_transform->get_shear()); + } + + } else { + // If we didn't have a componentwise transform already, never + // mind. + set_transform(other, rel_transform->set_shear(shear)); + } +} + +void NodePath:: +set_shxy(const NodePath &other, float shxy) { + nassertv_always(!is_empty()); + LVecBase3f shear = get_shear(other); + shear[0] = shxy; + set_shear(other, shear); +} + +void NodePath:: +set_shxz(const NodePath &other, float shxz) { + nassertv_always(!is_empty()); + LVecBase3f shear = get_shear(other); + shear[1] = shxz; + set_shear(other, shear); +} + +void NodePath:: +set_shyz(const NodePath &other, float shyz) { + nassertv_always(!is_empty()); + LVecBase3f shear = get_shear(other); + shear[2] = shyz; + set_shear(other, shear); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePath::get_shear +// Access: Published +// Description: Returns the relative shear of the bottom node +// as seen from the other node. +//////////////////////////////////////////////////////////////////// +LVecBase3f NodePath:: +get_shear(const NodePath &other) const { + nassertr_always(!is_empty(), LVecBase3f(0.0f, 0.0f, 0.0f)); + CPT(TransformState) transform = get_transform(other); + return transform->get_shear(); +} + //////////////////////////////////////////////////////////////////// // Function: NodePath::set_pos_hpr // Access: Published @@ -1175,20 +1300,21 @@ set_pos_hpr(const NodePath &other, const LVecBase3f &pos, // wouldn't need to do this, except for the possibility of // numerical error or decompose ambiguity. const LVecBase3f &orig_scale = orig_transform->get_scale(); + const LVecBase3f &orig_shear = orig_transform->get_shear(); - set_transform(other, TransformState::make_pos_hpr_scale - (pos, hpr, rel_transform->get_scale())); + set_transform(other, TransformState::make_pos_hpr_scale_shear + (pos, hpr, rel_transform->get_scale(), rel_transform->get_shear())); const TransformState *new_transform = get_transform(); if (new_transform->has_components()) { - set_pos_hpr_scale(new_transform->get_pos(), new_transform->get_hpr(), - orig_scale); + set_pos_hpr_scale_shear(new_transform->get_pos(), new_transform->get_hpr(), + orig_scale, orig_shear); } } else { // If we didn't have a componentwise transform already, never // mind. - set_transform(other, TransformState::make_pos_hpr_scale - (pos, hpr, rel_transform->get_scale())); + set_transform(other, TransformState::make_pos_hpr_scale_shear + (pos, hpr, rel_transform->get_scale(), rel_transform->get_shear())); } } @@ -1208,8 +1334,8 @@ set_hpr_scale(const NodePath &other, const LVecBase3f &hpr, const LVecBase3f &sc // few thousandths. nassertv_always(!is_empty()); CPT(TransformState) transform = get_transform(other); - transform = TransformState::make_pos_hpr_scale - (transform->get_pos(), hpr, scale); + transform = TransformState::make_pos_hpr_scale_shear + (transform->get_pos(), hpr, scale, transform->get_shear()); set_transform(other, transform); } @@ -1218,7 +1344,7 @@ set_hpr_scale(const NodePath &other, const LVecBase3f &hpr, const LVecBase3f &sc // Access: Published // Description: Completely replaces the transform with new // translation, rotation, and scale components, relative -// to the other node. +// to the other node, implicitly setting shear to 0. //////////////////////////////////////////////////////////////////// void NodePath:: set_pos_hpr_scale(const NodePath &other, @@ -1234,7 +1360,7 @@ set_pos_hpr_scale(const NodePath &other, // Access: Published // Description: Completely replaces the transform with new // translation, rotation, and scale components, relative -// to the other node. +// to the other node, implicitly setting shear to 0. //////////////////////////////////////////////////////////////////// void NodePath:: set_pos_quat_scale(const NodePath &other, @@ -1245,6 +1371,38 @@ set_pos_quat_scale(const NodePath &other, (pos, quat, scale)); } +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_pos_hpr_scale_shear +// Access: Published +// Description: Completely replaces the transform with new +// translation, rotation, scale, and shear components, +// relative to the other node. +//////////////////////////////////////////////////////////////////// +void NodePath:: +set_pos_hpr_scale_shear(const NodePath &other, + const LVecBase3f &pos, const LVecBase3f &hpr, + const LVecBase3f &scale, const LVecBase3f &shear) { + nassertv_always(!is_empty()); + set_transform(other, TransformState::make_pos_hpr_scale_shear + (pos, hpr, scale, shear)); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_pos_quat_scale_shear +// Access: Published +// Description: Completely replaces the transform with new +// translation, rotation, scale, and shear components, +// relative to the other node. +//////////////////////////////////////////////////////////////////// +void NodePath:: +set_pos_quat_scale_shear(const NodePath &other, + const LVecBase3f &pos, const LQuaternionf &quat, + const LVecBase3f &scale, const LVecBase3f &shear) { + nassertv_always(!is_empty()); + set_transform(other, TransformState::make_pos_quat_scale_shear + (pos, quat, scale, shear)); +} + //////////////////////////////////////////////////////////////////// // Function: NodePath::get_mat // Access: Published diff --git a/panda/src/pgraph/nodePath.h b/panda/src/pgraph/nodePath.h index d9cbdf8da3..30c175d0f3 100644 --- a/panda/src/pgraph/nodePath.h +++ b/panda/src/pgraph/nodePath.h @@ -250,7 +250,6 @@ PUBLISHED: void set_p(float p); void set_r(float r); LVecBase3f get_hpr() const; - LVecBase3f get_hpr(float roll) const; INLINE float get_h() const; INLINE float get_p() const; INLINE float get_r() const; @@ -269,6 +268,16 @@ PUBLISHED: INLINE float get_sy() const; INLINE float get_sz() const; + INLINE void set_shear(float shxy, float shxz, float shyz); + void set_shear(const LVecBase3f &shear); + void set_shxy(float shxy); + void set_shxz(float shxz); + void set_shyz(float shyz); + LVecBase3f get_shear() const; + INLINE float get_shxy() const; + INLINE float get_shxz() const; + INLINE float get_shyz() const; + INLINE void set_pos_hpr(float x, float y, float z, float h, float p, float r); void set_pos_hpr(const LVecBase3f &pos, @@ -287,6 +296,14 @@ PUBLISHED: void set_pos_quat_scale(const LVecBase3f &pos, const LQuaternionf &quat, const LVecBase3f &scale); + void set_pos_hpr_scale_shear(const LVecBase3f &pos, + const LVecBase3f &hpr, + const LVecBase3f &scale, + const LVecBase3f &shear); + void set_pos_quat_scale_shear(const LVecBase3f &pos, + const LQuaternionf &quat, + const LVecBase3f &scale, + const LVecBase3f &shear); void set_mat(const LMatrix4f &mat); INLINE void clear_mat(); @@ -317,7 +334,6 @@ PUBLISHED: void set_p(const NodePath &other, float p); void set_r(const NodePath &other, float r); LVecBase3f get_hpr(const NodePath &other) const; - LVecBase3f get_hpr(const NodePath &other, float roll) const; INLINE float get_h(const NodePath &other) const; INLINE float get_p(const NodePath &other) const; INLINE float get_r(const NodePath &other) const; @@ -335,6 +351,16 @@ PUBLISHED: INLINE float get_sy(const NodePath &other) const; INLINE float get_sz(const NodePath &other) const; + INLINE void set_shear(const NodePath &other, float shxy, float shxz, float shyz); + void set_shear(const NodePath &other, const LVecBase3f &shear); + void set_shxy(const NodePath &other, float shxy); + void set_shxz(const NodePath &other, float shxz); + void set_shyz(const NodePath &other, float shyz); + LVecBase3f get_shear(const NodePath &other) const; + INLINE float get_shxy(const NodePath &other) const; + INLINE float get_shxz(const NodePath &other) const; + INLINE float get_shyz(const NodePath &other) const; + INLINE void set_pos_hpr(const NodePath &other, float x, float y, float z, float h, float p, float r); @@ -359,6 +385,16 @@ PUBLISHED: const LVecBase3f &pos, const LQuaternionf &quat, const LVecBase3f &scale); + void set_pos_hpr_scale_shear(const NodePath &other, + const LVecBase3f &pos, + const LVecBase3f &hpr, + const LVecBase3f &scale, + const LVecBase3f &shear); + void set_pos_quat_scale_shear(const NodePath &other, + const LVecBase3f &pos, + const LQuaternionf &quat, + const LVecBase3f &scale, + const LVecBase3f &shear); const LMatrix4f &get_mat(const NodePath &other) const; void set_mat(const NodePath &other, const LMatrix4f &mat); diff --git a/panda/src/pgraph/transformState.I b/panda/src/pgraph/transformState.I index 9db8501042..36d6d6f8ce 100644 --- a/panda/src/pgraph/transformState.I +++ b/panda/src/pgraph/transformState.I @@ -114,6 +114,44 @@ make_scale(const LVecBase3f &scale) { scale); } +//////////////////////////////////////////////////////////////////// +// Function: TransformState::make_shear +// Access: Published, Static +// Description: Makes a new TransformState with the specified +// components. +//////////////////////////////////////////////////////////////////// +INLINE CPT(TransformState) TransformState:: +make_shear(const LVecBase3f &shear) { + return make_pos_hpr_scale_shear(LVecBase3f(0.0f, 0.0f, 0.0f), + LVecBase3f(0.0f, 0.0f, 0.0f), + LVecBase3f(1.0f, 1.0f, 1.0f), + shear); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformState::make_pos_hpr_scale +// Access: Published, Static +// Description: Makes a new TransformState with the specified +// components. +//////////////////////////////////////////////////////////////////// +INLINE CPT(TransformState) TransformState:: +make_pos_hpr_scale(const LVecBase3f &pos, const LVecBase3f &hpr, + const LVecBase3f &scale) { + return make_pos_hpr_scale_shear(pos, hpr, scale, LVecBase3f::zero()); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformState::make_pos_quat_scale +// Access: Published, Static +// Description: Makes a new TransformState with the specified +// components. +//////////////////////////////////////////////////////////////////// +INLINE CPT(TransformState) TransformState:: +make_pos_quat_scale(const LVecBase3f &pos, const LQuaternionf &quat, + const LVecBase3f &scale) { + return make_pos_quat_scale_shear(pos, quat, scale, LVecBase3f::zero()); +} + //////////////////////////////////////////////////////////////////// // Function: TransformState::is_identity // Access: Published @@ -284,6 +322,31 @@ has_uniform_scale() const { return (_flags & F_uniform_scale) != 0; } +//////////////////////////////////////////////////////////////////// +// Function: TransformState::has_shear +// Access: Published +// Description: Returns true if the transform's shear component +// can be extracted out separately. This is generally +// true only when has_components() is true. +//////////////////////////////////////////////////////////////////// +INLINE bool TransformState:: +has_shear() const { + return has_components(); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformState::has_nonzero_shear +// Access: Published +// Description: Returns true if the shear component is non-zero, +// false if it is zero or if the matrix cannot be +// decomposed. +//////////////////////////////////////////////////////////////////// +INLINE bool TransformState:: +has_nonzero_shear() const { + check_components(); + return (_flags & F_has_nonzero_shear) != 0; +} + //////////////////////////////////////////////////////////////////// // Function: TransformState::has_mat // Access: Published @@ -368,6 +431,20 @@ get_uniform_scale() const { return _scale[0]; } +//////////////////////////////////////////////////////////////////// +// Function: TransformState::get_shear +// Access: Published +// Description: Returns the shear component of the transform. It is +// an error to call this if has_components() returned +// false. +//////////////////////////////////////////////////////////////////// +INLINE const LVecBase3f &TransformState:: +get_shear() const { + check_components(); + nassertr(!is_invalid(), _shear); + return _shear; +} + //////////////////////////////////////////////////////////////////// // Function: TransformState::get_mat // Access: Published @@ -458,7 +535,8 @@ check_mat() const { // Access: Private // Description: Should be called immediately after _scale (and // F_has_components) is set, this checks for a uniform -// scale and sets the bit appropriately. +// scale (as well as a non-zero shear) and sets the bit +// appropriately. //////////////////////////////////////////////////////////////////// INLINE void TransformState:: check_uniform_scale() { @@ -466,6 +544,9 @@ check_uniform_scale() { IS_NEARLY_EQUAL(_scale[0], _scale[2])) { _flags |= F_uniform_scale; } + if (!_shear.almost_equal(LVecBase3f::zero())) { + _flags |= F_has_nonzero_shear; + } } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/pgraph/transformState.cxx b/panda/src/pgraph/transformState.cxx index 0966f740f7..86128f5c53 100644 --- a/panda/src/pgraph/transformState.cxx +++ b/panda/src/pgraph/transformState.cxx @@ -244,6 +244,11 @@ operator < (const TransformState &other) const { } c = _scale.compare_to(other._scale); + if (c != 0) { + return c < 0; + } + + c = _shear.compare_to(other._shear); return c < 0; } @@ -294,18 +299,19 @@ make_invalid() { } //////////////////////////////////////////////////////////////////// -// Function: TransformState::make_pos_hpr_scale +// Function: TransformState::make_pos_hpr_scale_shear // Access: Published, Static // Description: Makes a new TransformState with the specified // components. //////////////////////////////////////////////////////////////////// CPT(TransformState) TransformState:: -make_pos_hpr_scale(const LVecBase3f &pos, const LVecBase3f &hpr, - const LVecBase3f &scale) { +make_pos_hpr_scale_shear(const LVecBase3f &pos, const LVecBase3f &hpr, + const LVecBase3f &scale, const LVecBase3f &shear) { // Make a special-case check for the identity transform. if (pos == LVecBase3f(0.0f, 0.0f, 0.0f) && hpr == LVecBase3f(0.0f, 0.0f, 0.0f) && - scale == LVecBase3f(1.0f, 1.0f, 1.0f)) { + scale == LVecBase3f(1.0f, 1.0f, 1.0f) && + shear == LVecBase3f(0.0f, 0.0f, 0.0f)) { return make_identity(); } @@ -313,24 +319,26 @@ make_pos_hpr_scale(const LVecBase3f &pos, const LVecBase3f &hpr, state->_pos = pos; state->_hpr = hpr; state->_scale = scale; + state->_shear = shear; state->_flags = F_components_given | F_hpr_given | F_components_known | F_hpr_known | F_has_components; state->check_uniform_scale(); return return_new(state); } //////////////////////////////////////////////////////////////////// -// Function: TransformState::make_pos_quat_scale +// Function: TransformState::make_pos_quat_scale_shear // Access: Published, Static // Description: Makes a new TransformState with the specified // components. //////////////////////////////////////////////////////////////////// CPT(TransformState) TransformState:: -make_pos_quat_scale(const LVecBase3f &pos, const LQuaternionf &quat, - const LVecBase3f &scale) { +make_pos_quat_scale_shear(const LVecBase3f &pos, const LQuaternionf &quat, + const LVecBase3f &scale, const LVecBase3f &shear) { // Make a special-case check for the identity transform. if (pos == LVecBase3f(0.0f, 0.0f, 0.0f) && quat == LQuaternionf::ident_quat() && - scale == LVecBase3f(1.0f, 1.0f, 1.0f)) { + scale == LVecBase3f(1.0f, 1.0f, 1.0f) && + shear == LVecBase3f(0.0f, 0.0f, 0.0f)) { return make_identity(); } @@ -338,6 +346,7 @@ make_pos_quat_scale(const LVecBase3f &pos, const LQuaternionf &quat, state->_pos = pos; state->_quat = quat; state->_scale = scale; + state->_shear = shear; state->_flags = F_components_given | F_quat_given | F_components_known | F_quat_known | F_has_components; state->check_uniform_scale(); return return_new(state); @@ -376,9 +385,9 @@ set_pos(const LVecBase3f &pos) const { // If we started with a componentwise transform, we keep it that // way. if (quat_given()) { - return make_pos_quat_scale(pos, get_quat(), get_scale()); + return make_pos_quat_scale_shear(pos, get_quat(), get_scale(), get_shear()); } else { - return make_pos_hpr_scale(pos, get_hpr(), get_scale()); + return make_pos_hpr_scale_shear(pos, get_hpr(), get_scale(), get_shear()); } } else { @@ -400,7 +409,7 @@ CPT(TransformState) TransformState:: set_hpr(const LVecBase3f &hpr) const { nassertr(!is_invalid(), this); // nassertr(has_components(), this); - return make_pos_hpr_scale(get_pos(), hpr, get_scale()); + return make_pos_hpr_scale_shear(get_pos(), hpr, get_scale(), get_shear()); } //////////////////////////////////////////////////////////////////// @@ -414,7 +423,7 @@ CPT(TransformState) TransformState:: set_quat(const LQuaternionf &quat) const { nassertr(!is_invalid(), this); // nassertr(has_components(), this); - return make_pos_quat_scale(get_pos(), quat, get_scale()); + return make_pos_quat_scale_shear(get_pos(), quat, get_scale(), get_shear()); } //////////////////////////////////////////////////////////////////// @@ -429,9 +438,27 @@ set_scale(const LVecBase3f &scale) const { nassertr(!is_invalid(), this); // nassertr(has_components(), this); if (quat_given()) { - return make_pos_quat_scale(get_pos(), get_quat(), scale); + return make_pos_quat_scale_shear(get_pos(), get_quat(), scale, get_shear()); } else { - return make_pos_hpr_scale(get_pos(), get_hpr(), scale); + return make_pos_hpr_scale_shear(get_pos(), get_hpr(), scale, get_shear()); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformState::set_shear +// Access: Published +// Description: Returns a new TransformState object that represents the +// original TransformState with its shear component +// replaced with the indicated value, if possible. +//////////////////////////////////////////////////////////////////// +CPT(TransformState) TransformState:: +set_shear(const LVecBase3f &shear) const { + nassertr(!is_invalid(), this); + // nassertr(has_components(), this); + if (quat_given()) { + return make_pos_quat_scale_shear(get_pos(), get_quat(), get_scale(), shear); + } else { + return make_pos_hpr_scale_shear(get_pos(), get_hpr(), get_scale(), shear); } } @@ -611,10 +638,10 @@ output(ostream &out) const { out << "m"; } else if (output_hpr && quat_given()) { - // A leading "q" indicates that the pos and scale are exactly as - // specified, but the rotation was described as a quaternion, - // and we are decomposing that to hpr for the benefit of the - // user. + // A leading "q" indicates that the pos, scale, and shear are + // exactly as specified, but the rotation was described as a + // quaternion, and we are decomposing that to hpr for the + // benefit of the user. out << "q"; } @@ -636,6 +663,10 @@ output(ostream &out) const { lead = ' '; } } + if (has_nonzero_shear()) { + out << lead << "shear " << get_shear(); + lead = ' '; + } if (lead == '(') { out << "(almost identity)"; } else { @@ -879,6 +910,7 @@ do_compose(const TransformState *other) const { if (compose_componentwise && has_uniform_scale() && + !has_nonzero_shear() && !other->has_nonzero_shear() && ((components_given() && other->has_components()) || (other->components_given() && has_components()))) { // We will do this operation componentwise if *either* transform @@ -932,6 +964,7 @@ do_invert_compose(const TransformState *other) const { if (compose_componentwise && has_uniform_scale() && + !has_nonzero_shear() && !other->has_nonzero_shear() && ((components_given() && other->has_components()) || (other->components_given() && has_components()))) { // We will do this operation componentwise if *either* transform @@ -1040,6 +1073,7 @@ calc_components() { nassertv((_flags & F_is_invalid) == 0); if ((_flags & F_is_identity) != 0) { _scale.set(1.0f, 1.0f, 1.0f); + _shear.set(0.0f, 0.0f, 0.0f); _hpr.set(0.0f, 0.0f, 0.0f); _quat = LQuaternionf::ident_quat(); _pos.set(0.0f, 0.0f, 0.0f); @@ -1051,7 +1085,7 @@ calc_components() { nassertv((_flags & F_mat_known) != 0); const LMatrix4f &mat = get_mat(); - bool possible = decompose_matrix(mat, _scale, _hpr, _pos); + bool possible = decompose_matrix(mat, _scale, _shear, _hpr, _pos); if (!possible) { // Some matrices can't be decomposed into scale, hpr, pos. In // this case, we now know that we cannot compute the components; @@ -1121,7 +1155,7 @@ calc_mat() { // If we don't have a matrix and we're not identity, the only // other explanation is that we were constructed via components. nassertv((_flags & F_components_known) != 0); - compose_matrix(_mat, _scale, get_hpr(), _pos); + compose_matrix(_mat, _scale, _shear, get_hpr(), _pos); } _flags |= F_mat_known; } @@ -1175,6 +1209,7 @@ write_datagram(BamWriter *manager, Datagram &dg) { get_hpr().write_datagram(dg); } _scale.write_datagram(dg); + _shear.write_datagram(dg); } else { // A general matrix. @@ -1283,19 +1318,17 @@ fillin(DatagramIterator &scan, BamReader *manager) { _flags |= (F_hpr_given | F_hpr_known); } _scale.read_datagram(scan); + if (manager->get_file_minor_ver() >= 6) { + _shear.read_datagram(scan); + } else { + _shear.set(0.0f, 0.0f, 0.0f); + } check_uniform_scale(); } if ((_flags & F_mat_known) != 0) { // General matrix. _mat.read_datagram(scan); - - if (bams_componentwise) { - // Decompose the matrix if we can, and store it componentwise. - if (has_components()) { - _flags |= F_components_given | F_hpr_given; - } - } } } diff --git a/panda/src/pgraph/transformState.h b/panda/src/pgraph/transformState.h index 7349816ace..728534a416 100644 --- a/panda/src/pgraph/transformState.h +++ b/panda/src/pgraph/transformState.h @@ -76,12 +76,21 @@ PUBLISHED: const LVecBase3f &hpr); INLINE static CPT(TransformState) make_scale(float scale); INLINE static CPT(TransformState) make_scale(const LVecBase3f &scale); - static CPT(TransformState) make_pos_hpr_scale(const LVecBase3f &pos, - const LVecBase3f &hpr, - const LVecBase3f &scale); - static CPT(TransformState) make_pos_quat_scale(const LVecBase3f &pos, - const LQuaternionf &quat, - const LVecBase3f &scale); + INLINE static CPT(TransformState) make_shear(const LVecBase3f &scale); + INLINE static CPT(TransformState) make_pos_hpr_scale(const LVecBase3f &pos, + const LVecBase3f &hpr, + const LVecBase3f &scale); + INLINE static CPT(TransformState) make_pos_quat_scale(const LVecBase3f &pos, + const LQuaternionf &quat, + const LVecBase3f &scale); + static CPT(TransformState) make_pos_hpr_scale_shear(const LVecBase3f &pos, + const LVecBase3f &hpr, + const LVecBase3f &scale, + const LVecBase3f &shear); + static CPT(TransformState) make_pos_quat_scale_shear(const LVecBase3f &pos, + const LQuaternionf &quat, + const LVecBase3f &scale, + const LVecBase3f &shear); static CPT(TransformState) make_mat(const LMatrix4f &mat); INLINE bool is_identity() const; @@ -96,18 +105,22 @@ PUBLISHED: INLINE bool has_quat() const; INLINE bool has_scale() const; INLINE bool has_uniform_scale() const; + INLINE bool has_shear() const; + INLINE bool has_nonzero_shear() const; INLINE bool has_mat() const; INLINE const LVecBase3f &get_pos() const; INLINE const LVecBase3f &get_hpr() const; INLINE const LQuaternionf &get_quat() const; INLINE const LVecBase3f &get_scale() const; INLINE float get_uniform_scale() const; + INLINE const LVecBase3f &get_shear() const; INLINE const LMatrix4f &get_mat() const; CPT(TransformState) set_pos(const LVecBase3f &pos) const; CPT(TransformState) set_hpr(const LVecBase3f &hpr) const; CPT(TransformState) set_quat(const LQuaternionf &quat) const; CPT(TransformState) set_scale(const LVecBase3f &scale) const; + CPT(TransformState) set_shear(const LVecBase3f &shear) const; CPT(TransformState) compose(const TransformState *other) const; CPT(TransformState) invert_compose(const TransformState *other) const; @@ -175,22 +188,23 @@ private: INLINE bool is_destructing() const; enum Flags { - F_is_identity = 0x0001, - F_is_singular = 0x0002, - F_singular_known = 0x0004, // set if we know F_is_singular - F_components_given = 0x0008, - F_components_known = 0x0010, // set if we know F_has_components - F_has_components = 0x0020, - F_mat_known = 0x0040, // set if _mat is defined - F_is_invalid = 0x0080, - F_quat_given = 0x0100, - F_quat_known = 0x0200, // set if _quat is defined - F_hpr_given = 0x0400, - F_hpr_known = 0x0800, // set if _hpr is defined - F_uniform_scale = 0x1000, - F_is_destructing = 0x8000, + F_is_identity = 0x0001, + F_is_singular = 0x0002, + F_singular_known = 0x0004, // set if we know F_is_singular + F_components_given = 0x0008, + F_components_known = 0x0010, // set if we know F_has_components + F_has_components = 0x0020, + F_mat_known = 0x0040, // set if _mat is defined + F_is_invalid = 0x0080, + F_quat_given = 0x0100, + F_quat_known = 0x0200, // set if _quat is defined + F_hpr_given = 0x0400, + F_hpr_known = 0x0800, // set if _hpr is defined + F_uniform_scale = 0x1000, + F_has_nonzero_shear = 0x2000, + F_is_destructing = 0x8000, }; - LVecBase3f _pos, _hpr, _scale; + LVecBase3f _pos, _hpr, _scale, _shear; LQuaternionf _quat; LMatrix4f _mat; LMatrix4f *_inv_mat; diff --git a/panda/src/putil/bam.h b/panda/src/putil/bam.h index 3c6217a6b7..2b33d6d67c 100644 --- a/panda/src/putil/bam.h +++ b/panda/src/putil/bam.h @@ -34,12 +34,13 @@ static const unsigned short _bam_major_ver = 4; // Bumped to major version 3 on 12/8/00 to change float64's to float32's. // Bumped to major version 4 on 4/10/02 to store new scene graph. -static const unsigned short _bam_minor_ver = 5; +static const unsigned short _bam_minor_ver = 6; // Bumped to minor version 1 on 4/10/03 to add CullFaceAttrib::reverse. // Bumped to minor version 2 on 4/12/03 to add num_components to texture. // Bumped to minor version 3 on 4/15/03 to add ImageBuffer::_alpha_file_channel // Bumped to minor version 4 on 6/12/03 to add PandaNode::set_tag(). -// Bumped to minor version 5 on 7/09/03 to add rawdata mode to texture +// Bumped to minor version 5 on 7/09/03 to add rawdata mode to texture. +// Bumped to minor version 6 on 7/22/03 to add shear to scene graph and animation data. #endif diff --git a/panda/src/shader/planarReflector.cxx b/panda/src/shader/planarReflector.cxx index e388fc7994..ae5b2c499a 100644 --- a/panda/src/shader/planarReflector.cxx +++ b/panda/src/shader/planarReflector.cxx @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include diff --git a/panda/src/shader/spheretexReflector.cxx b/panda/src/shader/spheretexReflector.cxx index fdbc7ee5bf..7be971e6f3 100644 --- a/panda/src/shader/spheretexReflector.cxx +++ b/panda/src/shader/spheretexReflector.cxx @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff --git a/panda/src/text/textNode.cxx b/panda/src/text/textNode.cxx index 381481bdad..03689ef45d 100644 --- a/panda/src/text/textNode.cxx +++ b/panda/src/text/textNode.cxx @@ -233,11 +233,12 @@ write(ostream &out, int indent_level) const { << "draw order is " << _draw_order << ", " << _draw_order + 1 << ", " << _draw_order + 2 << "\n"; - LVecBase3f scale, hpr, trans; - if (decompose_matrix(_transform, scale, hpr, trans, _coordinate_system)) { + LVecBase3f scale, shear, hpr, trans; + if (decompose_matrix(_transform, scale, shear, hpr, trans, _coordinate_system)) { indent(out, indent_level + 2) << "transform is:\n" << " scale: " << scale << "\n" + << " shear: " << shear << "\n" << " hpr: " << hpr << "\n" << " trans: " << hpr << "\n"; } else { diff --git a/panda/src/tform/driveInterface.cxx b/panda/src/tform/driveInterface.cxx index b81f7f05ef..3b1aa28c72 100644 --- a/panda/src/tform/driveInterface.cxx +++ b/panda/src/tform/driveInterface.cxx @@ -190,8 +190,8 @@ set_force_roll(float) { //////////////////////////////////////////////////////////////////// void DriveInterface:: set_mat(const LMatrix4f &mat) { - LVecBase3f scale; - decompose_matrix(mat, scale, _hpr, _xyz); + LVecBase3f scale, shear; + decompose_matrix(mat, scale, shear, _hpr, _xyz); } //////////////////////////////////////////////////////////////////// @@ -201,7 +201,10 @@ set_mat(const LMatrix4f &mat) { //////////////////////////////////////////////////////////////////// const LMatrix4f &DriveInterface:: get_mat() { - compose_matrix(_mat, LVecBase3f(1.0f, 1.0f, 1.0f), _hpr, _xyz); + compose_matrix(_mat, + LVecBase3f(1.0f, 1.0f, 1.0f), + LVecBase3f(0.0f, 0.0f, 0.0f), + _hpr, _xyz); return _mat; } diff --git a/panda/src/tform/trackball.cxx b/panda/src/tform/trackball.cxx index af9eed65bd..f346f0292d 100644 --- a/panda/src/tform/trackball.cxx +++ b/panda/src/tform/trackball.cxx @@ -180,29 +180,29 @@ set_z(float z) { //////////////////////////////////////////////////////////////////// LVecBase3f Trackball:: get_hpr() const { - LVecBase3f scale, hpr, translate; - decompose_matrix(_rotation, scale, hpr, translate); + LVecBase3f scale, shear, hpr, translate; + decompose_matrix(_rotation, scale, shear, hpr, translate); return hpr; } float Trackball:: get_h() const { - LVecBase3f scale, hpr, translate; - decompose_matrix(_rotation, scale, hpr, translate); + LVecBase3f scale, shear, hpr, translate; + decompose_matrix(_rotation, scale, shear, hpr, translate); return hpr[0]; } float Trackball:: get_p() const { - LVecBase3f scale, hpr, translate; - decompose_matrix(_rotation, scale, hpr, translate); + LVecBase3f scale, shear, hpr, translate; + decompose_matrix(_rotation, scale, shear, hpr, translate); return hpr[1]; } float Trackball:: get_r() const { - LVecBase3f scale, hpr, translate; - decompose_matrix(_rotation, scale, hpr, translate); + LVecBase3f scale, shear, hpr, translate; + decompose_matrix(_rotation, scale, shear, hpr, translate); return hpr[2]; } @@ -214,45 +214,45 @@ get_r() const { //////////////////////////////////////////////////////////////////// void Trackball:: set_hpr(const LVecBase3f &hpr) { - LVecBase3f scale, old_hpr, translate; - decompose_matrix(_rotation, scale, old_hpr, translate); - compose_matrix(_rotation, scale, hpr, translate); + LVecBase3f scale, shear, old_hpr, translate; + decompose_matrix(_rotation, scale, shear, old_hpr, translate); + compose_matrix(_rotation, scale, shear, hpr, translate); recompute(); } void Trackball:: set_hpr(float h, float p, float r) { - LVecBase3f scale, hpr, translate; - decompose_matrix(_rotation, scale, hpr, translate); + LVecBase3f scale, shear, hpr, translate; + decompose_matrix(_rotation, scale, shear, hpr, translate); hpr.set(h, p, r); - compose_matrix(_rotation, scale, hpr, translate); + compose_matrix(_rotation, scale, shear, hpr, translate); recompute(); } void Trackball:: set_h(float h) { - LVecBase3f scale, hpr, translate; - decompose_matrix(_rotation, scale, hpr, translate); + LVecBase3f scale, shear, hpr, translate; + decompose_matrix(_rotation, scale, shear, hpr, translate); hpr[0] = h; - compose_matrix(_rotation, scale, hpr, translate); + compose_matrix(_rotation, scale, shear, hpr, translate); recompute(); } void Trackball:: set_p(float p) { - LVecBase3f scale, hpr, translate; - decompose_matrix(_rotation, scale, hpr, translate); + LVecBase3f scale, shear, hpr, translate; + decompose_matrix(_rotation, scale, shear, hpr, translate); hpr[1] = p; - compose_matrix(_rotation, scale, hpr, translate); + compose_matrix(_rotation, scale, shear, hpr, translate); recompute(); } void Trackball:: set_r(float r) { - LVecBase3f scale, hpr, translate; - decompose_matrix(_rotation, scale, hpr, translate); + LVecBase3f scale, shear, hpr, translate; + decompose_matrix(_rotation, scale, shear, hpr, translate); hpr[2] = r; - compose_matrix(_rotation, scale, hpr, translate); + compose_matrix(_rotation, scale, shear, hpr, translate); recompute(); } diff --git a/pandatool/src/egg-optchar/eggOptchar.cxx b/pandatool/src/egg-optchar/eggOptchar.cxx index 1baa56101a..750321d63d 100644 --- a/pandatool/src/egg-optchar/eggOptchar.cxx +++ b/pandatool/src/egg-optchar/eggOptchar.cxx @@ -90,9 +90,9 @@ EggOptchar() { &EggOptchar::dispatch_vector_string_comma, NULL, &_expose_components); add_option - ("zero", "joint[,hprxyzijk]", 0, + ("zero", "joint[,hprxyzijkabc]", 0, "Zeroes out the animation channels for the named joint. If " - "a subset of the component letters hprxyzijk is included, the " + "a subset of the component letters hprxyzijkabc is included, the " "operation is restricted to just those components; otherwise the " "entire transform is cleared.", &EggOptchar::dispatch_name_components, NULL, &_zero_channels); @@ -272,14 +272,14 @@ dispatch_name_components(const string &opt, const string &arg, void *var) { } if (sp._b.empty()) { - sp._b = matrix_components; + sp._b = matrix_component_letters; } else { for (string::const_iterator si = sp._b.begin(); si != sp._b.end(); ++si) { - if (strchr(matrix_components, *si) == NULL) { + if (strchr(matrix_component_letters, *si) == NULL) { nout << "Not a standard matrix component: \"" << *si << "\"\n" << "-" << opt << " requires a joint name followed by a set " << "of component names. The standard component names are \"" - << matrix_components << "\".\n"; + << matrix_component_letters << "\".\n"; return false; } } diff --git a/pandatool/src/eggcharbase/eggCharacterData.cxx b/pandatool/src/eggcharbase/eggCharacterData.cxx index baa2e089f0..a8e4b90e3f 100644 --- a/pandatool/src/eggcharbase/eggCharacterData.cxx +++ b/pandatool/src/eggcharbase/eggCharacterData.cxx @@ -211,6 +211,10 @@ do_reparent() { } } + // Report the set of joints that failed. It really shouldn't be + // possible for any joints to fail, so if you see anything reported + // here, something went wrong at a fundamental level. Perhaps a + // problem with decompose_matrix(). InvalidSet::const_iterator si; for (si = invalid_set.begin(); si != invalid_set.end(); ++si) { EggJointData *joint_data = (*si); @@ -225,7 +229,7 @@ do_reparent() { } else { nout << joint_data->get_parent()->get_name(); } - nout << " results in a skew transform.\n"; + nout << " results in an invalid transform.\n"; } } diff --git a/pandatool/src/eggcharbase/eggMatrixTablePointer.cxx b/pandatool/src/eggcharbase/eggMatrixTablePointer.cxx index a8a987f3db..2bed637908 100644 --- a/pandatool/src/eggcharbase/eggMatrixTablePointer.cxx +++ b/pandatool/src/eggcharbase/eggMatrixTablePointer.cxx @@ -198,16 +198,18 @@ do_rebuild() { return false; } + bool all_ok = true; + _xform->clear_data(); RebuildFrames::const_iterator fi; for (fi = _rebuild_frames.begin(); fi != _rebuild_frames.end(); ++fi) { if (!_xform->add_data(*fi)) { - return false; + all_ok = false; } } _rebuild_frames.clear(); - return true; + return all_ok; } //////////////////////////////////////////////////////////////////// diff --git a/pandatool/src/mayaegg/mayaToEggConverter.cxx b/pandatool/src/mayaegg/mayaToEggConverter.cxx index e0bf3cd47c..a8b9e665e7 100644 --- a/pandatool/src/mayaegg/mayaToEggConverter.cxx +++ b/pandatool/src/mayaegg/mayaToEggConverter.cxx @@ -455,7 +455,7 @@ convert_char_chan(double start_frame, double end_frame, double frame_inc, EggXfmSAnim *anim = _tree.get_egg_anim(node_desc); if (!anim->add_data(tgroup->get_transform())) { mayaegg_cat.error() - << "Shear transform on " << node_desc->get_name() + << "Invalid transform on " << node_desc->get_name() << " frame " << frame.value() << ".\n"; } }