瀏覽代碼

fix numeric roundoff error in animation

David Rose 18 年之前
父節點
當前提交
93b66d6706

+ 4 - 2
panda/src/chan/animChannelBase.cxx

@@ -32,10 +32,12 @@ TypeHandle AnimChannelBase::_type_handle;
 //  Description: Returns true if the value has changed since the last
 //  Description: Returns true if the value has changed since the last
 //               call to has_changed().  last_frame is the frame
 //               call to has_changed().  last_frame is the frame
 //               number of the last call; this_frame is the current
 //               number of the last call; this_frame is the current
-//               frame number.
+//               frame number.  last_frac and this_frac are the
+//               fractional steps into those frames, which will be 0.0
+//               unless we are running in frame_blend mode.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool AnimChannelBase::
 bool AnimChannelBase::
-has_changed(double, double) {
+has_changed(int, double, int, double) {
   return true;
   return true;
 }
 }
 
 

+ 2 - 1
panda/src/chan/animChannelBase.h

@@ -46,7 +46,8 @@ protected:
 public:
 public:
   INLINE AnimChannelBase(AnimGroup *parent, const string &name);
   INLINE AnimChannelBase(AnimGroup *parent, const string &name);
 
 
-  virtual bool has_changed(double last_frame, double this_frame);
+  virtual bool has_changed(int last_frame, double last_frac, 
+                           int this_frame, double this_frac);
 
 
   virtual TypeHandle get_value_type() const=0;
   virtual TypeHandle get_value_type() const=0;
 
 

+ 1 - 1
panda/src/chan/animChannelFixed.I

@@ -55,7 +55,7 @@ AnimChannelFixed(const string &name, const ValueType &value)
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class SwitchType>
 template<class SwitchType>
 bool AnimChannelFixed<SwitchType>::
 bool AnimChannelFixed<SwitchType>::
-has_changed(double, double) {
+has_changed(int, double, int, double) {
   return false;
   return false;
 }
 }
 
 

+ 2 - 1
panda/src/chan/animChannelFixed.h

@@ -44,7 +44,8 @@ protected:
 public:
 public:
   INLINE AnimChannelFixed(const string &name, const ValueType &value);
   INLINE AnimChannelFixed(const string &name, const ValueType &value);
 
 
-  virtual bool has_changed(double last_frame, double this_frame);
+  virtual bool has_changed(int last_frame, double last_frac, 
+                           int this_frame, double this_frac);
   virtual void get_value(int frame, ValueType &value);
   virtual void get_value(int frame, ValueType &value);
 
 
   virtual void output(ostream &out) const;
   virtual void output(ostream &out) const;

+ 1 - 1
panda/src/chan/animChannelMatrixDynamic.cxx

@@ -78,7 +78,7 @@ AnimChannelMatrixDynamic(const string &name)
 //               frame number.
 //               frame number.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool AnimChannelMatrixDynamic::
 bool AnimChannelMatrixDynamic::
