ソースを参照

add explicit support for shear to the scene graph

David Rose 22 年 前
コミット
344ca11ffd
46 ファイル変更1168 行追加641 行削除
  1. 7 4
      panda/src/chan/animChannel.cxx
  2. 5 3
      panda/src/chan/animChannelMatrixXfmTable.I
  3. 69 60
      panda/src/chan/animChannelMatrixXfmTable.cxx
  4. 5 10
      panda/src/chan/animChannelMatrixXfmTable.h
  5. 10 8
      panda/src/chan/movingPartMatrix.cxx
  6. 1 1
      panda/src/chan/movingPartMatrix.h
  7. 0 1
      panda/src/char/characterJoint.cxx
  8. 4 3
      panda/src/doc/eggSyntax.txt
  9. 2 2
      panda/src/egg/config_egg.cxx
  10. 2 2
      panda/src/egg/config_egg.h
  11. 25 10
      panda/src/egg/eggXfmAnimData.cxx
  12. 1 1
      panda/src/egg/eggXfmAnimData.h
  13. 126 155
      panda/src/egg/eggXfmSAnim.cxx
  14. 1 2
      panda/src/egg/eggXfmSAnim.h
  15. 5 3
      panda/src/gobj/lens.cxx
  16. 7 2
      panda/src/linmath/compose_matrix.cxx
  17. 7 6
      panda/src/linmath/compose_matrix.h
  18. 91 44
      panda/src/linmath/compose_matrix_src.I
  19. 41 32
      panda/src/linmath/compose_matrix_src.cxx
  20. 39 12
      panda/src/linmath/compose_matrix_src.h
  21. 21 30
      panda/src/linmath/lmatrix3_src.I
  22. 71 0
      panda/src/linmath/lmatrix3_src.cxx
  23. 13 5
      panda/src/linmath/lmatrix3_src.h
  24. 35 35
      panda/src/linmath/lmatrix4_src.I
  25. 13 5
      panda/src/linmath/lmatrix4_src.h
  26. 19 41
      panda/src/mathutil/fftCompressor.cxx
  27. 5 5
      panda/src/mathutil/fftCompressor.h
  28. 6 4
      panda/src/parametrics/parametricCurveCollection.cxx
  29. 0 6
      panda/src/pgraph/config_pgraph.cxx
  30. 0 1
      panda/src/pgraph/config_pgraph.h
  31. 58 0
      panda/src/pgraph/nodePath.I
  32. 214 56
      panda/src/pgraph/nodePath.cxx
  33. 38 2
      panda/src/pgraph/nodePath.h
  34. 82 1
      panda/src/pgraph/transformState.I
  35. 60 27
      panda/src/pgraph/transformState.cxx
  36. 35 21
      panda/src/pgraph/transformState.h
  37. 3 2
      panda/src/putil/bam.h
  38. 0 1
      panda/src/shader/planarReflector.cxx
  39. 0 1
      panda/src/shader/spheretexReflector.cxx
  40. 3 2
      panda/src/text/textNode.cxx
  41. 6 3
      panda/src/tform/driveInterface.cxx
  42. 23 23
      panda/src/tform/trackball.cxx
  43. 5 5
      pandatool/src/egg-optchar/eggOptchar.cxx
  44. 5 1
      pandatool/src/eggcharbase/eggCharacterData.cxx
  45. 4 2
      pandatool/src/eggcharbase/eggMatrixTablePointer.cxx
  46. 1 1
      pandatool/src/mayaegg/mayaToEggConverter.cxx

+ 7 - 4
panda/src/chan/animChannel.cxx

@@ -19,7 +19,7 @@
 
 
 #include "animChannel.h"
 #include "animChannel.h"
 
 
-#include <compose_matrix.h>
+#include "compose_matrix.h"
 
 
 // Tell GCC that we'll take care of the instantiation explicitly here.
 // Tell GCC that we'll take care of the instantiation explicitly here.
 #ifdef __GNUC__
 #ifdef __GNUC__
