Browse Source

*** empty log message ***

David Rose 25 years ago
parent
commit
ba2608b7b4

+ 3 - 3
panda/src/chan/animChannelMatrixXfmTable.cxx

@@ -263,9 +263,9 @@ write_datagram(BamWriter *manager, Datagram &me)
       max(max(_tables[3].size(), _tables[4].size()), _tables[5].size());
     hprs.reserve(hprs_length);
     for (i = 0; i < hprs_length; i++) {
-      float h = (i < (int)_tables[3].size()) ? _tables[3][i] : 0.0f;
-      float p = (i < (int)_tables[4].size()) ? _tables[4][i] : 0.0f;
-      float r = (i < (int)_tables[5].size()) ? _tables[5][i] : 0.0f;
+      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()];
       hprs.push_back(LVecBase3f(h, p, r));
     }
     compressor.write_hprs(me, &hprs[0], hprs_length);

+ 96 - 36
panda/src/mathutil/fftCompressor.cxx

@@ -65,10 +65,15 @@ is_compression_available() {
 //               how aggressively the reals are compressed; lower
 //               numbers mean smaller output, and more data loss.
 //
-//               As a special case, a negative quality indicates that
-//               the individual parameters should be separately
-//               controlled via config variables, and a quality
-//               greater than 100 indicates lossless output.
+//               There are a few special cases.  Quality -1 means to
+//               use whatever individual parameters are set in the
+//               user's Configrc file, rather than the single quality
+//               dial.  Quality 101 or higher means to generate
+//               lossless output (this is the default if libfftw is
+//               not available).  Quality 102 writes all four
+//               components of quaternions to the output file, rather
+//               than just three, and quality 103 doesn't even convert
+//               hpr to quat.
 ////////////////////////////////////////////////////////////////////
 void FFTCompressor::
 set_quality(int quality) {
@@ -84,11 +89,12 @@ set_quality(int quality) {
   _quality = quality;
 
   if (_quality < 0) {
-    // A negative quality indicates to read the important parameters
-    // from config variables.
+    // A negative quality indicates we should read the various
+    // parameters from individual config variables.
     _fft_offset = fft_offset;
     _fft_factor = fft_factor;
     _fft_exponent = fft_exponent;
+
   } else if (_quality < 40) {
     // 0 - 40 : 
     //   fft-offset 1.0 - 0.001
@@ -191,29 +197,17 @@ write_reals(Datagram &datagram, const float *array, int length) {
   }
     
   // Normal case: FFT the array, and write that out.
-  double data[length];
+  double *data = (double *)alloca(length * sizeof(double));
   int i;
   for (i = 0; i < length; i++) {
     data[i] = array[i];
   }
 
-  double half_complex[length];
+  double *half_complex = (double *)alloca(length * sizeof(double));
 
   rfftw_plan plan = get_real_compress_plan(length);
   rfftw_one(plan, data, half_complex);
 
-  if (mathutil_cat.is_debug()) {
-    mathutil_cat.debug()
-      << "write_reals :";
-    for (int i = 0; i < length; i++) {
-      double scale_factor = get_scale_factor(i, length);
-      mathutil_cat.debug(false) 
-	//	<< " " << data[i];
-	<< " " << floor(half_complex[i] / scale_factor + 0.5);
-    }
-    mathutil_cat.debug(false) << "\n";
-  }
-
   // Now encode the numbers, run-length encoded by size, so we only
   // write out the number of bits we need for each number.
 
@@ -281,6 +275,22 @@ write_reals(Datagram &datagram, const float *array, int length) {
 ////////////////////////////////////////////////////////////////////
 void FFTCompressor::
 write_hprs(Datagram &datagram, const LVecBase3f *array, int length) {
+  if (_quality >= 103) {
+    // If quality level is at least 103, we don't even convert hpr to
+    // quat.
+    vector_float h, p, r;
+    for (int i = 0; i < length; i++) {
+      h.push_back(array[i][0]);
+      p.push_back(array[i][1]);
+      r.push_back(array[i][2]);
+    }
+
+    write_reals(datagram, &h[0], length);
+    write_reals(datagram, &p[0], length);
+    write_reals(datagram, &r[0], length);
+    return;
+  }
+
   // First, convert the HPR's to quats.  We expect quats to have
   // better FFT consistency, and therefore compress better, even
   // though they have an extra component.
@@ -289,11 +299,12 @@ write_hprs(Datagram &datagram, const LVecBase3f *array, int length) {
   // have to write out all three components; any three can be used to
   // determine the fourth (provided we ensure consistency of sign).
 
-  vector_float qi, qj, qk;
+  vector_float qr, qi, qj, qk;
 
   for (int i = 0; i < length; i++) {
     LMatrix3f mat;
     compose_matrix(mat, LVecBase3f(1.0, 1.0, 1.0), array[i]);
+
     LOrientationf rot;
     rot.set(mat);
     rot.normalize();
@@ -312,11 +323,30 @@ write_hprs(Datagram &datagram, const LVecBase3f *array, int length) {
       rot.set(-rot.get_r(), -rot.get_i(), -rot.get_j(), -rot.get_k());
     }
 
+    /*
+    {
+      LMatrix3f mat2;
+      rot.extract_to_matrix(mat2);
+      LVecBase3f scale, hpr;
+      bool success = decompose_matrix(mat2, scale, hpr);
+      nassertv(success);
+      if (!array[i].almost_equal(hpr, 0.001)) {
+	cerr << "array " << array[i] << " hpr " << hpr << "\n";
+      }
+    }
+    */
+
+    qr.push_back(rot.get_r());
     qi.push_back(rot.get_i());
     qj.push_back(rot.get_j());
     qk.push_back(rot.get_k());
   }
 
+  // If quality is at least 102, we write all four quat components,
+  // instead of just the three.
+  if (_quality >= 102) {
+    write_reals(datagram, &qr[0], length);
+  }
   write_reals(datagram, &qi[0], length);
   write_reals(datagram, &qj[0], length);
   write_reals(datagram, &qk[0], length);
@@ -336,6 +366,11 @@ bool FFTCompressor::
 read_header(DatagramIterator &di) {
   _quality = di.get_int8();
 
+  if (mathutil_cat.is_debug()) {
+    mathutil_cat.debug()
+      << "Found compressed data at quality level " << _quality << "\n";
+  }
+
 #ifndef HAVE_FFTW
   if (_quality <= 100) {
     mathutil_cat.error()
@@ -410,7 +445,7 @@ read_reals(DatagramIterator &di, vector_float &array) {
     half_complex[i] *= get_scale_factor(i, length);
   }
 
-  double data[length];
+  double *data = (double *)alloca(length * sizeof(double));
   rfftw_plan plan = get_real_decompress_plan(length);
   rfftw_one(plan, &half_complex[0], data);
 
@@ -420,16 +455,6 @@ read_reals(DatagramIterator &di, vector_float &array) {
     array.push_back(data[i] * scale);
   }
 
-  if (mathutil_cat.is_debug()) {
-    mathutil_cat.debug()
-      << "read_reals :";
-    for (int i = 0; i < length; i++) {
-      mathutil_cat.debug(false)
-	<< " " << data[i] * scale;
-    }
-    mathutil_cat.debug(false) << "\n";
-  }
-
   return true;
 #endif
 }
@@ -444,11 +469,36 @@ read_reals(DatagramIterator &di, vector_float &array) {
 ////////////////////////////////////////////////////////////////////
 bool FFTCompressor::
 read_hprs(DatagramIterator &di, vector_LVecBase3f &array) {
-  vector_float qi, qj, qk;
+  if (_quality >= 103) {
+    // If quality level is at least 103, we don't even convert hpr to
+    // quat.
+    vector_float h, p, r;
+    bool okflag = true;
+    okflag = 
+      read_reals(di, h) &&
+      read_reals(di, p) &&
+      read_reals(di, r);
+
+    if (okflag) {
+      nassertr(h.size() == p.size() && p.size() == r.size(), false);
+      for (int i = 0; i < (int)h.size(); i++) {
+	array.push_back(LVecBase3f(h[i], p[i], r[i]));
+      }
+    }
+
+    return okflag;
+  }
+
+  vector_float qr, qi, qj, qk;
 
   bool okflag = true;
 
+  if (_quality >= 102) {
+    okflag = read_reals(di, qr);
+  }
+
   okflag = 
+    okflag &&
     read_reals(di, qi) &&
     read_reals(di, qj) &&
     read_reals(di, qk);
@@ -458,10 +508,20 @@ read_hprs(DatagramIterator &di, vector_LVecBase3f &array) {
     
     array.reserve(array.size() + qi.size());
     for (int i = 0; i < (int)qi.size(); i++) {
-      float qr2 = 1.0 - (qi[i] * qi[i] + qj[i] * qj[i] + qk[i] * qk[i]);
-      float qr = qr2 < 0.0 ? 0.0 : sqrtf(qr2);
+      LOrientationf rot;
+
+      if (_quality >= 102) {
+	// If we have written out all four components, use them.
+	rot.set(qr[i], qi[i], qj[i], qj[i]);
+
+      } else {
+	// Otherwise, infer the real component from the remaining
+	// three.
+	float qr2 = 1.0 - (qi[i] * qi[i] + qj[i] * qj[i] + qk[i] * qk[i]);
+	float qr1 = qr2 < 0.0 ? 0.0 : sqrtf(qr2);
+	rot.set(qr1, qi[i], qj[i], qk[i]); 
+      }
 
-      LOrientationf rot(qr, qi[i], qj[i], qk[i]);
       rot.normalize();      // Just for good measure.
 
       LMatrix3f mat;

+ 3 - 1
panda/src/putil/bam.h

@@ -19,7 +19,9 @@ static const unsigned short _bam_major_ver = 3;
 // Bumped to major version 2 on 7/6/00 due to major changes in Character.
 // Bumped to major version 3 on 12/8/00 to change float64's to float32's.
 
-static const unsigned short _bam_minor_ver = 0;
+static const unsigned short _bam_minor_ver = 1;
+// Bumped to minor version 1 on 12/15/00 to add FFT-style channel
+// compression.
 
 
 #endif