-has_changed(double, double) {
+has_changed(int, double, int, double) {
   if (_value_node != (PandaNode *)NULL) {
   if (_value_node != (PandaNode *)NULL) {
     _value = _value_node->get_transform();
     _value = _value_node->get_transform();
   }
   }

+ 2 - 1
panda/src/chan/animChannelMatrixDynamic.h

@@ -46,7 +46,8 @@ protected:
 public:
 public:
   AnimChannelMatrixDynamic(const string &name);
   AnimChannelMatrixDynamic(const string &name);
 
 
-  virtual bool has_changed(double last_frame, double this_frame);
+  virtual bool has_changed(int last_frame, double last_frac, 
+                           int this_frame, double this_frac);
   virtual void get_value(int frame, LMatrix4f &mat);
   virtual void get_value(int frame, LMatrix4f &mat);
 
 
   virtual void get_value_no_scale_shear(int frame, LMatrix4f &value);
   virtual void get_value_no_scale_shear(int frame, LMatrix4f &value);

+ 1 - 1
panda/src/chan/animChannelMatrixFixed.cxx

@@ -54,7 +54,7 @@ AnimChannelMatrixFixed(const string &name, const TransformState *transform) :
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool AnimChannelMatrixFixed::
 bool AnimChannelMatrixFixed::
-has_changed(double, double) {
+has_changed(int, double, int, double) {
   return false;
   return false;
 }
 }
 
 

+ 2 - 1
panda/src/chan/animChannelMatrixFixed.h

@@ -38,7 +38,8 @@ protected:
 public:
 public:
   AnimChannelMatrixFixed(const string &name, const TransformState *transform);
   AnimChannelMatrixFixed(const string &name, const TransformState *transform);
 
 
-  virtual bool has_changed(double last_frame, double this_frame);
+  virtual bool has_changed(int last_frame, double last_frac, 
+                           int this_frame, double this_frac);
   virtual void get_value(int frame, LMatrix4f &value);
   virtual void get_value(int frame, LMatrix4f &value);
   virtual void get_value_no_scale_shear(int frame, LMatrix4f &value);
   virtual void get_value_no_scale_shear(int frame, LMatrix4f &value);
   virtual void get_scale(int frame, LVecBase3f &scale);
   virtual void get_scale(int frame, LVecBase3f &scale);

+ 17 - 5
panda/src/chan/animChannelMatrixXfmTable.cxx

@@ -94,14 +94,26 @@ AnimChannelMatrixXfmTable::
 //               frame number.
 //               frame number.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool AnimChannelMatrixXfmTable::
 bool AnimChannelMatrixXfmTable::
-has_changed(double last_frame, double this_frame) {
+has_changed(int last_frame, double last_frac, 
+            int this_frame, double this_frac) {
   if (last_frame != this_frame) {
   if (last_frame != this_frame) {
-    int last_i_frame = (int)floor(last_frame);
-    int next_i_frame = (int)ceil(this_frame);
     for (int i = 0; i < num_matrix_components; i++) {
     for (int i = 0; i < num_matrix_components; i++) {
       if (_tables[i].size() > 1) {
       if (_tables[i].size() > 1) {
-        if (_tables[i][last_i_frame % _tables[i].size()] !=
-            _tables[i][next_i_frame % _tables[i].size()]) {
+        if (_tables[i][last_frame % _tables[i].size()] !=
+            _tables[i][this_frame % _tables[i].size()]) {
+          return true;
+        }
+      }
+    }
+  }
+
+  if (last_frac != this_frac) {
+    // If we have some fractional changes, also check the next
+    // subsequent frame (since we'll be blending with that).
+    for (int i = 0; i < num_matrix_components; i++) {
+      if (_tables[i].size() > 1) {
+        if (_tables[i][last_frame % _tables[i].size()] !=
+            _tables[i][(this_frame + 1) % _tables[i].size()]) {
           return true;
           return true;
         }
         }
       }
       }

+ 2 - 1
panda/src/chan/animChannelMatrixXfmTable.h

@@ -45,7 +45,8 @@ public:
   virtual ~AnimChannelMatrixXfmTable();
   virtual ~AnimChannelMatrixXfmTable();
   
   
 
 
-  virtual bool has_changed(double last_frame, double this_frame);
+  virtual bool has_changed(int last_frame, double last_frac, 
+                           int this_frame, double this_frac);
   virtual void get_value(int frame, LMatrix4f &mat);
   virtual void get_value(int frame, LMatrix4f &mat);
 
 
   virtual void get_value_no_scale_shear(int frame, LMatrix4f &value);
   virtual void get_value_no_scale_shear(int frame, LMatrix4f &value);

+ 1 - 1
panda/src/chan/animChannelScalarDynamic.cxx

@@ -80,7 +80,7 @@ AnimChannelScalarDynamic(const string &name)
 //               frame number.
 //               frame number.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool AnimChannelScalarDynamic::
 bool AnimChannelScalarDynamic::
-has_changed(double, double) {
+has_changed(int, double, int, double) {
   if (_value_node != (PandaNode *)NULL) {
   if (_value_node != (PandaNode *)NULL) {
     _value = _value_node->get_transform();
     _value = _value_node->get_transform();
     bool has_changed = (_value != _last_value);
     bool has_changed = (_value != _last_value);

+ 2 - 1
panda/src/chan/animChannelScalarDynamic.h

@@ -46,7 +46,8 @@ protected:
 public:
 public:
   AnimChannelScalarDynamic(const string &name);
   AnimChannelScalarDynamic(const string &name);
 
 
-  virtual bool has_changed(double last_frame, double this_frame);
+  virtual bool has_changed(int last_frame, double last_frac, 
+                           int this_frame, double this_frac);
   virtual void get_value(int frame, float &value);
   virtual void get_value(int frame, float &value);
 
 
 PUBLISHED:
 PUBLISHED:

+ 16 - 7
panda/src/chan/animChannelScalarTable.cxx

@@ -75,13 +75,22 @@ AnimChannelScalarTable(AnimGroup *parent, const string &name) :
 //               frame number.
 //               frame number.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool AnimChannelScalarTable::
 bool AnimChannelScalarTable::
-has_changed(double last_frame, double this_frame) {
-  if (last_frame != this_frame && _table.size() > 1) {
-    int last_i_frame = (int)floor(last_frame);
-    int next_i_frame = (int)ceil(this_frame);
-    if (_table[last_i_frame % _table.size()] !=
-        _table[next_i_frame % _table.size()]) {
-      return true;
+has_changed(int last_frame, double last_frac, 
+            int this_frame, double this_frac) {
+  if (_table.size() > 1) {
+    if (last_frame != this_frame) {
+      if (_table[last_frame % _table.size()] != 
+          _table[this_frame % _table.size()]) {
+        return true;
+      }
+    }
+    if (last_frac != this_frac) {
+      // If we have some fractional changes, also check the next
+      // subsequent frame (since we'll be blending with that).
+      if (_table[last_frame % _table.size()] != 
+          _table[(this_frame + 1) % _table.size()]) {
+        return true;
+      }
     }
     }
   }
   }
 
 

+ 2 - 1
panda/src/chan/animChannelScalarTable.h

@@ -40,7 +40,8 @@ protected:
 public:
 public:
   AnimChannelScalarTable(AnimGroup *parent, const string &name);
   AnimChannelScalarTable(AnimGroup *parent, const string &name);
 
 
-  virtual bool has_changed(double last_frame, double this_frame);
+  virtual bool has_changed(int last_frame, double last_frac, 
+                           int this_frame, double this_frac);
   virtual void get_value(int frame, float &value);
   virtual void get_value(int frame, float &value);
 
 
   void set_table(const CPTA_float &table);
   void set_table(const CPTA_float &table);

+ 11 - 8
panda/src/chan/animControl.cxx

@@ -88,15 +88,17 @@ output(ostream &out) const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool AnimControl::
 bool AnimControl::
 channel_has_changed(AnimChannelBase *channel, bool frame_blend_flag) const {
 channel_has_changed(AnimChannelBase *channel, bool frame_blend_flag) const {
-  if (_marked_frame < 0.0) {
+  if (_marked_frame < 0) {
     return true;
     return true;
   }
   }
 
 
-  double this_frame = get_full_fframe();
-  if (!frame_blend_flag) {
-    this_frame = floor(this_frame + 0.0001);
+  int this_frame = get_frame();
+  double this_frac = 0.0;
+  if (frame_blend_flag) {
+    this_frac = get_frac();
   }
   }
-  return channel->has_changed(_marked_frame, this_frame);
+  return channel->has_changed(_marked_frame, _marked_frac, 
+                              this_frame, this_frac);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -107,9 +109,10 @@ channel_has_changed(AnimChannelBase *channel, bool frame_blend_flag) const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void AnimControl::
 void AnimControl::
 mark_channels(bool frame_blend_flag) {
 mark_channels(bool frame_blend_flag) {
-  _marked_frame = get_full_fframe();
-  if (!frame_blend_flag) {
-    _marked_frame = floor(_marked_frame + 0.0001);
+  _marked_frame = get_frame();
+  _marked_frac = 0.0;
+  if (frame_blend_flag) {
+    _marked_frac = get_frac();
   }
   }
 }
 }
 
 

+ 4 - 1
panda/src/chan/animControl.h

@@ -74,7 +74,10 @@ private:
   int _channel_index;
   int _channel_index;
 
 
   // This is the frame number as of the last call to mark_channels().
   // This is the frame number as of the last call to mark_channels().
-  double _marked_frame;
+  // In frame_blend mode, we also record the fractional part of the
+  // frame number.
+  int _marked_frame;
+  double _marked_frac;
 
 
   // This is the bitmask of joints and/or sliders from the animation
   // This is the bitmask of joints and/or sliders from the animation
   // that we have actually bound into this AnimControl.  See
   // that we have actually bound into this AnimControl.  See

+ 1 - 1
panda/src/chan/movingPartBase.cxx

@@ -137,7 +137,7 @@ do_update(PartBundle *root, const CycleData *root_cdata, PartGroup *parent,
 
 
   if (_forced_channel != (AnimChannelBase *)NULL) {
   if (_forced_channel != (AnimChannelBase *)NULL) {
     if (!needs_update) {
     if (!needs_update) {
-      needs_update = _forced_channel->has_changed(0.0, 0.0);
+      needs_update = _forced_channel->has_changed(0, 0.0, 0, 0.0);
     }
     }
 
 
   } else {
   } else {