Browse Source

optimization for intra-frame interpolation

David Rose 19 years ago
parent
commit
00577b18dc

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

@@ -35,7 +35,7 @@ TypeHandle AnimChannelBase::_type_handle;
 //               frame number.
 //               frame number.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool AnimChannelBase::
 bool AnimChannelBase::
-has_changed(int, int) {
+has_changed(double, double) {
   return true;
   return true;
 }
 }
 
 

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

@@ -45,7 +45,7 @@ protected:
 public:
 public:
   INLINE AnimChannelBase(AnimGroup *parent, const string &name);
   INLINE AnimChannelBase(AnimGroup *parent, const string &name);
 
 
-  virtual bool has_changed(int last_frame, int this_frame);
+  virtual bool has_changed(double last_frame, double this_frame);
 
 
   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(int, int) {
+has_changed(double, double) {
   return false;
   return false;
 }
 }
 
 

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

@@ -41,7 +41,7 @@ public:
   INLINE AnimChannelFixed(AnimGroup *parent, const string &name, const ValueType &value);
   INLINE AnimChannelFixed(AnimGroup *parent, const string &name, const ValueType &value);
   INLINE AnimChannelFixed(const string &name, const ValueType &value);
   INLINE AnimChannelFixed(const string &name, const ValueType &value);
 
 
-  virtual bool has_changed(int last_frame, int this_frame);
+  virtual bool has_changed(double last_frame, double this_frame);
   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

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

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

@@ -46,7 +46,7 @@ protected:
   AnimChannelMatrixDynamic();
   AnimChannelMatrixDynamic();
 
 
 public:
 public:
-  virtual bool has_changed(int last_frame, int this_frame);
+  virtual bool has_changed(double last_frame, double this_frame);
   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);

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

@@ -70,12 +70,14 @@ AnimChannelMatrixXfmTable::
 //               frame number.
 //               frame number.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool AnimChannelMatrixXfmTable::
 bool AnimChannelMatrixXfmTable::
-has_changed(int last_frame, int this_frame) {
+has_changed(double last_frame, double this_frame) {
   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_frame % _tables[i].size()] !=
-            _tables[i][this_frame % _tables[i].size()]) {
+        if (_tables[i][last_i_frame % _tables[i].size()] !=
+            _tables[i][next_i_frame % _tables[i].size()]) {
           return true;
           return true;
         }
         }
       }
       }

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

@@ -45,7 +45,7 @@ public:
   ~AnimChannelMatrixXfmTable();
   ~AnimChannelMatrixXfmTable();
   
   
 
 
-  virtual bool has_changed(int last_frame, int this_frame);
+  virtual bool has_changed(double last_frame, double this_frame);
   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

