optimization for intra-frame interpolation

This commit is contained in:
David Rose 2006-10-15 17:51:17 +00:00
parent 9b2f1e4a69
commit 00577b18dc
20 changed files with 76 additions and 73 deletions

View File

@ -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;
} }

View File

@ -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;

View File

@ -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;
} }

View File

@ -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;

View File

@ -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();
} }

View File

@ -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);

View File

@ -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()] != if (_tables[i][last_i_frame % _tables[i].size()] !=
_tables[i][this_frame % _tables[i].size()]) { _tables[i][next_i_frame % _tables[i].size()]) {
return true; return true;
} }
} }

View File

@ -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);

View File

@ -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);

View File

@ -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:

View File

@ -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()] != int last_i_frame = (int)floor(last_frame);
_table[this_frame % _table.size()]) { 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;
} }
} }

View File

@ -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);

View File

@ -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 { channel_has_changed(AnimChannelBase *channel, bool frame_blend_flag) const {
if (_marked_frame < 0) { 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() { mark_channels(bool frame_blend_flag) {
_marked_frame = get_frame(); _marked_frame = get_full_fframe();
if (!frame_blend_flag) {
_marked_frame = floor(_marked_frame + 0.0001);
}
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View File

@ -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; bool channel_has_changed(AnimChannelBase *channel, bool frame_blend_flag) const;
void mark_channels(); 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

View File

@ -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;
} }

View File

@ -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, virtual bool do_update(PartBundle *root, const CycleData *root_cdata,
bool parent_changed, bool anim_changed, PartGroup *parent, bool parent_changed,
Thread *current_thread); 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,

View File

@ -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;
{ bool frame_blend_flag;
CDReader cdata(_cycler, current_thread); CDWriter cdata(_cycler, false, current_thread);
anim_changed = cdata->_anim_changed; anim_changed = cdata->_anim_changed;
frame_blend_flag = cdata->_frame_blend_flag;
if (cdata->_frame_blend_flag) { bool any_changed = do_update(this, cdata, NULL, false, anim_changed,
// If the intra-frame blend flag is on, we will just assume the current_thread);
// animation changes every time we call update().
anim_changed = true;
}
}
bool any_changed = do_update(this, 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);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View File

@ -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, if ((*ci)->do_update(root, root_cdata, this, parent_changed,
current_thread)) { anim_changed, current_thread)) {
any_changed = true; any_changed = true;
} }
} }

View File

@ -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, virtual bool do_update(PartBundle *root, const CycleData *root_cdata,
bool parent_changed, bool anim_changed, PartGroup *parent, bool parent_changed,
Thread *current_thread); 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;

View File

@ -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.
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();
}
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); double now = ClockObject::get_global_clock()->get_frame_time();
do_update(); 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();
}
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////