@@ -33,9 +33,9 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void ACMatrixSwitchType::
 void ACMatrixSwitchType::
 output_value(ostream &out, const ACMatrixSwitchType::ValueType &value) {
 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]) &&
       if (IS_NEARLY_EQUAL(scale[0], scale[1]) &&
           IS_NEARLY_EQUAL(scale[1], scale[2])) {
           IS_NEARLY_EQUAL(scale[1], scale[2])) {
         out << " scale " << scale[0];
         out << " scale " << scale[0];
@@ -43,6 +43,9 @@ output_value(ostream &out, const ACMatrixSwitchType::ValueType &value) {
         out << " scale " << scale;
         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))) {
     if (!hpr.almost_equal(LVecBase3f(0.0f, 0.0f, 0.0f))) {
       out << " hpr " << hpr;
       out << " hpr " << hpr;

+ 5 - 3
panda/src/chan/animChannelMatrixXfmTable.I

@@ -77,11 +77,12 @@ clear_table(char table_id) {
 //       Access: Protected, Static
 //       Access: Protected, Static
 //  Description: Returns the table ID associated with the indicated
 //  Description: Returns the table ID associated with the indicated
 //               table index number.  This is the letter 'i', 'j',
 //               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::
 INLINE char AnimChannelMatrixXfmTable::
 get_table_id(int table_index) {
 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::
 INLINE float AnimChannelMatrixXfmTable::
 get_default_value(int table_index) {
 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];
 }
 }
 
 

+ 69 - 60
panda/src/chan/animChannelMatrixXfmTable.cxx

@@ -21,24 +21,16 @@
 #include "animBundle.h"
 #include "animBundle.h"
 #include "config_chan.h"
 #include "config_chan.h"
 
 
-#include <compose_matrix.h>
-#include <indent.h>
-#include <datagram.h>
-#include <datagramIterator.h>
-#include <bamReader.h>
-#include <bamWriter.h>
-#include <fftCompressor.h>
+#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;
 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
 //     Function: AnimChannelMatrixXfmTable::Constructor
 //       Access: Public
 //       Access: Public
@@ -66,7 +58,7 @@ AnimChannelMatrixXfmTable(void)
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool AnimChannelMatrixXfmTable::
 bool AnimChannelMatrixXfmTable::
 has_changed(int last_frame, int this_frame) {
 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].size() > 1) {
       if (_tables[i][last_frame % _tables[i].size()] !=
       if (_tables[i][last_frame % _tables[i].size()] !=
           _tables[i][this_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::
 void AnimChannelMatrixXfmTable::
 get_value(int frame, LMatrix4f &mat) {
 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()) {
     if (_tables[i].empty()) {
       components[i] = get_default_value(i);
       components[i] = get_default_value(i);
     } else {
     } else {
@@ -106,12 +98,12 @@ get_value(int frame, LMatrix4f &mat) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void AnimChannelMatrixXfmTable::
 void AnimChannelMatrixXfmTable::
 get_value_no_scale(int frame, LMatrix4f &mat) {
 get_value_no_scale(int frame, LMatrix4f &mat) {
-  float components[num_tables];
+  float components[num_matrix_components];
   components[0] = 1.0f;
   components[0] = 1.0f;
   components[1] = 1.0f;
   components[1] = 1.0f;
   components[2] = 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()) {
     if (_tables[i].empty()) {
       components[i] = get_default_value(i);
       components[i] = get_default_value(i);
     } else {
     } else {
@@ -147,7 +139,7 @@ get_scale(int frame, float scale[3]) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void AnimChannelMatrixXfmTable::
 void AnimChannelMatrixXfmTable::
 clear_all_tables() {
 clear_all_tables() {
-  for (int i = 0; i < num_tables; i++) {
+  for (int i = 0; i < num_matrix_components; i++) {
     _tables[i] = NULL;
     _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.
   // Write a list of all the sub-tables that have data.
   bool found_any = false;
   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()) {
     if (!_tables[i].empty()) {
       out << get_table_id(i) << _tables[i].size();
       out << get_table_id(i) << _tables[i].size();
       found_any = true;
       found_any = true;
@@ -216,12 +208,12 @@ write(ostream &out, int indent_level) const {
 //     Function: AnimChannelMatrixXfmTable::get_table_index
 //     Function: AnimChannelMatrixXfmTable::get_table_index
 //       Access: Protected, Static
 //       Access: Protected, Static
 //  Description: Returns the table index number, a value between 0 and
 //  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.
 //               id.  Returns -1 if the table id is invalid.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 int AnimChannelMatrixXfmTable::
 int AnimChannelMatrixXfmTable::
 get_table_index(char table_id) {
 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)) {
     if (table_id == get_table_id(i)) {
       return i;
       return i;
     }
     }
@@ -237,8 +229,7 @@ get_table_index(char table_id) {
 //               the particular object to a Datagram
 //               the particular object to a Datagram
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void AnimChannelMatrixXfmTable::
 void AnimChannelMatrixXfmTable::
-write_datagram(BamWriter *manager, Datagram &me)
-{
+write_datagram(BamWriter *manager, Datagram &me) {
   AnimChannelMatrix::write_datagram(manager, me);
   AnimChannelMatrix::write_datagram(manager, me);
 
 
   if (compress_channels && !FFTCompressor::is_compression_available()) {
   if (compress_channels && !FFTCompressor::is_compression_available()) {
@@ -250,7 +241,7 @@ write_datagram(BamWriter *manager, Datagram &me)
   me.add_bool(compress_channels);
   me.add_bool(compress_channels);
   if (!compress_channels) {
   if (!compress_channels) {
     // Write out everything uncompressed, as a stream of floats.
     // 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());
       me.add_uint16(_tables[i].size());
       for(int j = 0; j < (int)_tables[i].size(); j++) {
       for(int j = 0; j < (int)_tables[i].size(); j++) {
         me.add_float32(_tables[i][j]);
         me.add_float32(_tables[i][j]);
@@ -264,9 +255,9 @@ write_datagram(BamWriter *manager, Datagram &me)
     compressor.set_quality(compress_chan_quality);
     compressor.set_quality(compress_chan_quality);
     compressor.write_header(me);
     compressor.write_header(me);
 
 
-    // First, write out the scales.
+    // First, write out the scales and shears.
     int i;
     int i;
-    for(i = 0; i < 3; i++) {
+    for (i = 0; i < 6; i++) {
       compressor.write_reals(me, _tables[i], _tables[i].size());
       compressor.write_reals(me, _tables[i], _tables[i].size());
     }
     }
 
 
@@ -274,18 +265,18 @@ write_datagram(BamWriter *manager, Datagram &me)
     // a HPR array.
     // a HPR array.
     vector_LVecBase3f hprs;
     vector_LVecBase3f hprs;
     int hprs_length =
     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);
     hprs.reserve(hprs_length);
     for (i = 0; i < hprs_length; i++) {
     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));
       hprs.push_back(LVecBase3f(h, p, r));
     }
     }
     compressor.write_hprs(me, &hprs[0], hprs_length);
     compressor.write_hprs(me, &hprs[0], hprs_length);
 
 
     // And now the translations.
     // 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());
       compressor.write_reals(me, _tables[i], _tables[i].size());
     }
     }
   }
   }
@@ -300,21 +291,26 @@ write_datagram(BamWriter *manager, Datagram &me)
 //               place
 //               place
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void AnimChannelMatrixXfmTable::
 void AnimChannelMatrixXfmTable::
-fillin(DatagramIterator& scan, BamReader* manager)
-{
+fillin(DatagramIterator &scan, BamReader *manager) {
   AnimChannelMatrix::fillin(scan, manager);
   AnimChannelMatrix::fillin(scan, manager);
 
 
   bool wrote_compressed = scan.get_bool();
   bool wrote_compressed = scan.get_bool();
 
 
   if (!wrote_compressed) {
   if (!wrote_compressed) {
     // Regular floats.
     // 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 {
   } else {
@@ -330,32 +326,45 @@ fillin(DatagramIterator& scan, BamReader* manager)
     compressor.read_header(scan);
     compressor.read_header(scan);
 
 
     int i;
     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());
       compressor.read_reals(scan, ind_table.v());
       _tables[i] = ind_table;
       _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.
     // Read in the HPR array and store it back in the joint angles.
     vector_LVecBase3f hprs;
     vector_LVecBase3f hprs;
     compressor.read_hprs(scan, 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++) {
     for (i = 0; i < (int)hprs.size(); i++) {
       h_table[i] = hprs[i][0];
       h_table[i] = hprs[i][0];
       p_table[i] = hprs[i][1];
       p_table[i] = hprs[i][1];
       r_table[i] = hprs[i][2];
       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.
     // 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());
       compressor.read_reals(scan, ind_table.v());
       _tables[i] = ind_table;
       _tables[i] = ind_table;
     }
     }
@@ -365,11 +374,11 @@ fillin(DatagramIterator& scan, BamReader* manager)
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AnimChannelMatrixXfmTable::make_AnimChannelMatrixXfmTable
 //     Function: AnimChannelMatrixXfmTable::make_AnimChannelMatrixXfmTable
 //       Access: Protected
 //       Access: Protected
-//  Description: Factory method to generate a AnimChannelMatrixXfmTable object
+//  Description: Factory method to generate an
+//               AnimChannelMatrixXfmTable object.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-TypedWritable* AnimChannelMatrixXfmTable::
-make_AnimChannelMatrixXfmTable(const FactoryParams &params)
-{
+TypedWritable *AnimChannelMatrixXfmTable::
+make_AnimChannelMatrixXfmTable(const FactoryParams &params) {
   AnimChannelMatrixXfmTable *me = new AnimChannelMatrixXfmTable;
   AnimChannelMatrixXfmTable *me = new AnimChannelMatrixXfmTable;
   DatagramIterator scan;
   DatagramIterator scan;
   BamReader *manager;
   BamReader *manager;
@@ -382,11 +391,11 @@ make_AnimChannelMatrixXfmTable(const FactoryParams &params)
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AnimChannelMatrixXfmTable::register_with_factory
 //     Function: AnimChannelMatrixXfmTable::register_with_factory
 //       Access: Public, Static
 //       Access: Public, Static
-//  Description: Factory method to generate a AnimChannelMatrixXfmTable object
+//  Description: Factory method to generate an
+//               AnimChannelMatrixXfmTable object.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void AnimChannelMatrixXfmTable::
 void AnimChannelMatrixXfmTable::
-register_with_read_factory(void)
-{
+register_with_read_factory() {
   BamReader::get_factory()->register_factory(get_class_type(), make_AnimChannelMatrixXfmTable);
   BamReader::get_factory()->register_factory(get_class_type(), make_AnimChannelMatrixXfmTable);
 }
 }
 
 

+ 5 - 10
panda/src/chan/animChannelMatrixXfmTable.h

@@ -19,12 +19,13 @@
 #ifndef ANIMCHANNELMATRIXXFMTABLE_H
 #ifndef ANIMCHANNELMATRIXXFMTABLE_H
 #define ANIMCHANNELMATRIXXFMTABLE_H
 #define ANIMCHANNELMATRIXXFMTABLE_H
 
 
-#include <pandabase.h>
+#include "pandabase.h"
 
 
 #include "animChannel.h"
 #include "animChannel.h"
 
 
-#include <pointerToArray.h>
-#include <pta_float.h>
+#include "pointerToArray.h"
+#include "pta_float.h"
+#include "compose_matrix.h"
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : AnimChannelMatrixXfmTable
 //       Class : AnimChannelMatrixXfmTable
@@ -59,13 +60,7 @@ protected:
   static int get_table_index(char table_id);
   static int get_table_index(char table_id);
   INLINE static float get_default_value(int table_index);
   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:
 public:
   static void register_with_read_factory(void);
   static void register_with_read_factory(void);

+ 10 - 8
panda/src/chan/movingPartMatrix.cxx

@@ -19,11 +19,11 @@
 
 
 #include "movingPartMatrix.h"
 #include "movingPartMatrix.h"
 
 
-#include <compose_matrix.h>
-#include <datagram.h>
-#include <datagramIterator.h>
-#include <bamReader.h>
-#include <bamWriter.h>
+#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.
 // Tell GCC that we'll take care of the instantiation explicitly here.
 #ifdef __GNUC__
 #ifdef __GNUC__
@@ -93,6 +93,8 @@ get_blend_value(const PartBundle *root) {
       // resulting matrix to eliminate artificially-introduced scales,
       // resulting matrix to eliminate artificially-introduced scales,
       // and then reapply the scales.
       // and then reapply the scales.
 
 
+      // Perhaps we should treat shear the same as a scale here?
+
       _value = 0.0f;
       _value = 0.0f;
       LVector3f scale(0.0f, 0.0f, 0.0f);
       LVector3f scale(0.0f, 0.0f, 0.0f);
       float net = 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.
       // 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);
     }
     }
   }
   }
 }
 }

+ 1 - 1
panda/src/chan/movingPartMatrix.h

@@ -19,7 +19,7 @@
 #ifndef MOVINGPARTMATRIX_H
 #ifndef MOVINGPARTMATRIX_H
 #define MOVINGPARTMATRIX_H
 #define MOVINGPARTMATRIX_H
 
 
-#include <pandabase.h>
+#include "pandabase.h"
 
 
 #include "movingPart.h"
 #include "movingPart.h"
 #include "animChannel.h"
 #include "animChannel.h"

+ 0 - 1
panda/src/char/characterJoint.cxx

@@ -19,7 +19,6 @@
 #include "characterJoint.h"
 #include "characterJoint.h"
 #include "config_char.h"
 #include "config_char.h"
 
 
-#include "compose_matrix.h"
 #include "datagram.h"
 #include "datagram.h"
 #include "datagramIterator.h"
 #include "datagramIterator.h"
 #include "bamReader.h"
 #include "bamReader.h"

+ 4 - 3
panda/src/doc/eggSyntax.txt

@@ -1227,18 +1227,19 @@ GROUPING ENTRIES
   <Xfm$Anim> name {
   <Xfm$Anim> name {
       <Scalar> fps { 24 }
       <Scalar> fps { 24 }
       <Char*> order { sphrt }
       <Char*> order { sphrt }
-      <Char*> contents { ijkphrxyz }
+      <Char*> contents { ijkabcphrxyz }
       <V> { values }
       <V> { values }
   }
   }
 
 
     This is a table of matrix transforms, one per frame, such as may
     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
     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; <V> is a list of numbers of length(contents)
     column of the table; <V> is a list of numbers of length(contents)
     * num_frames.  Each letter of the contents string corresponds to a
     * num_frames.  Each letter of the contents string corresponds to a
     type of transformation:
     type of transformation:
 
 
       i, j, k - scale in x, y, z directions, respectively
       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
       p, h, r - rotate by pitch, heading, roll
       x, y, z - translate in x, y, z directions
       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
     string.  The order the transforms are applied is defined by the
     order string:
     order string:
 
 
-      s       - all scale transforms
+      s       - all scale and shear transforms
       p, h, r - individual rotate transforms
       p, h, r - individual rotate transforms
       t       - all translation transforms
       t       - all translation transforms
 
 

+ 2 - 2
panda/src/egg/config_egg.cxx

@@ -51,8 +51,8 @@
 #include "eggXfmAnimData.h"
 #include "eggXfmAnimData.h"
 #include "eggXfmSAnim.h"
 #include "eggXfmSAnim.h"
 
 
-#include <dconfig.h>
-#include <get_config_path.h>
+#include "dconfig.h"
+#include "get_config_path.h"
 
 
 Configure(config_egg);
 Configure(config_egg);
 NotifyCategoryDef(egg, "");
 NotifyCategoryDef(egg, "");

+ 2 - 2
panda/src/egg/config_egg.h

@@ -19,8 +19,8 @@
 #ifndef CONFIG_EGG_H
 #ifndef CONFIG_EGG_H
 #define CONFIG_EGG_H
 #define CONFIG_EGG_H
 
 
-#include <pandabase.h>
-#include <notifyCategoryProxy.h>
+#include "pandabase.h"
+#include "notifyCategoryProxy.h"
 
 
 class DSearchPath;
 class DSearchPath;
 
 

+ 25 - 10
panda/src/egg/eggXfmAnimData.cxx

@@ -22,10 +22,10 @@
 #include "eggMiscFuncs.h"
 #include "eggMiscFuncs.h"
 #include "config_egg.h"
 #include "config_egg.h"
 
 
-#include <indent.h>
-#include <luse.h>
-#include <lmatrix.h>
-#include <compose_matrix.h>
+#include "indent.h"
+#include "luse.h"
+#include "lmatrix.h"
+#include "compose_matrix.h"
 
 
 TypeHandle EggXfmAnimData::_type_handle;
 TypeHandle EggXfmAnimData::_type_handle;
 
 
@@ -94,6 +94,7 @@ EggXfmAnimData(const EggXfmSAnim &convert_from)
 void EggXfmAnimData::
 void EggXfmAnimData::
 get_value(int row, LMatrix4d &mat) const {
 get_value(int row, LMatrix4d &mat) const {
   LVector3d scale(1.0, 1.0, 1.0);
   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 hpr(0.0, 0.0, 0.0);
   LVector3d translate(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;
       scale[2] = value;
       break;
       break;
 
 
+    case 'a':
+      shear[0] = value;
+      break;
+      
+    case 'b':
+      shear[1] = value;
+      break;
+      
+    case 'c':
+      shear[2] = value;
+      break;
+
     case 'h':
     case 'h':
       hpr[0] = value;
       hpr[0] = value;
       break;
       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);
                                   _coordsys);
 }
 }
 
 
@@ -221,26 +234,28 @@ r_transform(const LMatrix4d &mat, const LMatrix4d &inv,
       egg_cat.error()
       egg_cat.error()
         << "Transform from " << _coordsys << " to " << to_cs
         << "Transform from " << _coordsys << " to " << to_cs
         << " failed!\n";
         << " 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)
       egg_cat.error(false)
         << "orig:\n" << orig_mat
         << "orig:\n" << orig_mat
         << "d = " << d
         << "d = " << d
         << "\n  scale: " << scale
         << "\n  scale: " << scale
+        << "\n  shear: " << shear
         << "\n  hpr: " << hpr
         << "\n  hpr: " << hpr
         << "\n  trans: " << trans << "\n";
         << "\n  trans: " << trans << "\n";
 
 
       LMatrix4d new_mat = inv1 * orig_mat * mat;
       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)
       egg_cat.error(false)
         << "new:\n" << new_mat
         << "new:\n" << new_mat
         << "d = " << d
         << "d = " << d
         << "\n  scale: " << scale
         << "\n  scale: " << scale
+        << "\n  shear: " << shear
         << "\n  hpr: " << hpr
         << "\n  hpr: " << hpr
         << "\n  trans: " << trans << "\n";
         << "\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
     // matrix or some such thing that cannot be represented in an anim
     // file.
     // file.
     nassertv(result);
     nassertv(result);

+ 1 - 1
panda/src/egg/eggXfmAnimData.h

@@ -19,7 +19,7 @@
 #ifndef EGGXFMANIMDATA_H
 #ifndef EGGXFMANIMDATA_H
 #define EGGXFMANIMDATA_H
 #define EGGXFMANIMDATA_H
 
 
-#include <pandabase.h>
+#include "pandabase.h"
 
 
 #include "eggAnimData.h"
 #include "eggAnimData.h"
 #include "eggXfmSAnim.h"
 #include "eggXfmSAnim.h"

+ 126 - 155
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_legacy = "sphrt";
 const string EggXfmSAnim::_standard_order_hpr_fix = "srpht";
 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
 //     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
   // write out all the non-table children first, then write out the
   // table children in our expected order.  (Normally there are only
   // table children in our expected order.  (Normally there are only
   // table children.)
   // 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;
   const_iterator ci;
   for (ci = begin(); ci != end(); ++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.
       // Each child SAnimData table should have a one-letter name.
       nassertv(sanim->get_name().length() == 1);
       nassertv(sanim->get_name().length() == 1);
       char name = sanim->get_name()[0];
       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);
         nassertv(tables[index] == (EggSAnimData *)NULL);
         tables[index] = sanim;
         tables[index] = sanim;
       }
       }
@@ -206,7 +202,7 @@ write(ostream &out, int indent_level) const {
   }
   }
 
 
   // Now write out the table children in our normal order.
   // 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) {
     if (tables[i] != (EggSAnimData *)NULL) {
       tables[i]->write(out, indent_level + 2);
       tables[i]->write(out, indent_level + 2);
     }
     }
@@ -227,6 +223,7 @@ write(ostream &out, int indent_level) const {
 void EggXfmSAnim::
 void EggXfmSAnim::
 compose_with_order(LMatrix4d &mat,
 compose_with_order(LMatrix4d &mat,
                    const LVecBase3d &scale,
                    const LVecBase3d &scale,
+                   const LVecBase3d &shear,
                    const LVecBase3d &hpr,
                    const LVecBase3d &hpr,
                    const LVecBase3d &trans,
                    const LVecBase3d &trans,
                    const string &order,
                    const string &order,
@@ -247,7 +244,7 @@ compose_with_order(LMatrix4d &mat,
   for (pi = order.begin(); pi != order.end(); ++pi) {
   for (pi = order.begin(); pi != order.end(); ++pi) {
     switch (*pi) {
     switch (*pi) {
     case 's':
     case 's':
-      mat = mat * LMatrix4d::scale_mat(scale);
+      mat = mat * LMatrix4d::scale_shear_mat(scale, shear, cs);
       break;
       break;
 
 
     case 'h':
     case 'h':
@@ -318,11 +315,12 @@ get_num_rows() const {
 //               table of matrices.  It is an error to call this if
 //               table of matrices.  It is an error to call this if
 //               any SAnimData children of this node have an improper
 //               any SAnimData children of this node have an improper
 //               name (e.g. not a single letter, or not one of
 //               name (e.g. not a single letter, or not one of
-//               "ijkhprxyz").
+//               "ijkabchprxyz").
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void EggXfmSAnim::
 void EggXfmSAnim::
 get_value(int row, LMatrix4d &mat) const {
 get_value(int row, LMatrix4d &mat) const {
   LVector3d scale(1.0, 1.0, 1.0);
   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 hpr(0.0, 0.0, 0.0);
   LVector3d translate(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;
         scale[2] = value;
         break;
         break;
 
 
+      case 'a':
+        shear[0] = value;
+        break;
+
+      case 'b':
+        shear[1] = value;
+        break;
+
+      case 'c':
+        shear[2] = value;
+        break;
+
       case 'h':
       case 'h':
         hpr[0] = value;
         hpr[0] = value;
         break;
         break;
@@ -393,7 +403,7 @@ get_value(int row, LMatrix4d &mat) const {
   }
   }
 
 
   // So now we've got the nine components; build a matrix.
   // 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.
 //               normalize() first if you are not sure.
 //
 //
 //               The return value is true if the matrix can be
 //               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::
 bool EggXfmSAnim::
 set_value(int row, const LMatrix4d &mat) {
 set_value(int row, const LMatrix4d &mat) {
   nassertr(get_order() == get_standard_order(), false);
   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.
   // Sanity check our sub-tables.
 #ifndef NDEBUG
 #ifndef NDEBUG
   int table_length = -1;
   int table_length = -1;
-  int num_tables = 0;
 #endif
 #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
 #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);
-      }
+    // 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
 #endif
+    sanim->set_value(row, components[i]);
+  }
 
 
-      // 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);
-      }
+#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
 
 
-  nassertr(num_tables == 9, false);
-  return true;
+  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
 //               table of matrices.  It is an error to call this if
 //               any SAnimData children of this node have an improper
 //               any SAnimData children of this node have an improper
 //               name (e.g. not a single letter, or not one of
 //               name (e.g. not a single letter, or not one of
-//               "ijkhprxyz").
+//               "ijkabchprxyz").
 //
 //
 //               This function has the further requirement that all
 //               This function has the further requirement that all
 //               nine of the subtables must exist and be of the same
 //               nine of the subtables must exist and be of the same
 //               length.  Furthermore, the order string must be the
 //               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
 //               Thus, you probably cannot take an existing
 //               EggXfmSAnim object and start adding matrices to the
 //               EggXfmSAnim object and start adding matrices to the
@@ -521,21 +509,20 @@ set_value(int row, const LMatrix4d &mat) {
 //               you on an existing EggXfmSAnim.
 //               you on an existing EggXfmSAnim.
 //
 //
 //               This function may fail silently if the matrix cannot
 //               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::
 bool EggXfmSAnim::
 add_data(const LMatrix4d &mat) {
 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 (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);
       add_child(sanim);
     }
     }
 
 
@@ -547,73 +534,57 @@ add_data(const LMatrix4d &mat) {
 
 
 #ifndef NDEBUG
 #ifndef NDEBUG
   int table_length = -1;
   int table_length = -1;
-  int num_tables = 0;
 #endif
 #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
 #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);
-      }
+    // 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
 #endif
+    sanim->add_data(components[i]);
+  }
 
 
-      // 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);
-      }
+#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;
   }
   }
-
-  nassertr(num_tables == 9, false);
+#endif
 
 
   return add_ok;
   return add_ok;
 }
 }
@@ -723,7 +694,7 @@ normalize_by_expanding() {
   // are.
   // are.
   int num_tables = 0;
   int num_tables = 0;
   int table_length = 1;
   int table_length = 1;
-  string remaining_tables = "ijkhprxyz";
+  string remaining_tables = matrix_component_letters;
 
 
   for (ci = begin(); ci != end(); ++ci) {
   for (ci = begin(); ci != end(); ++ci) {
     if ((*ci)->is_of_type(EggSAnimData::get_class_type())) {
     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.
     // Create new, default, children for each table we lack.
     for (size_t p = 0; p < remaining_tables.length(); p++) {
     for (size_t p = 0; p < remaining_tables.length(); p++) {
       if (remaining_tables[p] != ' ') {
       if (remaining_tables[p] != ' ') {

+ 1 - 2
panda/src/egg/eggXfmSAnim.h

@@ -71,6 +71,7 @@ public:
 
 
   static void compose_with_order(LMatrix4d &mat,
   static void compose_with_order(LMatrix4d &mat,
                                  const LVecBase3d &scale,
                                  const LVecBase3d &scale,
+                                 const LVecBase3d &shear,
                                  const LVecBase3d &hpr,
                                  const LVecBase3d &hpr,
                                  const LVecBase3d &trans,
                                  const LVecBase3d &trans,
                                  const string &order,
                                  const string &order,
@@ -94,8 +95,6 @@ private:
 
 
   static const string _standard_order_legacy;
   static const string _standard_order_legacy;
   static const string _standard_order_hpr_fix;
   static const string _standard_order_hpr_fix;
-  static const string _table_ids;
-  static const int _num_table_ids;
   
   
 public:
 public:
 
 

+ 5 - 3
panda/src/gobj/lens.cxx

@@ -1275,8 +1275,8 @@ void Lens::
 compute_view_hpr() {
 compute_view_hpr() {
   if ((_user_flags & UF_view_hpr) == 0) {
   if ((_user_flags & UF_view_hpr) == 0) {
     const LMatrix4f &view_mat = get_view_mat();
     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);
   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_mat) == 0) {
     if ((_user_flags & UF_view_hpr) != 0) {
     if ((_user_flags & UF_view_hpr) != 0) {
       compose_matrix(_lens_mat,
       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);
                      LVecBase3f(0.0f, 0.0f, 0.0f), _cs);
 
 
     } else if ((_user_flags & UF_view_vector) != 0) {
     } else if ((_user_flags & UF_view_vector) != 0) {

+ 7 - 2
panda/src/linmath/compose_matrix.cxx

@@ -27,5 +27,10 @@
 #include "compose_matrix_src.cxx"
 #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
+};

+ 7 - 6
panda/src/linmath/compose_matrix.h

@@ -44,17 +44,18 @@
 #include "lvec2_ops.h"
 #include "lvec2_ops.h"
 #include "lvec3_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 "fltnames.h"
 #include "compose_matrix_src.h"
 #include "compose_matrix_src.h"
 
 
 #include "dblnames.h"
 #include "dblnames.h"
 #include "compose_matrix_src.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
 #endif
 
 

+ 91 - 44
panda/src/linmath/compose_matrix_src.I

@@ -19,56 +19,130 @@
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: compose_matrix
 //     Function: compose_matrix
-//  Description: Computes the 4x4 matrix according to scale, rotation,
-//               and translation.
+//  Description: Computes the 4x4 matrix according to scale, shear,
+//               rotation, and translation.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH void
 INLINE_LINMATH void
 compose_matrix(FLOATNAME(LMatrix4) &mat,
 compose_matrix(FLOATNAME(LMatrix4) &mat,
                const FLOATNAME(LVecBase3) &scale,
                const FLOATNAME(LVecBase3) &scale,
+               const FLOATNAME(LVecBase3) &shear,
                const FLOATNAME(LVecBase3) &hpr,
                const FLOATNAME(LVecBase3) &hpr,
                const FLOATNAME(LVecBase3) &translate,
                const FLOATNAME(LVecBase3) &translate,
                CoordinateSystem cs) {
                CoordinateSystem cs) {
   FLOATNAME(LMatrix3) upper3;
   FLOATNAME(LMatrix3) upper3;
-  compose_matrix(upper3, scale, hpr, cs);
+  compose_matrix(upper3, scale, shear, hpr, cs);
   mat = FLOATNAME(LMatrix4)(upper3, translate);
   mat = FLOATNAME(LMatrix4)(upper3, translate);
 }
 }
 
 
 INLINE_LINMATH void
 INLINE_LINMATH void
 compose_matrix(FLOATNAME(LMatrix4) &mat,
 compose_matrix(FLOATNAME(LMatrix4) &mat,
-               const FLOATTYPE components[9],
+               const FLOATTYPE components[num_matrix_components],
                CoordinateSystem cs) {
                CoordinateSystem cs) {
   FLOATNAME(LVector3) scale(components[0],
   FLOATNAME(LVector3) scale(components[0],
                             components[1],
                             components[1],
                             components[2]);
                             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);
+  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
 //     Function: decompose_matrix
 //  Description: Extracts out the components of an affine 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.
+//               Returns true if the scale, shear, hpr, and translate
+//               completely describe the matrix, or false if the
+//               matrix is not affine.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH bool
 INLINE_LINMATH bool
 decompose_matrix(const FLOATNAME(LMatrix4) &mat,
 decompose_matrix(const FLOATNAME(LMatrix4) &mat,
                  FLOATNAME(LVecBase3) &scale,
                  FLOATNAME(LVecBase3) &scale,
+		 FLOATNAME(LVecBase3) &shear,
                  FLOATNAME(LVecBase3) &hpr,
                  FLOATNAME(LVecBase3) &hpr,
                  FLOATNAME(LVecBase3) &translate,
                  FLOATNAME(LVecBase3) &translate,
                  CoordinateSystem cs) {
                  CoordinateSystem cs) {
   // Get the translation first.
   // Get the translation first.
   mat.get_row3(translate,3);
   mat.get_row3(translate,3);
-  return decompose_matrix(mat.get_upper_3(), scale, hpr, cs);
+  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,
+//               and translation.
+////////////////////////////////////////////////////////////////////
+INLINE_LINMATH void
+compose_matrix(FLOATNAME(LMatrix4) &mat,
+               const FLOATNAME(LVecBase3) &scale,
+               const FLOATNAME(LVecBase3) &hpr,
+               const FLOATNAME(LVecBase3) &translate,
+               CoordinateSystem cs) {
+  FLOATNAME(LMatrix3) upper3;
+  compose_matrix(upper3, scale, hpr, cs);
+  mat = FLOATNAME(LMatrix4)(upper3, translate);
+}
+
+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());
 }
 }
 
 
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: decompose_matrix
 //     Function: decompose_matrix
 //  Description: Extracts out the components of an affine matrix.
 //  Description: Extracts out the components of an affine matrix.
@@ -76,41 +150,14 @@ decompose_matrix(const FLOATNAME(LMatrix4) &mat,
 //               completely describe the matrix, or false if there is
 //               completely describe the matrix, or false if there is
 //               also a shear component or if the matrix is not
 //               also a shear component or if the matrix is not
 //               affine.
 //               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
 INLINE_LINMATH bool
 decompose_matrix(const FLOATNAME(LMatrix4) &mat,
 decompose_matrix(const FLOATNAME(LMatrix4) &mat,
                  FLOATNAME(LVecBase3) &scale,
                  FLOATNAME(LVecBase3) &scale,
                  FLOATNAME(LVecBase3) &hpr,
                  FLOATNAME(LVecBase3) &hpr,
                  FLOATNAME(LVecBase3) &translate,
                  FLOATNAME(LVecBase3) &translate,
-                 FLOATTYPE roll,
                  CoordinateSystem cs) {
                  CoordinateSystem cs) {
   // Get the translation first.
   // Get the translation first.
   mat.get_row3(translate,3);
   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;
+  return decompose_matrix(mat.get_upper_3(), scale, hpr, cs);
 }
 }

+ 41 - 32
panda/src/linmath/compose_matrix_src.cxx

@@ -19,11 +19,13 @@
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: compose_matrix
 //     Function: compose_matrix
-//  Description: Computes the 3x3 matrix from scale and rotation.
+//  Description: Computes the 3x3 matrix from scale, shear, and
+//               rotation.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void
 void
 compose_matrix(FLOATNAME(LMatrix3) &mat,
 compose_matrix(FLOATNAME(LMatrix3) &mat,
                const FLOATNAME(LVecBase3) &scale,
                const FLOATNAME(LVecBase3) &scale,
+               const FLOATNAME(LVecBase3) &shear,
                const FLOATNAME(LVecBase3) &hpr,
                const FLOATNAME(LVecBase3) &hpr,
                CoordinateSystem cs) {
                CoordinateSystem cs) {
 
 
@@ -31,16 +33,18 @@ compose_matrix(FLOATNAME(LMatrix3) &mat,
   // as default until legacy tools are fixed to work with correct way
   // as default until legacy tools are fixed to work with correct way
 
 
   if (temp_hpr_fix) {
   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 {
   } 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
 //     Function: decompose_matrix
 //  Description: Extracts out the components of a 3x3 rotation 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
 bool
 decompose_matrix(const FLOATNAME(LMatrix3) &mat,
 decompose_matrix(const FLOATNAME(LMatrix3) &mat,
                  FLOATNAME(LVecBase3) &scale,
                  FLOATNAME(LVecBase3) &scale,
+                 FLOATNAME(LVecBase3) &shear,
                  FLOATNAME(LVecBase3) &hpr,
                  FLOATNAME(LVecBase3) &hpr,
                  CoordinateSystem cs) {
                  CoordinateSystem cs) {
   if (cs == CS_default) {
   if (cs == CS_default) {
@@ -595,29 +601,28 @@ decompose_matrix(const FLOATNAME(LMatrix3) &mat,
       << "after unwind, mat is " << new_mat << "\n";
       << "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
 //               component, rather than attempting to determine roll
 //               by examining the matrix; this helps alleviate roll
 //               by examining the matrix; this helps alleviate roll
 //               instability due to roundoff errors or gimbal lock.
 //               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
 bool
 decompose_matrix(const FLOATNAME(LMatrix3) &mat,
 decompose_matrix(const FLOATNAME(LMatrix3) &mat,

+ 39 - 12
panda/src/linmath/compose_matrix_src.h

@@ -21,51 +21,78 @@ BEGIN_PUBLISH
 EXPCL_PANDA void
 EXPCL_PANDA void
 compose_matrix(FLOATNAME(LMatrix3) &mat,
 compose_matrix(FLOATNAME(LMatrix3) &mat,
                const FLOATNAME(LVecBase3) &scale,
                const FLOATNAME(LVecBase3) &scale,
+               const FLOATNAME(LVecBase3) &shear,
                const FLOATNAME(LVecBase3) &hpr,
                const FLOATNAME(LVecBase3) &hpr,
                CoordinateSystem cs = CS_default);
                CoordinateSystem cs = CS_default);
 
 
 INLINE_LINMATH void
 INLINE_LINMATH void
 compose_matrix(FLOATNAME(LMatrix4) &mat,
 compose_matrix(FLOATNAME(LMatrix4) &mat,
                const FLOATNAME(LVecBase3) &scale,
                const FLOATNAME(LVecBase3) &scale,
+               const FLOATNAME(LVecBase3) &shear,
                const FLOATNAME(LVecBase3) &hpr,
                const FLOATNAME(LVecBase3) &hpr,
                const FLOATNAME(LVecBase3) &translate,
                const FLOATNAME(LVecBase3) &translate,
                CoordinateSystem cs = CS_default);
                CoordinateSystem cs = CS_default);
 
 
 INLINE_LINMATH void
 INLINE_LINMATH void
-compose_matrix(FLOATNAME(LMatrix4) &mat, const FLOATTYPE components[9],
+compose_matrix(FLOATNAME(LMatrix4) &mat, const FLOATTYPE components[num_matrix_components],
                CoordinateSystem cs = CS_default);
                CoordinateSystem cs = CS_default);
 
 
 EXPCL_PANDA bool
 EXPCL_PANDA bool
 decompose_matrix(const FLOATNAME(LMatrix3) &mat,
 decompose_matrix(const FLOATNAME(LMatrix3) &mat,
                  FLOATNAME(LVecBase3) &scale,
                  FLOATNAME(LVecBase3) &scale,
+                 FLOATNAME(LVecBase3) &shear,
                  FLOATNAME(LVecBase3) &hpr,
                  FLOATNAME(LVecBase3) &hpr,
                  CoordinateSystem cs = CS_default);
                  CoordinateSystem cs = CS_default);
 
 
-EXPCL_PANDA bool
-decompose_matrix(const FLOATNAME(LMatrix3) &mat,
-                 FLOATNAME(LVecBase3) &scale,
-                 FLOATNAME(LVecBase3) &hpr,
-                 FLOATTYPE roll,
-                 CoordinateSystem cs);
-
 INLINE_LINMATH bool
 INLINE_LINMATH bool
 decompose_matrix(const FLOATNAME(LMatrix4) &mat,
 decompose_matrix(const FLOATNAME(LMatrix4) &mat,
                  FLOATNAME(LVecBase3) &scale,
                  FLOATNAME(LVecBase3) &scale,
+                 FLOATNAME(LVecBase3) &shear,
                  FLOATNAME(LVecBase3) &hpr,
                  FLOATNAME(LVecBase3) &hpr,
                  FLOATNAME(LVecBase3) &translate,
                  FLOATNAME(LVecBase3) &translate,
                  CoordinateSystem cs = CS_default);
                  CoordinateSystem cs = CS_default);
 
 
 INLINE_LINMATH bool
 INLINE_LINMATH bool
-decompose_matrix(const FLOATNAME(LMatrix4) &mat,
+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,
+               CoordinateSystem cs = CS_default);
+
+INLINE_LINMATH void
+compose_matrix(FLOATNAME(LMatrix4) &mat,
+               const FLOATNAME(LVecBase3) &scale,
+               const FLOATNAME(LVecBase3) &hpr,
+               const FLOATNAME(LVecBase3) &translate,
+               CoordinateSystem cs = CS_default);
+
+INLINE EXPCL_PANDA bool
+decompose_matrix(const FLOATNAME(LMatrix3) &mat,
+                 FLOATNAME(LVecBase3) &scale,
+                 FLOATNAME(LVecBase3) &hpr,
+                 CoordinateSystem cs = CS_default);
+
+EXPCL_PANDA bool
+decompose_matrix(const FLOATNAME(LMatrix3) &mat,
                  FLOATNAME(LVecBase3) &scale,
                  FLOATNAME(LVecBase3) &scale,
                  FLOATNAME(LVecBase3) &hpr,
                  FLOATNAME(LVecBase3) &hpr,
-                 FLOATNAME(LVecBase3) &translate,
                  FLOATTYPE roll,
                  FLOATTYPE roll,
                  CoordinateSystem cs);
                  CoordinateSystem cs);
 
 
 INLINE_LINMATH bool
 INLINE_LINMATH bool
-decompose_matrix(const FLOATNAME(LMatrix4) &mat, FLOATTYPE components[9],
-                 CoordinateSystem CS = CS_default);
+decompose_matrix(const FLOATNAME(LMatrix4) &mat,
+                 FLOATNAME(LVecBase3) &scale,
+                 FLOATNAME(LVecBase3) &hpr,
+                 FLOATNAME(LVecBase3) &translate,
+                 CoordinateSystem cs = CS_default);
 
 
 END_PUBLISH
 END_PUBLISH
 
 

+ 21 - 30
panda/src/linmath/lmatrix3_src.I

@@ -558,28 +558,6 @@ multiply(const FLOATNAME(LMatrix3) &other1, const FLOATNAME(LMatrix3) &other2) {
   MATRIX3_PRODUCT((*this),other1,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
 //     Function: LMatrix3::matrix * scalar
 //       Access: Public
 //       Access: Public
@@ -1102,10 +1080,9 @@ scale_mat(FLOATTYPE sx, FLOATTYPE sy, FLOATTYPE sz) {
 //               shear in each of the three planes.
 //               shear in each of the three planes.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH FLOATNAME(LMatrix3) FLOATNAME(LMatrix3)::
 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.
 //               shear in each of the three planes.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH FLOATNAME(LMatrix3) FLOATNAME(LMatrix3)::
 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);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 71 - 0
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 =
 const FLOATNAME(LMatrix3) FLOATNAME(LMatrix3)::_ly_to_rz_mat =
   FLOATNAME(LMatrix3)::_flip_z_mat * FLOATNAME(LMatrix3)::_y_to_z_up_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
 //     Function: LMatrix::convert_mat
 //       Access: Public, Static
 //       Access: Public, Static

+ 13 - 5
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;
   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);
   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);
     scale_mat(FLOATTYPE sx, FLOATTYPE sy, FLOATTYPE sz);
 
 
   static INLINE_LINMATH FLOATNAME(LMatrix3)
   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, 
+              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)
   static INLINE_LINMATH FLOATNAME(LMatrix3)
-    shear_mat(FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz);
+    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,
   static const FLOATNAME(LMatrix3) &convert_mat(CoordinateSystem from,
                                                 CoordinateSystem to);
                                                 CoordinateSystem to);

+ 35 - 35
panda/src/linmath/lmatrix4_src.I

@@ -730,31 +730,6 @@ multiply(const FLOATNAME(LMatrix4) &other1, const FLOATNAME(LMatrix4) &other2) {
   MATRIX4_PRODUCT((*this),other1,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
 //     Function: LMatrix4::matrix * scalar
 //       Access: Public
 //       Access: Public
@@ -1359,11 +1334,9 @@ scale_mat(FLOATTYPE scale) {
 //               shear in each of the three planes.
 //               shear in each of the three planes.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH FLOATNAME(LMatrix4) FLOATNAME(LMatrix4)::
 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.
 //               shear in each of the three planes.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH FLOATNAME(LMatrix4) FLOATNAME(LMatrix4)::
 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);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 13 - 5
panda/src/linmath/lmatrix4_src.h

@@ -104,9 +104,6 @@ PUBLISHED:
   // this = other1 * other2
   // this = other1 * other2
   INLINE_LINMATH void multiply(const FLOATNAME(LMatrix4) &other1, const FLOATNAME(LMatrix4) &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 * (const FLOATNAME(LMatrix4) &other) const;
 
 
   INLINE_LINMATH FLOATNAME(LMatrix4) operator * (FLOATTYPE scalar) const;
   INLINE_LINMATH FLOATNAME(LMatrix4) operator * (FLOATTYPE scalar) const;
@@ -153,9 +150,20 @@ PUBLISHED:
     scale_mat(FLOATTYPE scale);
     scale_mat(FLOATTYPE scale);
 
 
   static INLINE_LINMATH FLOATNAME(LMatrix4)
   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, 
+              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)
   static INLINE_LINMATH FLOATNAME(LMatrix4)
-    shear_mat(FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz);
+    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) &y_to_z_up_mat();
   INLINE_LINMATH static const FLOATNAME(LMatrix4) &z_to_y_up_mat();
   INLINE_LINMATH static const FLOATNAME(LMatrix4) &z_to_y_up_mat();

+ 19 - 41
panda/src/mathutil/fftCompressor.cxx

@@ -19,9 +19,9 @@
 #include "fftCompressor.h"
 #include "fftCompressor.h"
 #include "config_mathutil.h"
 #include "config_mathutil.h"
 
 
-#include <datagram.h>
-#include <datagramIterator.h>
-#include <compose_matrix.h>
+#include "datagram.h"
+#include "datagramIterator.h"
+#include "compose_matrix.h"
 #include <math.h>
 #include <math.h>
 
 
 #ifdef HAVE_FFTW
 #ifdef HAVE_FFTW
@@ -348,7 +348,8 @@ write_hprs(Datagram &datagram, const LVecBase3f *array, int length) {
       m20, m21, m22;
       m20, m21, m22;
     for (int i = 0; i < length; i++) {
     for (int i = 0; i < length; i++) {
       LMatrix3f mat;
       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));
       m00.push_back(mat(0, 0));
       m01.push_back(mat(0, 1));
       m01.push_back(mat(0, 1));
       m02.push_back(mat(0, 2));
       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++) {
   for (int i = 0; i < length; i++) {
     LMatrix3f mat;
     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) {
     if (_transpose_quats) {
       mat.transpose_in_place();
       mat.transpose_in_place();
     }
     }
@@ -418,31 +420,16 @@ write_hprs(Datagram &datagram, const LVecBase3f *array, int length) {
       rot.extract_to_matrix(mat2);
       rot.extract_to_matrix(mat2);
       if (!mat.almost_equal(mat2, 0.0001)) {
       if (!mat.almost_equal(mat2, 0.0001)) {
         LVecBase3f hpr1, hpr2;
         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()
         mathutil_cat.warning()
           << "Converted hpr to quaternion incorrectly!\n"
           << "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)
         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
 #endif
@@ -628,16 +615,9 @@ read_hprs(DatagramIterator &di, vector_LVecBase3f &array) {
         LMatrix3f mat(m00[i], m01[i], m02[i],
         LMatrix3f mat(m00[i], m01[i], m02[i],
                       m10[i], m11[i], m12[i],
                       m10[i], m11[i], m12[i],
                       m20[i], m21[i], m22[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) {
       if (_transpose_quats) {
         mat.transpose_in_place();
         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);
       array.push_back(hpr);
     }
     }
   }
   }

+ 5 - 5
panda/src/mathutil/fftCompressor.h

@@ -19,12 +19,12 @@
 #ifndef FFTCOMPRESSOR_H
 #ifndef FFTCOMPRESSOR_H
 #define FFTCOMPRESSOR_H
 #define FFTCOMPRESSOR_H
 
 
-#include <pandabase.h>
+#include "pandabase.h"
 
 
-#include <pointerToArray.h>
-#include <vector_float.h>
-#include <vector_double.h>
-#include <vector_LVecBase3f.h>
+#include "pointerToArray.h"
+#include "vector_float.h"
+#include "vector_double.h"
+#include "vector_LVecBase3f.h"
 
 
 class Datagram;
 class Datagram;
 class DatagramIterator;
 class DatagramIterator;

+ 6 - 4
panda/src/parametrics/parametricCurveCollection.cxx

@@ -568,7 +568,10 @@ evaluate(float t, LMatrix4f &result, CoordinateSystem cs) const {
     return false;
     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;
   return true;
 }
 }
 
 
@@ -935,9 +938,8 @@ determine_hpr(float t, ParametricCurve *xyz_curve, LVecBase3f &hpr) const {
   LMatrix3f mat;
   LMatrix3f mat;
   look_at(mat, tangent);
   look_at(mat, tangent);
 
 
-  LVecBase3f scale;
-  decompose_matrix(mat, scale, hpr);
-  return true;
+  LVecBase3f scale, shear;
+  return decompose_matrix(mat, scale, shear, hpr);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 0 - 6
panda/src/pgraph/config_pgraph.cxx

@@ -110,12 +110,6 @@ const bool paranoid_compose = config_pgraph.GetBool("paranoid-compose", false);
 // by matrix.
 // by matrix.
 const bool compose_componentwise = config_pgraph.GetBool("compose-componentwise", true);
 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
 // Set this false to disable TransparencyAttrib::M_dual altogether
 // (and use M_alpha in its place).
 // (and use M_alpha in its place).
 const bool m_dual = config_pgraph.GetBool("m-dual", true);
 const bool m_dual = config_pgraph.GetBool("m-dual", true);

+ 0 - 1
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 unambiguous_graph;
 extern const bool paranoid_compose;
 extern const bool paranoid_compose;
 extern const bool compose_componentwise;
 extern const bool compose_componentwise;
-extern const bool bams_componentwise;
 
 
 extern const bool m_dual;
 extern const bool m_dual;
 extern const bool m_dual_opaque;
 extern const bool m_dual_opaque;

+ 58 - 0
panda/src/pgraph/nodePath.I

@@ -522,6 +522,32 @@ get_sz() const {
   return get_scale()[2];
   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
 //     Function: NodePath::set_pos_hpr
 //       Access: Published
 //       Access: Published
@@ -705,6 +731,38 @@ get_sz(const NodePath &other) const {
   return get_scale(other)[2];
   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
 //     Function: NodePath::set_pos_hpr
 //       Access: Published
 //       Access: Published

+ 214 - 56
panda/src/pgraph/nodePath.cxx

@@ -39,7 +39,6 @@
 #include "transparencyAttrib.h"
 #include "transparencyAttrib.h"
 #include "materialPool.h"
 #include "materialPool.h"
 #include "look_at.h"
 #include "look_at.h"
-#include "compose_matrix.h"
 #include "plist.h"
 #include "plist.h"
 #include "boundingSphere.h"
 #include "boundingSphere.h"
 #include "geomNode.h"
 #include "geomNode.h"
@@ -692,19 +691,6 @@ get_hpr() const {
   return transform->get_hpr();
   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
 //     Function: NodePath::set_quat
 //       Access: Published
 //       Access: Published
@@ -782,6 +768,58 @@ get_scale() const {
   return transform->get_scale();
   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
 //     Function: NodePath::set_pos_hpr
 //       Access: Published
 //       Access: Published
@@ -792,8 +830,8 @@ void NodePath::
 set_pos_hpr(const LVecBase3f &pos, const LVecBase3f &hpr) {
 set_pos_hpr(const LVecBase3f &pos, const LVecBase3f &hpr) {
   nassertv_always(!is_empty());
   nassertv_always(!is_empty());
   CPT(TransformState) transform = get_transform();
   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);
   set_transform(transform);
 }
 }
 
 
@@ -807,16 +845,16 @@ void NodePath::
 set_hpr_scale(const LVecBase3f &hpr, const LVecBase3f &scale) {
 set_hpr_scale(const LVecBase3f &hpr, const LVecBase3f &scale) {
   nassertv_always(!is_empty());
   nassertv_always(!is_empty());
   CPT(TransformState) transform = get_transform();
   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);
   set_transform(transform);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: NodePath::set_pos_hpr_scale
 //     Function: NodePath::set_pos_hpr_scale
 //       Access: Published
 //       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::
 void NodePath::
 set_pos_hpr_scale(const LVecBase3f &pos, const LVecBase3f &hpr,
 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
 //     Function: NodePath::set_pos_quat_scale
 //       Access: Published
 //       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::
 void NodePath::
 set_pos_quat_scale(const LVecBase3f &pos, const LQuaternionf &quat,
 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));
                 (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
 //     Function: NodePath::set_mat
 //       Access: Published
 //       Access: Published
@@ -900,14 +966,15 @@ set_pos(const NodePath &other, const LVecBase3f &pos) {
   CPT(TransformState) orig_transform = get_transform();
   CPT(TransformState) orig_transform = get_transform();
   if (orig_transform->has_components()) {
   if (orig_transform->has_components()) {
     // If we had a componentwise transform before we started, we
     // 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
     // wouldn't need to do this, except for the possibility of
     // numerical error or decompose ambiguity.
     // numerical error or decompose ambiguity.
     const LVecBase3f &orig_hpr = orig_transform->get_hpr();
     const LVecBase3f &orig_hpr = orig_transform->get_hpr();
     const LVecBase3f &orig_scale = orig_transform->get_scale();
     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_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 {
   } else {
     // If we didn't have a componentwise transform already, never
     // 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();
   CPT(TransformState) orig_transform = get_transform();
   if (orig_transform->has_components()) {
   if (orig_transform->has_components()) {
     // If we had a componentwise transform before we started, we
     // 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
     // wouldn't need to do this, except for the possibility of
     // numerical error or decompose ambiguity.
     // numerical error or decompose ambiguity.
     const LVecBase3f &orig_pos = orig_transform->get_pos();
     const LVecBase3f &orig_pos = orig_transform->get_pos();
     const LVecBase3f &orig_scale = orig_transform->get_scale();
     const LVecBase3f &orig_scale = orig_transform->get_scale();
+    const LVecBase3f &orig_shear = orig_transform->get_shear();
 
 
     set_transform(other, rel_transform->set_hpr(hpr));
     set_transform(other, rel_transform->set_hpr(hpr));
     const TransformState *new_transform = get_transform();
     const TransformState *new_transform = get_transform();
     if (new_transform->has_components()) {
     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 {
   } else {
@@ -1024,22 +1092,6 @@ get_hpr(const NodePath &other) const {
   return transform->get_hpr();
   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
 //     Function: NodePath::set_quat
 //       Access: Published
 //       Access: Published
@@ -1054,16 +1106,17 @@ set_quat(const NodePath &other, const LQuaternionf &quat) {
   CPT(TransformState) orig_transform = get_transform();
   CPT(TransformState) orig_transform = get_transform();
   if (orig_transform->has_components()) {
   if (orig_transform->has_components()) {
     // If we had a componentwise transform before we started, we
     // 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
     // wouldn't need to do this, except for the possibility of
     // numerical error or decompose ambiguity.
     // numerical error or decompose ambiguity.
     const LVecBase3f &orig_pos = orig_transform->get_pos();
     const LVecBase3f &orig_pos = orig_transform->get_pos();
     const LVecBase3f &orig_scale = orig_transform->get_scale();
     const LVecBase3f &orig_scale = orig_transform->get_scale();
+    const LVecBase3f &orig_shear = orig_transform->get_shear();
 
 
     set_transform(other, rel_transform->set_quat(quat));
     set_transform(other, rel_transform->set_quat(quat));
     const TransformState *new_transform = get_transform();
     const TransformState *new_transform = get_transform();
     if (new_transform->has_components()) {
     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 {
   } else {
@@ -1100,16 +1153,17 @@ set_scale(const NodePath &other, const LVecBase3f &scale) {
   CPT(TransformState) orig_transform = get_transform();
   CPT(TransformState) orig_transform = get_transform();
   if (orig_transform->has_components()) {
   if (orig_transform->has_components()) {
     // If we had a componentwise transform before we started, we
     // 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
     // wouldn't need to do this, except for the possibility of
     // numerical error or decompose ambiguity.
     // numerical error or decompose ambiguity.
     const LVecBase3f &orig_pos = orig_transform->get_pos();
     const LVecBase3f &orig_pos = orig_transform->get_pos();
     const LVecBase3f &orig_hpr = orig_transform->get_hpr();
     const LVecBase3f &orig_hpr = orig_transform->get_hpr();
+    const LVecBase3f &orig_shear = orig_transform->get_shear();
 
 
     set_transform(other, rel_transform->set_scale(scale));
     set_transform(other, rel_transform->set_scale(scale));
     const TransformState *new_transform = get_transform();
     const TransformState *new_transform = get_transform();
     if (new_transform->has_components()) {
     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 {
   } else {
@@ -1156,6 +1210,77 @@ get_scale(const NodePath &other) const {
   return transform->get_scale();
   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
 //     Function: NodePath::set_pos_hpr
 //       Access: Published
 //       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
     // wouldn't need to do this, except for the possibility of
     // numerical error or decompose ambiguity.
     // numerical error or decompose ambiguity.
     const LVecBase3f &orig_scale = orig_transform->get_scale();
     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();
     const TransformState *new_transform = get_transform();
     if (new_transform->has_components()) {
     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 {
   } else {
     // If we didn't have a componentwise transform already, never
     // If we didn't have a componentwise transform already, never
     // mind.
     // 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.
   // few thousandths.
   nassertv_always(!is_empty());
   nassertv_always(!is_empty());
   CPT(TransformState) transform = get_transform(other);
   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);
   set_transform(other, transform);
 }
 }
 
 
@@ -1218,7 +1344,7 @@ set_hpr_scale(const NodePath &other, const LVecBase3f &hpr, const LVecBase3f &sc
 //       Access: Published
 //       Access: Published
 //  Description: Completely replaces the transform with new
 //  Description: Completely replaces the transform with new
 //               translation, rotation, and scale components, relative
 //               translation, rotation, and scale components, relative
-//               to the other node.
+//               to the other node, implicitly setting shear to 0.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void NodePath::
 void NodePath::
 set_pos_hpr_scale(const NodePath &other,
 set_pos_hpr_scale(const NodePath &other,
@@ -1234,7 +1360,7 @@ set_pos_hpr_scale(const NodePath &other,
 //       Access: Published
 //       Access: Published
 //  Description: Completely replaces the transform with new
 //  Description: Completely replaces the transform with new
 //               translation, rotation, and scale components, relative
 //               translation, rotation, and scale components, relative
-//               to the other node.
+//               to the other node, implicitly setting shear to 0.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void NodePath::
 void NodePath::
 set_pos_quat_scale(const NodePath &other,
 set_pos_quat_scale(const NodePath &other,
@@ -1245,6 +1371,38 @@ set_pos_quat_scale(const NodePath &other,
                 (pos, quat, scale));
                 (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
 //     Function: NodePath::get_mat
 //       Access: Published
 //       Access: Published

+ 38 - 2
panda/src/pgraph/nodePath.h

@@ -250,7 +250,6 @@ PUBLISHED:
   void set_p(float p);
   void set_p(float p);
   void set_r(float r);
   void set_r(float r);
   LVecBase3f get_hpr() const;
   LVecBase3f get_hpr() const;
-  LVecBase3f get_hpr(float roll) const;
   INLINE float get_h() const;
   INLINE float get_h() const;
   INLINE float get_p() const;
   INLINE float get_p() const;
   INLINE float get_r() const;
   INLINE float get_r() const;
@@ -269,6 +268,16 @@ PUBLISHED:
   INLINE float get_sy() const;
   INLINE float get_sy() const;
   INLINE float get_sz() 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,
   INLINE void set_pos_hpr(float x, float y, float z,
                           float h, float p, float r);
                           float h, float p, float r);
   void set_pos_hpr(const LVecBase3f &pos,
   void set_pos_hpr(const LVecBase3f &pos,
@@ -287,6 +296,14 @@ PUBLISHED:
   void set_pos_quat_scale(const LVecBase3f &pos,
   void set_pos_quat_scale(const LVecBase3f &pos,
                           const LQuaternionf &quat,
                           const LQuaternionf &quat,
                           const LVecBase3f &scale);
                           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);
   void set_mat(const LMatrix4f &mat);
   INLINE void clear_mat();
   INLINE void clear_mat();
@@ -317,7 +334,6 @@ PUBLISHED:
   void set_p(const NodePath &other, float p);
   void set_p(const NodePath &other, float p);
   void set_r(const NodePath &other, float r);
   void set_r(const NodePath &other, float r);
   LVecBase3f get_hpr(const NodePath &other) const;
   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_h(const NodePath &other) const;
   INLINE float get_p(const NodePath &other) const;
   INLINE float get_p(const NodePath &other) const;
   INLINE float get_r(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_sy(const NodePath &other) const;
   INLINE float get_sz(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,
   INLINE void set_pos_hpr(const NodePath &other,
                           float x, float y, float z,
                           float x, float y, float z,
                           float h, float p, float r);
                           float h, float p, float r);
@@ -359,6 +385,16 @@ PUBLISHED:
                           const LVecBase3f &pos,
                           const LVecBase3f &pos,
                           const LQuaternionf &quat,
                           const LQuaternionf &quat,
                           const LVecBase3f &scale);
                           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;
   const LMatrix4f &get_mat(const NodePath &other) const;
   void set_mat(const NodePath &other, const LMatrix4f &mat);
   void set_mat(const NodePath &other, const LMatrix4f &mat);

+ 82 - 1
panda/src/pgraph/transformState.I

@@ -114,6 +114,44 @@ make_scale(const LVecBase3f &scale) {
                             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
 //     Function: TransformState::is_identity
 //       Access: Published
 //       Access: Published
@@ -284,6 +322,31 @@ has_uniform_scale() const {
   return (_flags & F_uniform_scale) != 0;
   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
 //     Function: TransformState::has_mat
 //       Access: Published
 //       Access: Published
@@ -368,6 +431,20 @@ get_uniform_scale() const {
   return _scale[0];
   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
 //     Function: TransformState::get_mat
 //       Access: Published
 //       Access: Published
@@ -458,7 +535,8 @@ check_mat() const {
 //       Access: Private
 //       Access: Private
 //  Description: Should be called immediately after _scale (and
 //  Description: Should be called immediately after _scale (and
 //               F_has_components) is set, this checks for a uniform
 //               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::
 INLINE void TransformState::
 check_uniform_scale() {
 check_uniform_scale() {
@@ -466,6 +544,9 @@ check_uniform_scale() {
       IS_NEARLY_EQUAL(_scale[0], _scale[2])) {
       IS_NEARLY_EQUAL(_scale[0], _scale[2])) {
     _flags |= F_uniform_scale;
     _flags |= F_uniform_scale;
   }
   }
+  if (!_shear.almost_equal(LVecBase3f::zero())) {
+    _flags |= F_has_nonzero_shear;
+  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 60 - 27
panda/src/pgraph/transformState.cxx

@@ -244,6 +244,11 @@ operator < (const TransformState &other) const {
     }
     }
 
 
     c = _scale.compare_to(other._scale);
     c = _scale.compare_to(other._scale);
+    if (c != 0) {
+      return c < 0;
+    }
+
+    c = _shear.compare_to(other._shear);
     return c < 0;
     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
 //       Access: Published, Static
 //  Description: Makes a new TransformState with the specified
 //  Description: Makes a new TransformState with the specified
 //               components.
 //               components.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 CPT(TransformState) TransformState::
 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.
   // Make a special-case check for the identity transform.
   if (pos == LVecBase3f(0.0f, 0.0f, 0.0f) &&
   if (pos == LVecBase3f(0.0f, 0.0f, 0.0f) &&
       hpr == 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();
     return make_identity();
   }
   }
 
 
@@ -313,24 +319,26 @@ make_pos_hpr_scale(const LVecBase3f &pos, const LVecBase3f &hpr,
   state->_pos = pos;
   state->_pos = pos;
   state->_hpr = hpr;
   state->_hpr = hpr;
   state->_scale = scale;
   state->_scale = scale;
+  state->_shear = shear;
   state->_flags = F_components_given | F_hpr_given | F_components_known | F_hpr_known | F_has_components;
   state->_flags = F_components_given | F_hpr_given | F_components_known | F_hpr_known | F_has_components;
   state->check_uniform_scale();
   state->check_uniform_scale();
   return return_new(state);
   return return_new(state);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: TransformState::make_pos_quat_scale
+//     Function: TransformState::make_pos_quat_scale_shear
 //       Access: Published, Static
 //       Access: Published, Static
 //  Description: Makes a new TransformState with the specified
 //  Description: Makes a new TransformState with the specified
 //               components.
 //               components.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 CPT(TransformState) TransformState::
 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.
   // Make a special-case check for the identity transform.
   if (pos == LVecBase3f(0.0f, 0.0f, 0.0f) &&
   if (pos == LVecBase3f(0.0f, 0.0f, 0.0f) &&
       quat == LQuaternionf::ident_quat() &&
       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();
     return make_identity();
   }
   }
 
 
@@ -338,6 +346,7 @@ make_pos_quat_scale(const LVecBase3f &pos, const LQuaternionf &quat,
   state->_pos = pos;
   state->_pos = pos;
   state->_quat = quat;
   state->_quat = quat;
   state->_scale = scale;
   state->_scale = scale;
+  state->_shear = shear;
   state->_flags = F_components_given | F_quat_given | F_components_known | F_quat_known | F_has_components;
   state->_flags = F_components_given | F_quat_given | F_components_known | F_quat_known | F_has_components;
   state->check_uniform_scale();
   state->check_uniform_scale();
   return return_new(state);
   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
     // If we started with a componentwise transform, we keep it that
     // way.
     // way.
     if (quat_given()) {
     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 {
     } 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 {
   } else {
@@ -400,7 +409,7 @@ CPT(TransformState) TransformState::
 set_hpr(const LVecBase3f &hpr) const {
 set_hpr(const LVecBase3f &hpr) const {
   nassertr(!is_invalid(), this);
   nassertr(!is_invalid(), this);
   //  nassertr(has_components(), 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 {
 set_quat(const LQuaternionf &quat) const {
   nassertr(!is_invalid(), this);
   nassertr(!is_invalid(), this);
   //  nassertr(has_components(), 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(!is_invalid(), this);
   //  nassertr(has_components(), this);
   //  nassertr(has_components(), this);
   if (quat_given()) {
   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 {
   } 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";
       out << "m";
 
 
     } else if (output_hpr && quat_given()) {
     } 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";
       out << "q";
     }
     }
 
 
@@ -636,6 +663,10 @@ output(ostream &out) const {
         lead = ' ';
         lead = ' ';
       }
       }
     }
     }
+    if (has_nonzero_shear()) {
+      out << lead << "shear " << get_shear();
+      lead = ' ';
+    }
     if (lead == '(') {
     if (lead == '(') {
       out << "(almost identity)";
       out << "(almost identity)";
     } else {
     } else {
@@ -879,6 +910,7 @@ do_compose(const TransformState *other) const {
 
 
   if (compose_componentwise && 
   if (compose_componentwise && 
       has_uniform_scale() && 
       has_uniform_scale() && 
+      !has_nonzero_shear() && !other->has_nonzero_shear() &&
       ((components_given() && other->has_components()) ||
       ((components_given() && other->has_components()) ||
        (other->components_given() && has_components()))) {
        (other->components_given() && has_components()))) {
     // We will do this operation componentwise if *either* transform
     // We will do this operation componentwise if *either* transform
@@ -932,6 +964,7 @@ do_invert_compose(const TransformState *other) const {
 
 
   if (compose_componentwise && 
   if (compose_componentwise && 
       has_uniform_scale() && 
       has_uniform_scale() && 
+      !has_nonzero_shear() && !other->has_nonzero_shear() &&
       ((components_given() && other->has_components()) ||
       ((components_given() && other->has_components()) ||
        (other->components_given() && has_components()))) {
        (other->components_given() && has_components()))) {
     // We will do this operation componentwise if *either* transform
     // We will do this operation componentwise if *either* transform
@@ -1040,6 +1073,7 @@ calc_components() {
   nassertv((_flags & F_is_invalid) == 0);
   nassertv((_flags & F_is_invalid) == 0);
   if ((_flags & F_is_identity) != 0) {
   if ((_flags & F_is_identity) != 0) {
     _scale.set(1.0f, 1.0f, 1.0f);
     _scale.set(1.0f, 1.0f, 1.0f);
+    _shear.set(0.0f, 0.0f, 0.0f);
     _hpr.set(0.0f, 0.0f, 0.0f);
     _hpr.set(0.0f, 0.0f, 0.0f);
     _quat = LQuaternionf::ident_quat();
     _quat = LQuaternionf::ident_quat();
     _pos.set(0.0f, 0.0f, 0.0f);
     _pos.set(0.0f, 0.0f, 0.0f);
@@ -1051,7 +1085,7 @@ calc_components() {
     nassertv((_flags & F_mat_known) != 0);
     nassertv((_flags & F_mat_known) != 0);
 
 
     const LMatrix4f &mat = get_mat();
     const LMatrix4f &mat = get_mat();
-    bool possible = decompose_matrix(mat, _scale, _hpr, _pos);
+    bool possible = decompose_matrix(mat, _scale, _shear, _hpr, _pos);
     if (!possible) {
     if (!possible) {
       // Some matrices can't be decomposed into scale, hpr, pos.  In
       // Some matrices can't be decomposed into scale, hpr, pos.  In
       // this case, we now know that we cannot compute the components;
       // 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
     // If we don't have a matrix and we're not identity, the only
     // other explanation is that we were constructed via components.
     // other explanation is that we were constructed via components.
     nassertv((_flags & F_components_known) != 0);
     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;
   _flags |= F_mat_known;
 }
 }
@@ -1175,6 +1209,7 @@ write_datagram(BamWriter *manager, Datagram &dg) {
       get_hpr().write_datagram(dg);
       get_hpr().write_datagram(dg);
     }
     }
     _scale.write_datagram(dg);
     _scale.write_datagram(dg);
+    _shear.write_datagram(dg);
 
 
   } else {
   } else {
     // A general matrix.
     // A general matrix.
@@ -1283,19 +1318,17 @@ fillin(DatagramIterator &scan, BamReader *manager) {
       _flags |= (F_hpr_given | F_hpr_known);
       _flags |= (F_hpr_given | F_hpr_known);
     }
     }
     _scale.read_datagram(scan);
     _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();
     check_uniform_scale();
   }
   }
 
 
   if ((_flags & F_mat_known) != 0) {
   if ((_flags & F_mat_known) != 0) {
     // General matrix.
     // General matrix.
     _mat.read_datagram(scan);
     _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;
-      }
-    }
   }
   }
 }
 }
 
 

+ 35 - 21
panda/src/pgraph/transformState.h

@@ -76,12 +76,21 @@ PUBLISHED:
                                                  const LVecBase3f &hpr);
                                                  const LVecBase3f &hpr);
   INLINE static CPT(TransformState) make_scale(float scale);
   INLINE static CPT(TransformState) make_scale(float scale);
   INLINE static CPT(TransformState) make_scale(const LVecBase3f &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);
   static CPT(TransformState) make_mat(const LMatrix4f &mat);
 
 
   INLINE bool is_identity() const;
   INLINE bool is_identity() const;
@@ -96,18 +105,22 @@ PUBLISHED:
   INLINE bool has_quat() const;
   INLINE bool has_quat() const;
   INLINE bool has_scale() const;
   INLINE bool has_scale() const;
   INLINE bool has_uniform_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 bool has_mat() const;
   INLINE const LVecBase3f &get_pos() const;
   INLINE const LVecBase3f &get_pos() const;
   INLINE const LVecBase3f &get_hpr() const;
   INLINE const LVecBase3f &get_hpr() const;
   INLINE const LQuaternionf &get_quat() const;
   INLINE const LQuaternionf &get_quat() const;
   INLINE const LVecBase3f &get_scale() const;
   INLINE const LVecBase3f &get_scale() const;
   INLINE float get_uniform_scale() const;
   INLINE float get_uniform_scale() const;
+  INLINE const LVecBase3f &get_shear() const;
   INLINE const LMatrix4f &get_mat() const;
   INLINE const LMatrix4f &get_mat() const;
 
 
   CPT(TransformState) set_pos(const LVecBase3f &pos) const;
   CPT(TransformState) set_pos(const LVecBase3f &pos) const;
   CPT(TransformState) set_hpr(const LVecBase3f &hpr) const;
   CPT(TransformState) set_hpr(const LVecBase3f &hpr) const;
   CPT(TransformState) set_quat(const LQuaternionf &quat) const;
   CPT(TransformState) set_quat(const LQuaternionf &quat) const;
   CPT(TransformState) set_scale(const LVecBase3f &scale) 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) compose(const TransformState *other) const;
   CPT(TransformState) invert_compose(const TransformState *other) const;
   CPT(TransformState) invert_compose(const TransformState *other) const;
@@ -175,22 +188,23 @@ private:
   INLINE bool is_destructing() const;
   INLINE bool is_destructing() const;
 
 
   enum Flags {
   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;
   LQuaternionf _quat;
   LMatrix4f _mat;
   LMatrix4f _mat;
   LMatrix4f *_inv_mat;
   LMatrix4f *_inv_mat;

+ 3 - 2
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 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.
 // 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 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 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 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 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
 #endif

+ 0 - 1
panda/src/shader/planarReflector.cxx

@@ -26,7 +26,6 @@
 #include <renderBuffer.h>
 #include <renderBuffer.h>
 #include <perspectiveProjection.h>
 #include <perspectiveProjection.h>
 #include <look_at.h>
 #include <look_at.h>
-#include <compose_matrix.h>
 #include <get_rel_pos.h>
 #include <get_rel_pos.h>
 #include <lightTransition.h>
 #include <lightTransition.h>
 #include <depthTestTransition.h>
 #include <depthTestTransition.h>

+ 0 - 1
panda/src/shader/spheretexReflector.cxx

@@ -27,7 +27,6 @@
 #include <renderBuffer.h>
 #include <renderBuffer.h>
 #include <perspectiveLens.h>
 #include <perspectiveLens.h>
 #include <look_at.h>
 #include <look_at.h>
-#include <compose_matrix.h>
 #include <cullFaceTransition.h>
 #include <cullFaceTransition.h>
 #include <colorBlendTransition.h>
 #include <colorBlendTransition.h>
 #include <transformTransition.h>
 #include <transformTransition.h>

+ 3 - 2
panda/src/text/textNode.cxx

@@ -233,11 +233,12 @@ write(ostream &out, int indent_level) const {
     << "draw order is " << _draw_order << ", "
     << "draw order is " << _draw_order << ", "
     << _draw_order + 1 << ", " << _draw_order + 2 << "\n";
     << _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)
   indent(out, indent_level + 2)
     << "transform is:\n"
     << "transform is:\n"
     << "  scale: " << scale << "\n"
     << "  scale: " << scale << "\n"
+    << "  shear: " << shear << "\n"
     << "    hpr: " << hpr << "\n"
     << "    hpr: " << hpr << "\n"
     << "  trans: " << hpr << "\n";
     << "  trans: " << hpr << "\n";
   } else {
   } else {

+ 6 - 3
panda/src/tform/driveInterface.cxx

@@ -190,8 +190,8 @@ set_force_roll(float) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void DriveInterface::
 void DriveInterface::
 set_mat(const LMatrix4f &mat) {
 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::
 const LMatrix4f &DriveInterface::
 get_mat() {
 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;
   return _mat;
 }
 }
 
 

+ 23 - 23
panda/src/tform/trackball.cxx

@@ -180,29 +180,29 @@ set_z(float z) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 LVecBase3f Trackball::
 LVecBase3f Trackball::
 get_hpr() const {
 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;
   return hpr;
 }
 }
 
 
 float Trackball::
 float Trackball::
 get_h() const {
 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];
   return hpr[0];
 }
 }
 
 
 float Trackball::
 float Trackball::
 get_p() const {
 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];
   return hpr[1];
 }
 }
 
 
 float Trackball::
 float Trackball::
 get_r() const {
 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];
   return hpr[2];
 }
 }
 
 
@@ -214,45 +214,45 @@ get_r() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void Trackball::
 void Trackball::
 set_hpr(const LVecBase3f &hpr) {
 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();
   recompute();
 }
 }
 
 
 void Trackball::
 void Trackball::
 set_hpr(float h, float p, float r) {
 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);
   hpr.set(h, p, r);
-  compose_matrix(_rotation, scale, hpr, translate);
+  compose_matrix(_rotation, scale, shear, hpr, translate);
   recompute();
   recompute();
 }
 }
 
 
 void Trackball::
 void Trackball::
 set_h(float h) {
 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;
   hpr[0] = h;
-  compose_matrix(_rotation, scale, hpr, translate);
+  compose_matrix(_rotation, scale, shear, hpr, translate);
   recompute();
   recompute();
 }
 }
 
 
 void Trackball::
 void Trackball::
 set_p(float p) {
 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;
   hpr[1] = p;
-  compose_matrix(_rotation, scale, hpr, translate);
+  compose_matrix(_rotation, scale, shear, hpr, translate);
   recompute();
   recompute();
 }
 }
 
 
 void Trackball::
 void Trackball::
 set_r(float r) {
 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;
   hpr[2] = r;
-  compose_matrix(_rotation, scale, hpr, translate);
+  compose_matrix(_rotation, scale, shear, hpr, translate);
   recompute();
   recompute();
 }
 }
 
 

+ 5 - 5
pandatool/src/egg-optchar/eggOptchar.cxx

@@ -90,9 +90,9 @@ EggOptchar() {
      &EggOptchar::dispatch_vector_string_comma, NULL, &_expose_components);
      &EggOptchar::dispatch_vector_string_comma, NULL, &_expose_components);
 
 
   add_option
   add_option
-    ("zero", "joint[,hprxyzijk]", 0,
+    ("zero", "joint[,hprxyzijkabc]", 0,
      "Zeroes out the animation channels for the named joint.  If "
      "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 "
      "operation is restricted to just those components; otherwise the "
      "entire transform is cleared.",
      "entire transform is cleared.",
      &EggOptchar::dispatch_name_components, NULL, &_zero_channels);
      &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()) {
   if (sp._b.empty()) {
-    sp._b = matrix_components;
+    sp._b = matrix_component_letters;
   } else {
   } else {
     for (string::const_iterator si = sp._b.begin(); si != sp._b.end(); ++si) {
     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"
         nout << "Not a standard matrix component: \"" << *si << "\"\n"
              << "-" << opt << " requires a joint name followed by a set "
              << "-" << opt << " requires a joint name followed by a set "
              << "of component names.  The standard component names are \"" 
              << "of component names.  The standard component names are \"" 
-             << matrix_components << "\".\n";
+             << matrix_component_letters << "\".\n";
         return false;
         return false;
       }
       }
     }
     }

+ 5 - 1
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;
   InvalidSet::const_iterator si;
   for (si = invalid_set.begin(); si != invalid_set.end(); ++si) {
   for (si = invalid_set.begin(); si != invalid_set.end(); ++si) {
     EggJointData *joint_data = (*si);
     EggJointData *joint_data = (*si);
@@ -225,7 +229,7 @@ do_reparent() {
       } else {
       } else {
         nout << joint_data->get_parent()->get_name();
         nout << joint_data->get_parent()->get_name();
       }
       }
-      nout << " results in a skew transform.\n";
+      nout << " results in an invalid transform.\n";
     }
     }
   }
   }
 
 

+ 4 - 2
pandatool/src/eggcharbase/eggMatrixTablePointer.cxx

@@ -198,16 +198,18 @@ do_rebuild() {
     return false;
     return false;
   }
   }
 
 
+  bool all_ok = true;
+  
   _xform->clear_data();
   _xform->clear_data();
   RebuildFrames::const_iterator fi;
   RebuildFrames::const_iterator fi;
   for (fi = _rebuild_frames.begin(); fi != _rebuild_frames.end(); ++fi) {
   for (fi = _rebuild_frames.begin(); fi != _rebuild_frames.end(); ++fi) {
     if (!_xform->add_data(*fi)) {
     if (!_xform->add_data(*fi)) {
-      return false;
+      all_ok = false;
     }
     }
   }
   }
 
 
   _rebuild_frames.clear();
   _rebuild_frames.clear();
-  return true;
+  return all_ok;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 1 - 1
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);
         EggXfmSAnim *anim = _tree.get_egg_anim(node_desc);
         if (!anim->add_data(tgroup->get_transform())) {
         if (!anim->add_data(tgroup->get_transform())) {
           mayaegg_cat.error()
           mayaegg_cat.error()
-            << "Shear transform on " << node_desc->get_name()
+            << "Invalid transform on " << node_desc->get_name()
             << " frame " << frame.value() << ".\n";
             << " frame " << frame.value() << ".\n";
         }
         }
       }
       }