mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 02:42:49 -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::
|
INLINE MovingPartBase::
|
||||||
MovingPartBase(const MovingPartBase ©) :
|
MovingPartBase(const MovingPartBase ©) :
|
||||||
PartGroup(copy),
|
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,
|
// We don't copy the bound channels. We do copy the forced_channel,
|
||||||
// though this is just a pointerwise copy.
|
// though this is just a pointerwise copy.
|
||||||
|
@ -29,8 +29,11 @@ TypeHandle MovingPartBase::_type_handle;
|
|||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
MovingPartBase::
|
MovingPartBase::
|
||||||
MovingPartBase(PartGroup *parent, const string &name)
|
MovingPartBase(PartGroup *parent, const string &name) :
|
||||||
: PartGroup(parent, name) {
|
PartGroup(parent, name),
|
||||||
|
_num_effective_channels(0),
|
||||||
|
_effective_control(NULL)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -39,7 +42,10 @@ MovingPartBase(PartGroup *parent, const string &name)
|
|||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
MovingPartBase::
|
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);
|
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 {
|
} else {
|
||||||
const PartBundle::CData *cdata = (const PartBundle::CData *)root_cdata;
|
const PartBundle::CData *cdata = (const PartBundle::CData *)root_cdata;
|
||||||
PartBundle::ChannelBlend::const_iterator bci;
|
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);
|
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,
|
virtual void find_bound_joints(int &joint_index, bool is_included,
|
||||||
BitArray &bound_joints,
|
BitArray &bound_joints,
|
||||||
const PartSubset &subset);
|
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;
|
typedef pvector< PT(AnimChannelBase) > Channels;
|
||||||
Channels _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;
|
PT(AnimChannelBase) _forced_channel;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -77,39 +77,16 @@ get_blend_value(const PartBundle *root) {
|
|||||||
_value = _initial_value;
|
_value = _initial_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if ((cdata->_blend.size() == 1 || !cdata->_anim_blend_flag) &&
|
} else if (_effective_control != (AnimControl *)NULL &&
|
||||||
!cdata->_frame_blend_flag) {
|
!cdata->_frame_blend_flag) {
|
||||||
// A single value, the normal case.
|
// A single value, the normal case.
|
||||||
AnimControl *bound_control = NULL;
|
ChannelType *channel = DCAST(ChannelType, _effective_channel);
|
||||||
ChannelType *bound_channel = NULL;
|
channel->get_value(_effective_control->get_frame(), _value);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// A blend of two or more values, either between multiple
|
// A blend of two or more values, either between multiple
|
||||||
// different animations, or between consecutive frames of the same
|
// different animations, or between consecutive frames of the same
|
||||||
// animation (or both).
|
// animation (or both).
|
||||||
|
|
||||||
switch (cdata->_blend_type) {
|
switch (cdata->_blend_type) {
|
||||||
case PartBundle::BT_linear:
|
case PartBundle::BT_linear:
|
||||||
{
|
{
|
||||||
|
@ -62,33 +62,11 @@ get_blend_value(const PartBundle *root) {
|
|||||||
_value = _initial_value;
|
_value = _initial_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if ((cdata->_blend.size() == 1 || !cdata->_anim_blend_flag) &&
|
} else if (_effective_control != (AnimControl *)NULL &&
|
||||||
!cdata->_frame_blend_flag) {
|
!cdata->_frame_blend_flag) {
|
||||||
// A single value, the normal case.
|
// A single value, the normal case.
|
||||||
AnimControl *bound_control = NULL;
|
ChannelType *channel = DCAST(ChannelType, _effective_channel);
|
||||||
ChannelType *bound_channel = NULL;
|
channel->get_value(_effective_control->get_frame(), _value);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// A blend of two or more values.
|
// 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,
|
bind_hierarchy(ptanim, channel_index, joint_index,
|
||||||
subset.is_include_empty(), bound_joints, subset);
|
subset.is_include_empty(), bound_joints, subset);
|
||||||
control->setup_anim(this, anim, channel_index, bound_joints);
|
control->setup_anim(this, anim, channel_index, bound_joints);
|
||||||
|
|
||||||
|
CDReader cdata(_cycler);
|
||||||
|
determine_effective_channels(cdata);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -706,6 +710,7 @@ recompute_net_blend(CData *cdata) {
|
|||||||
for (bti = cdata->_blend.begin(); bti != cdata->_blend.end(); ++bti) {
|
for (bti = cdata->_blend.begin(); bti != cdata->_blend.end(); ++bti) {
|
||||||
cdata->_net_blend += (*bti).second;
|
cdata->_net_blend += (*bti).second;
|
||||||
}
|
}
|
||||||
|
determine_effective_channels(cdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
@ -53,6 +53,18 @@ PartGroup::
|
|||||||
~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
|
// Function: PartGroup::make_copy
|
||||||
// Access: Public, Virtual
|
// 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
|
// Function: PartGroup::write_descendants
|
||||||
|
@ -66,6 +66,7 @@ PUBLISHED:
|
|||||||
// This is the normal PartGroup constructor.
|
// This is the normal PartGroup constructor.
|
||||||
PartGroup(PartGroup *parent, const string &name);
|
PartGroup(PartGroup *parent, const string &name);
|
||||||
virtual ~PartGroup();
|
virtual ~PartGroup();
|
||||||
|
virtual bool is_character_joint() const;
|
||||||
|
|
||||||
virtual PartGroup *make_copy() const;
|
virtual PartGroup *make_copy() const;
|
||||||
PartGroup *copy_subgraph() const;
|
PartGroup *copy_subgraph() const;
|
||||||
@ -96,6 +97,7 @@ public:
|
|||||||
PartGroup *parent, bool parent_changed,
|
PartGroup *parent, bool parent_changed,
|
||||||
bool anim_changed, Thread *current_thread);
|
bool anim_changed, Thread *current_thread);
|
||||||
virtual void do_xform(const LMatrix4f &mat, const LMatrix4f &inv_mat);
|
virtual void do_xform(const LMatrix4f &mat, const LMatrix4f &inv_mat);
|
||||||
|
virtual void determine_effective_channels(const CycleData *root_cdata);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void write_descendants(ostream &out, int indent_level) const;
|
void write_descendants(ostream &out, int indent_level) const;
|
||||||
|
@ -83,6 +83,18 @@ CharacterJoint::
|
|||||||
nassertv(_character == (Character *)NULL);
|
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
|
// Function: CharacterJoint::make_copy
|
||||||
// Access: Public, Virtual
|
// Access: Public, Virtual
|
||||||
@ -112,11 +124,10 @@ make_copy() const {
|
|||||||
bool CharacterJoint::
|
bool CharacterJoint::
|
||||||
update_internals(PartBundle *root, PartGroup *parent, bool self_changed,
|
update_internals(PartBundle *root, PartGroup *parent, bool self_changed,
|
||||||
bool parent_changed, Thread *current_thread) {
|
bool parent_changed, Thread *current_thread) {
|
||||||
|
|
||||||
nassertr(parent != (PartGroup *)NULL, false);
|
nassertr(parent != (PartGroup *)NULL, false);
|
||||||
|
|
||||||
bool net_changed = 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
|
// The joint is not a toplevel joint; its parent therefore affects
|
||||||
// its net transform.
|
// its net transform.
|
||||||
if (parent_changed || self_changed) {
|
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);
|
CPT(TransformState) t = TransformState::make_mat(_net_transform);
|
||||||
|
|
||||||
NodeList::iterator ai;
|
NodeList::iterator ai;
|
||||||
ai = _net_transform_nodes.begin();
|
for (ai = _net_transform_nodes.begin();
|
||||||
while (ai != _net_transform_nodes.end()) {
|
ai != _net_transform_nodes.end();
|
||||||
|
++ai) {
|
||||||
PandaNode *node = *ai;
|
PandaNode *node = *ai;
|
||||||
node->set_transform(t, current_thread);
|
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);
|
CPT(TransformState) t = TransformState::make_mat(_value);
|
||||||
|
|
||||||
NodeList::iterator ai;
|
NodeList::iterator ai;
|
||||||
ai = _local_transform_nodes.begin();
|
for (ai = _local_transform_nodes.begin();
|
||||||
while (ai != _local_transform_nodes.end()) {
|
ai != _local_transform_nodes.end();
|
||||||
|
++ai) {
|
||||||
PandaNode *node = *ai;
|
PandaNode *node = *ai;
|
||||||
node->set_transform(t, current_thread);
|
node->set_transform(t, current_thread);
|
||||||
++ai;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "movingPartMatrix.h"
|
#include "movingPartMatrix.h"
|
||||||
#include "pandaNode.h"
|
#include "pandaNode.h"
|
||||||
#include "nodePathCollection.h"
|
#include "nodePathCollection.h"
|
||||||
|
#include "ordered_vector.h"
|
||||||
|
|
||||||
class JointVertexTransform;
|
class JointVertexTransform;
|
||||||
class Character;
|
class Character;
|
||||||
@ -41,6 +42,7 @@ PUBLISHED:
|
|||||||
virtual ~CharacterJoint();
|
virtual ~CharacterJoint();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
virtual bool is_character_joint() const;
|
||||||
virtual PartGroup *make_copy() const;
|
virtual PartGroup *make_copy() const;
|
||||||
|
|
||||||
virtual bool update_internals(PartBundle *root, PartGroup *parent,
|
virtual bool update_internals(PartBundle *root, PartGroup *parent,
|
||||||
@ -73,11 +75,11 @@ private:
|
|||||||
// Not a reference-counted pointer.
|
// Not a reference-counted pointer.
|
||||||
Character *_character;
|
Character *_character;
|
||||||
|
|
||||||
typedef pset< PT(PandaNode) > NodeList;
|
typedef ov_set< PT(PandaNode) > NodeList;
|
||||||
NodeList _net_transform_nodes;
|
NodeList _net_transform_nodes;
|
||||||
NodeList _local_transform_nodes;
|
NodeList _local_transform_nodes;
|
||||||
|
|
||||||
typedef pset<JointVertexTransform *> VertexTransforms;
|
typedef ov_set<JointVertexTransform *> VertexTransforms;
|
||||||
VertexTransforms _vertex_transforms;
|
VertexTransforms _vertex_transforms;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#include "typedWritableReferenceCount.h"
|
#include "typedWritableReferenceCount.h"
|
||||||
#include "updateSeq.h"
|
#include "updateSeq.h"
|
||||||
#include "luse.h"
|
#include "luse.h"
|
||||||
#include "pset.h"
|
#include "ordered_vector.h"
|
||||||
#include "cycleData.h"
|
#include "cycleData.h"
|
||||||
#include "cycleDataReader.h"
|
#include "cycleDataReader.h"
|
||||||
#include "cycleDataWriter.h"
|
#include "cycleDataWriter.h"
|
||||||
@ -57,7 +57,7 @@ protected:
|
|||||||
void mark_modified(Thread *current_thread);
|
void mark_modified(Thread *current_thread);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef pset<TransformTable *> Palettes;
|
typedef ov_set<TransformTable *> Palettes;
|
||||||
Palettes _tables;
|
Palettes _tables;
|
||||||
|
|
||||||
// This is the data that must be cycled between pipeline stages.
|
// This is the data that must be cycled between pipeline stages.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user