@@ -59,7 +59,7 @@ AnimChannelScalarDynamic() {
 //               frame number.
 //               frame number.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool AnimChannelScalarDynamic::
 bool AnimChannelScalarDynamic::
-has_changed(int, int) {
+has_changed(double, 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);

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

@@ -45,7 +45,7 @@ protected:
   AnimChannelScalarDynamic();
   AnimChannelScalarDynamic();
 
 
 public:
 public:
-  virtual bool has_changed(int last_frame, int this_frame);
+  virtual bool has_changed(double last_frame, double this_frame);
   virtual void get_value(int frame, float &value);
   virtual void get_value(int frame, float &value);
 
 
 PUBLISHED:
 PUBLISHED:

+ 5 - 3
panda/src/chan/animChannelScalarTable.cxx

@@ -58,10 +58,12 @@ AnimChannelScalarTable(){
 //               frame number.
 //               frame number.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool AnimChannelScalarTable::
 bool AnimChannelScalarTable::
-has_changed(int last_frame, int this_frame) {
+has_changed(double last_frame, double this_frame) {
   if (last_frame != this_frame && _table.size() > 1) {
   if (last_frame != this_frame && _table.size() > 1) {
-    if (_table[last_frame % _table.size()] !=
-        _table[this_frame % _table.size()]) {
+    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;
       return true;
     }
     }
   }
   }

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

@@ -36,7 +36,7 @@ class EXPCL_PANDA AnimChannelScalarTable : public AnimChannelScalar {
 public:
 public:
   AnimChannelScalarTable(AnimGroup *parent, const string &name);
   AnimChannelScalarTable(AnimGroup *parent, const string &name);
 
 
-  virtual bool has_changed(int last_frame, int this_frame);
+  virtual bool has_changed(double last_frame, double this_frame);
   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 - 5
panda/src/chan/animControl.cxx

@@ -87,12 +87,15 @@ output(ostream &out) const {
 //               changed since the last call to mark_channels().
 //               changed since the last call to mark_channels().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool AnimControl::
 bool AnimControl::
-channel_has_changed(AnimChannelBase *channel) const {
-  if (_marked_frame < 0) {
+channel_has_changed(AnimChannelBase *channel, bool frame_blend_flag) const {
+  if (_marked_frame < 0.0) {
     return true;
     return true;
   }
   }
 
 
-  int this_frame = get_frame();
+  double this_frame = get_full_fframe();
+  if (!frame_blend_flag) {
+    this_frame = floor(this_frame + 0.0001);
+  }
   return channel->has_changed(_marked_frame, this_frame);
   return channel->has_changed(_marked_frame, this_frame);
 }
 }
 
 
@@ -103,8 +106,11 @@ channel_has_changed(AnimChannelBase *channel) const {
 //               next call to channel_has_changed().
 //               next call to channel_has_changed().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void AnimControl::
 void AnimControl::
-mark_channels() {
-  _marked_frame = get_frame();
+mark_channels(bool frame_blend_flag) {
+  _marked_frame = get_full_fframe();
+  if (!frame_blend_flag) {
+    _marked_frame = floor(_marked_frame + 0.0001);
+  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 3 - 3
panda/src/chan/animControl.h

@@ -59,8 +59,8 @@ public:
   // interface; they're just public so we don't have to declare a
   // interface; they're just public so we don't have to declare a
   // bunch of friends.
   // bunch of friends.
 
 
-  bool channel_has_changed(AnimChannelBase *channel) const;
-  void mark_channels();
+  bool channel_has_changed(AnimChannelBase *channel, bool frame_blend_flag) const;
+  void mark_channels(bool frame_blend_flag);
 
 
 protected:
 protected:
   virtual void animation_activated();
   virtual void animation_activated();
@@ -74,7 +74,7 @@ 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().
-  int _marked_frame;
+  double _marked_frame;
 
 
   // 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

+ 5 - 4
panda/src/chan/movingPartBase.cxx

@@ -98,7 +98,7 @@ write_with_value(ostream &out, int indent_level) const {
 //               false otherwise.
 //               false otherwise.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool MovingPartBase::
 bool MovingPartBase::
-do_update(PartBundle *root, PartGroup *parent,
+do_update(PartBundle *root, const CycleData *root_cdata, PartGroup *parent,
           bool parent_changed, bool anim_changed,
           bool parent_changed, bool anim_changed,
           Thread *current_thread) {
           Thread *current_thread) {
   bool any_changed = false;
   bool any_changed = false;
@@ -107,7 +107,7 @@ do_update(PartBundle *root, PartGroup *parent,
   // See if any of the channel values have changed since last time.
   // See if any of the channel values have changed since last time.
 
 
   {
   {
-    PartBundle::CDReader cdata(root->_cycler, current_thread);
+    const PartBundle::CData *cdata = (const PartBundle::CData *)root_cdata;
     PartBundle::ChannelBlend::const_iterator bci;
     PartBundle::ChannelBlend::const_iterator bci;
     for (bci = cdata->_blend.begin();
     for (bci = cdata->_blend.begin();
          !needs_update && bci != cdata->_blend.end();
          !needs_update && bci != cdata->_blend.end();
@@ -117,7 +117,7 @@ do_update(PartBundle *root, PartGroup *parent,
       nassertr(channel_index >= 0 && channel_index < (int)_channels.size(), false);
       nassertr(channel_index >= 0 && channel_index < (int)_channels.size(), false);
       AnimChannelBase *channel = _channels[channel_index];
       AnimChannelBase *channel = _channels[channel_index];
       if (channel != (AnimChannelBase*)NULL) {
       if (channel != (AnimChannelBase*)NULL) {
-        needs_update = control->channel_has_changed(channel);
+        needs_update = control->channel_has_changed(channel, cdata->_frame_blend_flag);
       }
       }
     }
     }
   }
   }
@@ -135,7 +135,8 @@ do_update(PartBundle *root, PartGroup *parent,
   // Now recurse.
   // Now recurse.
   Children::iterator ci;
   Children::iterator ci;
   for (ci = _children.begin(); ci != _children.end(); ++ci) {
   for (ci = _children.begin(); ci != _children.end(); ++ci) {
-    if ((*ci)->do_update(root, this, parent_changed || needs_update,
+    if ((*ci)->do_update(root, root_cdata, this, 
+                         parent_changed || needs_update,
                          anim_changed, current_thread)) {
                          anim_changed, current_thread)) {
       any_changed = true;
       any_changed = true;
     }
     }

+ 3 - 3
panda/src/chan/movingPartBase.h

@@ -56,9 +56,9 @@ PUBLISHED:
   virtual void output_value(ostream &out) const=0;
   virtual void output_value(ostream &out) const=0;
 
 
 public:
 public:
-  virtual bool do_update(PartBundle *root, PartGroup *parent,
-                         bool parent_changed, bool anim_changed,
-                         Thread *current_thread);
+  virtual bool do_update(PartBundle *root, const CycleData *root_cdata,
+                         PartGroup *parent, bool parent_changed, 
+                         bool anim_changed, Thread *current_thread);
 
 
   virtual void get_blend_value(const PartBundle *root)=0;
   virtual void get_blend_value(const PartBundle *root)=0;
   virtual bool update_internals(PartGroup *parent, bool self_changed,
   virtual bool update_internals(PartGroup *parent, bool self_changed,

+ 14 - 17
panda/src/chan/partBundle.cxx

@@ -246,24 +246,20 @@ bool PartBundle::
 update() {
 update() {
   Thread *current_thread = Thread::get_current_thread();
   Thread *current_thread = Thread::get_current_thread();
   bool anim_changed;
   bool anim_changed;
-  {
-    CDReader cdata(_cycler, current_thread);
-    anim_changed = cdata->_anim_changed;
-
-    if (cdata->_frame_blend_flag) {
-      // If the intra-frame blend flag is on, we will just assume the
-      // animation changes every time we call update().
-      anim_changed = true;
-    }
-  }
-  bool any_changed = do_update(this, NULL, false, anim_changed, current_thread);
+  bool frame_blend_flag;
+  CDWriter cdata(_cycler, false, current_thread);
+  anim_changed = cdata->_anim_changed;
+  frame_blend_flag = cdata->_frame_blend_flag;
+
+  bool any_changed = do_update(this, cdata, NULL, false, anim_changed, 
+                               current_thread);
 
 
   // Now update all the controls for next time.
   // Now update all the controls for next time.
-  CDWriter cdata(_cycler, false, current_thread);
+  //  CDWriter cdata(_cycler, false, current_thread);
   ChannelBlend::const_iterator cbi;
   ChannelBlend::const_iterator cbi;
   for (cbi = cdata->_blend.begin(); cbi != cdata->_blend.end(); ++cbi) {
   for (cbi = cdata->_blend.begin(); cbi != cdata->_blend.end(); ++cbi) {
     AnimControl *control = (*cbi).first;
     AnimControl *control = (*cbi).first;
-    control->mark_channels();
+    control->mark_channels(frame_blend_flag);
   }
   }
   
   
   cdata->_anim_changed = false;
   cdata->_anim_changed = false;
@@ -281,14 +277,14 @@ update() {
 bool PartBundle::
 bool PartBundle::
 force_update() {
 force_update() {
   Thread *current_thread = Thread::get_current_thread();
   Thread *current_thread = Thread::get_current_thread();
-  bool any_changed = do_update(this, NULL, true, true, current_thread);
+  CDWriter cdata(_cycler, false, current_thread);
+  bool any_changed = do_update(this, cdata, NULL, true, true, current_thread);
 
 
   // Now update all the controls for next time.
   // Now update all the controls for next time.
-  CDWriter cdata(_cycler, false, current_thread);
   ChannelBlend::const_iterator cbi;
   ChannelBlend::const_iterator cbi;
   for (cbi = cdata->_blend.begin(); cbi != cdata->_blend.end(); ++cbi) {
   for (cbi = cdata->_blend.begin(); cbi != cdata->_blend.end(); ++cbi) {
     AnimControl *control = (*cbi).first;
     AnimControl *control = (*cbi).first;
-    control->mark_channels();
+    control->mark_channels(cdata->_frame_blend_flag);
   }
   }
   
   
   cdata->_anim_changed = false;
   cdata->_anim_changed = false;
@@ -442,7 +438,8 @@ clear_and_stop_intersecting(AnimControl *control, CData *cdata) {
 void PartBundle::
 void PartBundle::
 finalize(BamReader *) {
 finalize(BamReader *) {
   Thread *current_thread = Thread::get_current_thread();
   Thread *current_thread = Thread::get_current_thread();
-  do_update(this, NULL, true, true, current_thread);
+  CDWriter cdata(_cycler, true);
+  do_update(this, cdata, NULL, true, true, current_thread);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

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

@@ -360,14 +360,14 @@ write_with_value(ostream &out, int indent_level) const {
 //               false otherwise.
 //               false otherwise.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool PartGroup::
 bool PartGroup::
-do_update(PartBundle *root, PartGroup *,
+do_update(PartBundle *root, const CycleData *root_cdata, PartGroup *,
           bool parent_changed, bool anim_changed, Thread *current_thread) {
           bool parent_changed, bool anim_changed, Thread *current_thread) {
   bool any_changed = false;
   bool any_changed = false;
 
 
   Children::iterator ci;
   Children::iterator ci;
   for (ci = _children.begin(); ci != _children.end(); ++ci) {
   for (ci = _children.begin(); ci != _children.end(); ++ci) {
-    if ((*ci)->do_update(root, this, parent_changed, anim_changed,
-                         current_thread)) {
+    if ((*ci)->do_update(root, root_cdata, this, parent_changed, 
+                         anim_changed, current_thread)) {
       any_changed = true;
       any_changed = true;
     }
     }
   }
   }

+ 4 - 3
panda/src/chan/partGroup.h

@@ -35,6 +35,7 @@ class PartSubset;
 class BamReader;
 class BamReader;
 class FactoryParams;
 class FactoryParams;
 class BitArray;
 class BitArray;
+class CycleData;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : PartGroup
 //       Class : PartGroup
@@ -85,9 +86,9 @@ public:
                        const PartGroup *parent,
                        const PartGroup *parent,
                        int hierarchy_match_flags = 0) const;
                        int hierarchy_match_flags = 0) const;
 
 
-  virtual bool do_update(PartBundle *root, PartGroup *parent,
-                         bool parent_changed, bool anim_changed,
-                         Thread *current_thread);
+  virtual bool do_update(PartBundle *root, const CycleData *root_cdata,
+                         PartGroup *parent, bool parent_changed, 
+                         bool anim_changed, Thread *current_thread);
 
 
 protected:
 protected:
   void write_descendants(ostream &out, int indent_level) const;
   void write_descendants(ostream &out, int indent_level) const;

+ 14 - 20
panda/src/char/character.cxx

@@ -155,19 +155,7 @@ cull_callback(CullTraverser *, CullTraverserData &) {
   // the view frustum.  We may need a better way to do this
   // the view frustum.  We may need a better way to do this
   // optimization later, to handle characters that might animate
   // optimization later, to handle characters that might animate
   // themselves in front of the view frustum.
   // themselves in front of the view frustum.
-
-  double now = ClockObject::get_global_clock()->get_frame_time();
-  if (now != _last_auto_update) {
-    _last_auto_update = now;
-
-    PStatTimer timer(_joints_pcollector);
-    if (char_cat.is_spam()) {
-      char_cat.spam() << "Animating " << *this << " at time " << now << "\n";
-    }
-    
-    do_update();
-  }
-
+  update();
   return true;
   return true;
 }
 }
 
 
@@ -211,14 +199,11 @@ calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point, bool &found_any,
 //               code to force an update of the character's position
 //               code to force an update of the character's position
 //               to the current frame, regardless of whether the
 //               to the current frame, regardless of whether the
 //               character is currently onscreen and animating.
 //               character is currently onscreen and animating.
+//
+//               This method is deprecated.  Call update() instead.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void Character::
 void Character::
 update_to_now() {
 update_to_now() {
-  if (char_cat.is_spam()) {
-    double now = ClockObject::get_global_clock()->get_frame_time();
-    char_cat.spam() << "Animating " << *this << " at time " << now << "\n";
-  }
-
   update();
   update();
 }
 }
 
 
@@ -232,8 +217,17 @@ update_to_now() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void Character::
 void Character::
 update() {
 update() {
-  PStatTimer timer(_joints_pcollector);
-  do_update();
+  double now = ClockObject::get_global_clock()->get_frame_time();
+  if (now != _last_auto_update) {
+    _last_auto_update = now;
+
+    PStatTimer timer(_joints_pcollector);
+    if (char_cat.is_spam()) {
+      char_cat.spam() << "Animating " << *this << " at time " << now << "\n";
+    }
+    
+    do_update();
+  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////