mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
shave a few more microseconds off animation time
This commit is contained in:
parent
2a5851d614
commit
a666ef78fe
@ -22,7 +22,9 @@
|
||||
INLINE MovingPartBase::
|
||||
MovingPartBase(const MovingPartBase ©) :
|
||||
PartGroup(copy),
|
||||
_forced_channel(copy._forced_channel)
|
||||
_forced_channel(copy._forced_channel),
|
||||
_num_effective_channels(0),
|
||||
_effective_control(NULL)
|
||||
{
|
||||
// We don't copy the bound channels. We do copy the forced_channel,
|
||||
// though this is just a pointerwise copy.
|
||||
|
@ -29,8 +29,11 @@ TypeHandle MovingPartBase::_type_handle;
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
MovingPartBase::
|
||||
MovingPartBase(PartGroup *parent, const string &name)
|
||||
: PartGroup(parent, name) {
|
||||
MovingPartBase(PartGroup *parent, const string &name) :
|
||||
PartGroup(parent, name),
|
||||
_num_effective_channels(0),
|
||||
_effective_control(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -39,7 +42,10 @@ MovingPartBase(PartGroup *parent, const string &name)
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
MovingPartBase::
|
||||
MovingPartBase() {
|
||||
MovingPartBase() :
|
||||
_num_effective_channels(0),
|
||||
_effective_control(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -136,6 +142,10 @@ do_update(PartBundle *root, const CycleData *root_cdata, PartGroup *parent,
|
||||
needs_update = _forced_channel->has_changed(0, 0.0, 0, 0.0);
|
||||
}
|
||||
|
||||
} else if (_effective_control != (AnimControl *)NULL) {
|
||||
const PartBundle::CData *cdata = (const PartBundle::CData *)root_cdata;
|
||||
needs_update = _effective_control->channel_has_changed(_effective_channel, cdata->_frame_blend_flag);
|
||||
|
||||
} else {
|
||||
const PartBundle::CData *cdata = (const PartBundle::CData *)root_cdata;
|
||||
PartBundle::ChannelBlend::const_iterator bci;
|
||||
@ -315,3 +325,45 @@ find_bound_joints(int &joint_index, bool is_included, BitArray &bound_joints,
|
||||
|
||||
PartGroup::find_bound_joints(joint_index, is_included, bound_joints, subset);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MovingPartBase::determine_effective_channels
|
||||
// Access: Protected, Virtual
|
||||
// Description: Should be called whenever the ChannelBlend values
|
||||
// have changed, this recursively updates the
|
||||
// _effective_channel member in each part.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MovingPartBase::
|
||||
determine_effective_channels(const CycleData *root_cdata) {
|
||||
_effective_control = NULL;
|
||||
_effective_channel = NULL;
|
||||
_num_effective_channels = 0;
|
||||
|
||||
AnimControl *effective_control = NULL;
|
||||
AnimChannelBase *effective_channel = NULL;
|
||||
int num_effective_channels = 0;
|
||||
|
||||
const PartBundle::CData *cdata = (const PartBundle::CData *)root_cdata;
|
||||
PartBundle::ChannelBlend::const_iterator cbi;
|
||||
for (cbi = cdata->_blend.begin();
|
||||
cbi != cdata->_blend.end();
|
||||
++cbi) {
|
||||
AnimControl *control = (*cbi).first;
|
||||
int channel_index = control->get_channel_index();
|
||||
if (channel_index >= 0 && channel_index < (int)_channels.size()) {
|
||||
if (_channels[channel_index] != (AnimChannelBase *)NULL) {
|
||||
effective_control = control;
|
||||
effective_channel = _channels[channel_index];
|
||||
++num_effective_channels;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_num_effective_channels = num_effective_channels;
|
||||
if (num_effective_channels == 1) {
|
||||
_effective_control = effective_control;
|
||||
_effective_channel = effective_channel;
|
||||
}
|
||||
|
||||
PartGroup::determine_effective_channels(root_cdata);
|
||||
}
|
||||
|
@ -75,9 +75,26 @@ protected:
|
||||
virtual void find_bound_joints(int &joint_index, bool is_included,
|
||||
BitArray &bound_joints,
|
||||
const PartSubset &subset);
|
||||
virtual void determine_effective_channels(const CycleData *root_cdata);
|
||||
|
||||
// This is the vector of all channels bound to this part.
|
||||
typedef pvector< PT(AnimChannelBase) > Channels;
|
||||
Channels _channels;
|
||||
|
||||
// This is the number of channels in the above _channels vector that
|
||||
// actually have an effect on this part.
|
||||
int _num_effective_channels;
|
||||
|
||||
// This is the single channel that has an effect on this part, as
|
||||
// determined by determine_effective_channels(). It is only set if
|
||||
// there is exactly one channel that affects this part
|
||||
// (i.e. _num_effective_channels is 1). If there are multiple
|
||||
// channels, or no channels at all, it is NULL.
|
||||
AnimControl *_effective_control;
|
||||
PT(AnimChannelBase) _effective_channel;
|
||||
|
||||
// This is the particular channel that's been forced to this part,
|
||||
// via set_forced_channel(). It overrides all of the above if set.
|
||||
PT(AnimChannelBase) _forced_channel;
|
||||
|
||||
public:
|
||||
|
@ -77,39 +77,16 @@ get_blend_value(const PartBundle *root) {
|
||||
_value = _initial_value;
|
||||
}
|
||||
|
||||
} else if ((cdata->_blend.size() == 1 || !cdata->_anim_blend_flag) &&
|
||||
} else if (_effective_control != (AnimControl *)NULL &&
|
||||
!cdata->_frame_blend_flag) {
|
||||
// A single value, the normal case.
|
||||
AnimControl *bound_control = NULL;
|
||||
ChannelType *bound_channel = NULL;
|
||||
|
||||
PartBundle::ChannelBlend::const_iterator cbi;
|
||||
for (cbi = cdata->_blend.begin();
|
||||
cbi != cdata->_blend.end() && bound_channel == (ChannelType *)NULL;
|
||||
++cbi) {
|
||||
AnimControl *control = (*cbi).first;
|
||||
int channel_index = control->get_channel_index();
|
||||
if (channel_index >= 0 && channel_index < (int)_channels.size()) {
|
||||
bound_control = control;
|
||||
bound_channel = DCAST(ChannelType, _channels[channel_index]);
|
||||
}
|
||||
}
|
||||
|
||||
if (bound_channel == (ChannelType *)NULL) {
|
||||
// Nothing is actually bound here.
|
||||
if (restore_initial_pose) {
|
||||
_value = _initial_value;
|
||||
}
|
||||
|
||||
} else {
|
||||
bound_channel->get_value(bound_control->get_frame(), _value);
|
||||
}
|
||||
ChannelType *channel = DCAST(ChannelType, _effective_channel);
|
||||
channel->get_value(_effective_control->get_frame(), _value);
|
||||
|
||||
} else {
|
||||
// A blend of two or more values, either between multiple
|
||||
// different animations, or between consecutive frames of the same
|
||||
// animation (or both).
|
||||
|
||||
switch (cdata->_blend_type) {
|
||||
case PartBundle::BT_linear:
|
||||
{
|
||||
|
@ -62,33 +62,11 @@ get_blend_value(const PartBundle *root) {
|
||||
_value = _initial_value;
|
||||
}
|
||||
|
||||
} else if ((cdata->_blend.size() == 1 || !cdata->_anim_blend_flag) &&
|
||||
} else if (_effective_control != (AnimControl *)NULL &&
|
||||
!cdata->_frame_blend_flag) {
|
||||
// A single value, the normal case.
|
||||
AnimControl *bound_control = NULL;
|
||||
ChannelType *bound_channel = NULL;
|
||||
|
||||
PartBundle::ChannelBlend::const_iterator cbi;
|
||||
for (cbi = cdata->_blend.begin();
|
||||
cbi != cdata->_blend.end() && bound_channel == (ChannelType *)NULL;
|
||||
++cbi) {
|
||||
AnimControl *control = (*cbi).first;
|
||||
int channel_index = control->get_channel_index();
|
||||
if (channel_index >= 0 && channel_index < (int)_channels.size()) {
|
||||
bound_control = control;
|
||||
bound_channel = DCAST(ChannelType, _channels[channel_index]);
|
||||
}
|
||||
}
|
||||
|
||||
if (bound_channel == NULL) {
|
||||
// Nothing is actually bound here.
|
||||
if (restore_initial_pose) {
|
||||
_value = _initial_value;
|
||||
}
|
||||
|
||||
} else {
|
||||
bound_channel->get_value(bound_control->get_frame(), _value);
|
||||
}
|
||||
ChannelType *channel = DCAST(ChannelType, _effective_channel);
|
||||
channel->get_value(_effective_control->get_frame(), _value);
|
||||
|
||||
} else {
|
||||
// A blend of two or more values.
|
||||
|
@ -603,6 +603,10 @@ do_bind_anim(AnimControl *control, AnimBundle *anim,
|
||||
bind_hierarchy(ptanim, channel_index, joint_index,
|
||||
subset.is_include_empty(), bound_joints, subset);
|
||||
control->setup_anim(this, anim, channel_index, bound_joints);
|
||||
|
||||
CDReader cdata(_cycler);
|
||||
determine_effective_channels(cdata);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -706,6 +710,7 @@ recompute_net_blend(CData *cdata) {
|
||||
for (bti = cdata->_blend.begin(); bti != cdata->_blend.end(); ++bti) {
|
||||
cdata->_net_blend += (*bti).second;
|
||||
}
|
||||
determine_effective_channels(cdata);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -53,6 +53,18 @@ PartGroup::
|
||||
~PartGroup() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PartGroup::is_character_joint
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns true if this part is a CharacterJoint, false
|
||||
// otherwise. This is a tiny optimization over
|
||||
// is_of_type(CharacterType::get_class_type()).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PartGroup::
|
||||
is_character_joint() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PartGroup::make_copy
|
||||
// Access: Public, Virtual
|
||||
@ -450,6 +462,21 @@ do_xform(const LMatrix4f &mat, const LMatrix4f &inv_mat) {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PartGroup::determine_effective_channels
|
||||
// Access: Public, Virtual
|
||||
// Description: Should be called whenever the ChannelBlend values
|
||||
// have changed, this recursively updates the
|
||||
// _effective_channel member in each part.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PartGroup::
|
||||
determine_effective_channels(const CycleData *root_cdata) {
|
||||
Children::iterator ci;
|
||||
for (ci = _children.begin(); ci != _children.end(); ++ci) {
|
||||
(*ci)->determine_effective_channels(root_cdata);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PartGroup::write_descendants
|
||||
|
@ -66,6 +66,7 @@ PUBLISHED:
|
||||
// This is the normal PartGroup constructor.
|
||||
PartGroup(PartGroup *parent, const string &name);
|
||||
virtual ~PartGroup();
|
||||
virtual bool is_character_joint() const;
|
||||
|
||||
virtual PartGroup *make_copy() const;
|
||||
PartGroup *copy_subgraph() const;
|
||||
@ -96,6 +97,7 @@ public:
|
||||
PartGroup *parent, bool parent_changed,
|
||||
bool anim_changed, Thread *current_thread);
|
||||
virtual void do_xform(const LMatrix4f &mat, const LMatrix4f &inv_mat);
|
||||
virtual void determine_effective_channels(const CycleData *root_cdata);
|
||||
|
||||
protected:
|
||||
void write_descendants(ostream &out, int indent_level) const;
|
||||
|
@ -83,6 +83,18 @@ CharacterJoint::
|
||||
nassertv(_character == (Character *)NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CharacterJoint::is_character_joint
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns true if this part is a CharacterJoint, false
|
||||
// otherwise. This is a tiny optimization over
|
||||
// is_of_type(CharacterType::get_class_type()).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool CharacterJoint::
|
||||
is_character_joint() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CharacterJoint::make_copy
|
||||
// Access: Public, Virtual
|
||||
@ -112,11 +124,10 @@ make_copy() const {
|
||||
bool CharacterJoint::
|
||||
update_internals(PartBundle *root, PartGroup *parent, bool self_changed,
|
||||
bool parent_changed, Thread *current_thread) {
|
||||
|
||||
nassertr(parent != (PartGroup *)NULL, false);
|
||||
|
||||
bool net_changed = false;
|
||||
if (parent->is_of_type(CharacterJoint::get_class_type())) {
|
||||
if (parent->is_character_joint()) {
|
||||
// The joint is not a toplevel joint; its parent therefore affects
|
||||
// its net transform.
|
||||
if (parent_changed || self_changed) {
|
||||
@ -140,11 +151,11 @@ update_internals(PartBundle *root, PartGroup *parent, bool self_changed,
|
||||
CPT(TransformState) t = TransformState::make_mat(_net_transform);
|
||||
|
||||
NodeList::iterator ai;
|
||||
ai = _net_transform_nodes.begin();
|
||||
while (ai != _net_transform_nodes.end()) {
|
||||
for (ai = _net_transform_nodes.begin();
|
||||
ai != _net_transform_nodes.end();
|
||||
++ai) {
|
||||
PandaNode *node = *ai;
|
||||
node->set_transform(t, current_thread);
|
||||
++ai;
|
||||
}
|
||||
}
|
||||
|
||||
@ -161,11 +172,11 @@ update_internals(PartBundle *root, PartGroup *parent, bool self_changed,
|
||||
CPT(TransformState) t = TransformState::make_mat(_value);
|
||||
|
||||
NodeList::iterator ai;
|
||||
ai = _local_transform_nodes.begin();
|
||||
while (ai != _local_transform_nodes.end()) {
|
||||
for (ai = _local_transform_nodes.begin();
|
||||
ai != _local_transform_nodes.end();
|
||||
++ai) {
|
||||
PandaNode *node = *ai;
|
||||
node->set_transform(t, current_thread);
|
||||
++ai;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "movingPartMatrix.h"
|
||||
#include "pandaNode.h"
|
||||
#include "nodePathCollection.h"
|
||||
#include "ordered_vector.h"
|
||||
|
||||
class JointVertexTransform;
|
||||
class Character;
|
||||
@ -41,6 +42,7 @@ PUBLISHED:
|
||||
virtual ~CharacterJoint();
|
||||
|
||||
public:
|
||||
virtual bool is_character_joint() const;
|
||||
virtual PartGroup *make_copy() const;
|
||||
|
||||
virtual bool update_internals(PartBundle *root, PartGroup *parent,
|
||||
@ -73,11 +75,11 @@ private:
|
||||
// Not a reference-counted pointer.
|
||||
Character *_character;
|
||||
|
||||
typedef pset< PT(PandaNode) > NodeList;
|
||||
typedef ov_set< PT(PandaNode) > NodeList;
|
||||
NodeList _net_transform_nodes;
|
||||
NodeList _local_transform_nodes;
|
||||
|
||||
typedef pset<JointVertexTransform *> VertexTransforms;
|
||||
typedef ov_set<JointVertexTransform *> VertexTransforms;
|
||||
VertexTransforms _vertex_transforms;
|
||||
|
||||
public:
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include "typedWritableReferenceCount.h"
|
||||
#include "updateSeq.h"
|
||||
#include "luse.h"
|
||||
#include "pset.h"
|
||||
#include "ordered_vector.h"
|
||||
#include "cycleData.h"
|
||||
#include "cycleDataReader.h"
|
||||
#include "cycleDataWriter.h"
|
||||
@ -57,7 +57,7 @@ protected:
|
||||
void mark_modified(Thread *current_thread);
|
||||
|
||||
private:
|
||||
typedef pset<TransformTable *> Palettes;
|
||||
typedef ov_set<TransformTable *> Palettes;
|
||||
Palettes _tables;
|
||||
|
||||
// This is the data that must be cycled between pipeline stages.
|
||||
|
Loading…
x
Reference in New Issue
Block a user