rework controlJoint() and freezeJoint() to reduce memory footprint

This commit is contained in:
David Rose 2007-07-03 17:24:21 +00:00
parent a297fb9c6f
commit 81ae62f553
24 changed files with 374 additions and 336 deletions

View File

@ -38,23 +38,7 @@ AnimChannelFixed(AnimGroup *parent, const AnimChannelFixed<SwitchType> &copy) :
////////////////////////////////////////////////////////////////////
// Function: AnimChannelFixed::Constructor
// Access: Public
// Description: This is the flavor of AnimChannelFixed that puts it
// in a hierarchy.
////////////////////////////////////////////////////////////////////
template<class SwitchType>
INLINE AnimChannelFixed<SwitchType>::
AnimChannelFixed(AnimGroup *parent, const string &name,
const ValueType &value)
: AnimChannel<SwitchType>(parent, name),
_value(value) {
}
////////////////////////////////////////////////////////////////////
// Function: AnimChannelFixed::Constructor
// Access: Public
// Description: This flavor creates an AnimChannelFixed that is not
// in a hierarchy.
// Description:
////////////////////////////////////////////////////////////////////
template<class SwitchType>
INLINE AnimChannelFixed<SwitchType>::

View File

@ -42,7 +42,6 @@ protected:
INLINE AnimChannelFixed(AnimGroup *parent, const AnimChannelFixed<SwitchType> &copy);
public:
INLINE AnimChannelFixed(AnimGroup *parent, const string &name, const ValueType &value);
INLINE AnimChannelFixed(const string &name, const ValueType &value);
virtual bool has_changed(double last_frame, double this_frame);

View File

@ -61,8 +61,8 @@ AnimChannelMatrixDynamic(AnimGroup *parent, const AnimChannelMatrixDynamic &copy
// Description:
////////////////////////////////////////////////////////////////////
AnimChannelMatrixDynamic::
AnimChannelMatrixDynamic(AnimGroup *parent, const string &name)
: AnimChannelMatrix(parent, name)
AnimChannelMatrixDynamic(const string &name)
: AnimChannelMatrix(name)
{
_value = TransformState::make_identity();
_last_value = NULL; // This is impossible; thus, has_changed() will

View File

@ -44,7 +44,7 @@ protected:
AnimChannelMatrixDynamic(AnimGroup *parent, const AnimChannelMatrixDynamic &copy);
public:
AnimChannelMatrixDynamic(AnimGroup *parent, const string &name);
AnimChannelMatrixDynamic(const string &name);
virtual bool has_changed(double last_frame, double this_frame);
virtual void get_value(int frame, LMatrix4f &mat);

View File

@ -31,54 +31,44 @@ TypeHandle AnimChannelMatrixFixed::_type_handle;
////////////////////////////////////////////////////////////////////
AnimChannelMatrixFixed::
AnimChannelMatrixFixed(AnimGroup *parent, const AnimChannelMatrixFixed &copy) :
AnimChannelFixed<ACMatrixSwitchType>(parent, copy),
_value_no_scale_shear(copy._value_no_scale_shear),
_scale(copy._scale),
_hpr(copy._hpr),
_quat(copy._quat),
_pos(copy._pos),
_shear(copy._shear)
AnimChannel<ACMatrixSwitchType>(parent, copy),
_transform(copy._transform)
{
}
////////////////////////////////////////////////////////////////////
// Function: AnimChannelMatrixFixed::Constructor
// Access: Public
// Description: This flavor creates an AnimChannelMatrixFixed that
// *is* in a hierarchy.
// Description:
////////////////////////////////////////////////////////////////////
AnimChannelMatrixFixed::
AnimChannelMatrixFixed(AnimGroup *parent, const string &name,
const LMatrix4f &value)
: AnimChannelFixed<ACMatrixSwitchType>(parent, name, value)
AnimChannelMatrixFixed(const string &name, const TransformState *transform) :
AnimChannel<ACMatrixSwitchType>(name),
_transform(transform)
{
// Decompose the matrix into components in case we will be blending.
decompose_matrix(_value, _scale, _shear, _hpr, _pos);
compose_matrix(_value_no_scale_shear, LVecBase3f(1.0f, 1.0f, 1.0f),
_hpr, _pos);
_quat.set_hpr(_hpr);
}
////////////////////////////////////////////////////////////////////
// Function: AnimChannelMatrixFixed::Constructor
// Access: Public
// Description: This flavor creates an AnimChannelMatrixFixed that is not
// in a hierarchy.
// Function: AnimChannelFixed::has_changed
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
AnimChannelMatrixFixed::
AnimChannelMatrixFixed(const string &name, const LMatrix4f &value)
: AnimChannelFixed<ACMatrixSwitchType>(name, value)
{
// Decompose the matrix into components in case we will be blending.
decompose_matrix(_value, _scale, _shear, _hpr, _pos);
compose_matrix(_value_no_scale_shear, LVecBase3f(1.0f, 1.0f, 1.0f),
_hpr, _pos);
_quat.set_hpr(_hpr);
bool AnimChannelMatrixFixed::
has_changed(double, double) {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: AnimChannelFixed::get_value
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void AnimChannelMatrixFixed::
get_value(int, LMatrix4f &value) {
value = _transform->get_mat();
}
////////////////////////////////////////////////////////////////////
// Function: AnimChannelMatrixFixed::get_value_no_scale_shear
// Access: Public, Virtual
@ -87,7 +77,12 @@ AnimChannelMatrixFixed(const string &name, const LMatrix4f &value)
////////////////////////////////////////////////////////////////////
void AnimChannelMatrixFixed::
get_value_no_scale_shear(int frame, LMatrix4f &mat) {
mat = _value_no_scale_shear;
if (_transform->has_scale() || _transform->has_shear()) {
compose_matrix(mat, LVecBase3f(1.0f, 1.0f, 1.0f),
_transform->get_hpr(), _transform->get_pos());
} else {
mat = _transform->get_mat();
}
}
////////////////////////////////////////////////////////////////////
@ -97,7 +92,7 @@ get_value_no_scale_shear(int frame, LMatrix4f &mat) {
////////////////////////////////////////////////////////////////////
void AnimChannelMatrixFixed::
get_scale(int, LVecBase3f &scale) {
scale = _scale;
scale = _transform->get_scale();
}
////////////////////////////////////////////////////////////////////
@ -109,7 +104,7 @@ get_scale(int, LVecBase3f &scale) {
////////////////////////////////////////////////////////////////////
void AnimChannelMatrixFixed::
get_hpr(int, LVecBase3f &hpr) {
hpr = _hpr;
hpr = _transform->get_hpr();
}
////////////////////////////////////////////////////////////////////
@ -121,7 +116,7 @@ get_hpr(int, LVecBase3f &hpr) {
////////////////////////////////////////////////////////////////////
void AnimChannelMatrixFixed::
get_quat(int, LQuaternionf &quat) {
quat = _quat;
quat = _transform->get_quat();
}
////////////////////////////////////////////////////////////////////
@ -133,7 +128,7 @@ get_quat(int, LQuaternionf &quat) {
////////////////////////////////////////////////////////////////////
void AnimChannelMatrixFixed::
get_pos(int, LVecBase3f &pos) {
pos = _pos;
pos = _transform->get_pos();
}
////////////////////////////////////////////////////////////////////
@ -145,5 +140,16 @@ get_pos(int, LVecBase3f &pos) {
////////////////////////////////////////////////////////////////////
void AnimChannelMatrixFixed::
get_shear(int, LVecBase3f &shear) {
shear = _shear;
shear = _transform->get_shear();
}
////////////////////////////////////////////////////////////////////
// Function: AnimChannelFixed::output
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void AnimChannelMatrixFixed::
output(ostream &out) const {
AnimChannel<ACMatrixSwitchType>::output(out);
out << " = " << *_transform;
}

View File

@ -21,25 +21,25 @@
#include "pandabase.h"
#include "animChannelFixed.h"
#include "animChannel.h"
#include "luse.h"
EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, AnimChannelFixed<ACMatrixSwitchType>);
EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, AnimChannel<ACMatrixSwitchType>);
////////////////////////////////////////////////////////////////////
// Class : AnimChannelMatrixFixed
// Description : A specialization on AnimChannelFixed to add all the
// Description : A specialization on AnimChannel to add all the
// special matrix component operations.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA AnimChannelMatrixFixed : public AnimChannelFixed<ACMatrixSwitchType> {
class EXPCL_PANDA AnimChannelMatrixFixed : public AnimChannel<ACMatrixSwitchType> {
protected:
AnimChannelMatrixFixed(AnimGroup *parent, const AnimChannelMatrixFixed &copy);
public:
AnimChannelMatrixFixed(AnimGroup *parent, const string &name, const LMatrix4f &value);
AnimChannelMatrixFixed(const string &name, const LMatrix4f &value);
AnimChannelMatrixFixed(const string &name, const TransformState *transform);
virtual bool has_changed(double last_frame, double this_frame);
virtual void get_value(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_hpr(int frame, LVecBase3f &hpr);
@ -47,13 +47,10 @@ public:
virtual void get_pos(int frame, LVecBase3f &pos);
virtual void get_shear(int frame, LVecBase3f &shear);
virtual void output(ostream &out) const;
private:
LMatrix4f _value_no_scale_shear;
LVecBase3f _scale;
LVecBase3f _hpr;
LQuaternionf _quat;
LVecBase3f _pos;
LVecBase3f _shear;
CPT(TransformState) _transform;
public:
virtual TypeHandle get_type() const {
@ -64,9 +61,9 @@ public:
return _type_handle;
}
static void init_type() {
AnimChannelFixed<ACMatrixSwitchType>::init_type();
AnimChannel<ACMatrixSwitchType>::init_type();
register_type(_type_handle, "AnimChannelMatrixFixed",
AnimChannelFixed<ACMatrixSwitchType>::get_class_type());
AnimChannel<ACMatrixSwitchType>::get_class_type());
}
private:

View File

@ -63,8 +63,8 @@ AnimChannelScalarDynamic(AnimGroup *parent, const AnimChannelScalarDynamic &copy
// Description:
////////////////////////////////////////////////////////////////////
AnimChannelScalarDynamic::
AnimChannelScalarDynamic(AnimGroup *parent, const string &name)
: AnimChannelScalar(parent, name)
AnimChannelScalarDynamic(const string &name)
: AnimChannelScalar(name)
{
_last_value = _value = TransformState::make_identity();
_value_changed = true;

View File

@ -44,7 +44,7 @@ protected:
AnimChannelScalarDynamic(AnimGroup *parent, const AnimChannelScalarDynamic &copy);
public:
AnimChannelScalarDynamic(AnimGroup *parent, const string &name);
AnimChannelScalarDynamic(const string &name);
virtual bool has_changed(double last_frame, double this_frame);
virtual void get_value(int frame, float &value);

View File

@ -19,8 +19,6 @@
#include "animGroup.h"
#include "animBundle.h"
#include "animChannelMatrixDynamic.h"
#include "animChannelScalarDynamic.h"
#include "config_chan.h"
#include "indent.h"
@ -145,116 +143,6 @@ find_child(const string &name) const {
return (AnimGroup *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: AnimGroup::make_child_dynamic
// Access: Public
// Description: Finds the indicated child and replaces it with an
// AnimChannelMatrixDynamic or AnimChannelScalarDynamic,
// as appropriate, and returns the new channel.
//
// This may be called before binding the animation to a
// character to replace certain joints with
// dynamically-controlled ones.
//
// Returns NULL if the named child cannot be found.
////////////////////////////////////////////////////////////////////
AnimGroup *AnimGroup::
make_child_dynamic(const string &name) {
Children::iterator ci;
for (ci = _children.begin(); ci != _children.end(); ++ci) {
AnimGroup *child = (*ci);
if (child->get_name() == name) {
AnimGroup *new_child = NULL;
if (child->is_of_type(AnimChannelMatrix::get_class_type())) {
AnimChannelMatrix *mchild = DCAST(AnimChannelMatrix, child);
AnimChannelMatrixDynamic *new_mchild =
new AnimChannelMatrixDynamic(this, name);
new_child = new_mchild;
// Copy in the original value from frame 0.
LMatrix4f orig_value;
mchild->get_value(0, orig_value);
new_mchild->set_value(orig_value);
} else if (child->is_of_type(AnimChannelScalar::get_class_type())) {
AnimChannelScalar *schild = DCAST(AnimChannelScalar, child);
AnimChannelScalarDynamic *new_schild =
new AnimChannelScalarDynamic(this, name);
new_child = new_schild;
// Copy in the original value from frame 0.
float orig_value;
schild->get_value(0, orig_value);
new_schild->set_value(orig_value);
}
if (new_child != (AnimGroup *)NULL) {
new_child->_children.swap(child->_children);
nassertr(_children.back() == new_child, NULL);
// The new child was appended to the end of our children list
// by its constructor. Reposition it to replace the original
// child.
// I would like to use these lines, but for some reason it
// crashes:
/*
{
(*ci) = new_child;
_children.pop_back();
}
*/
// But this longer way of achieving the same result works
// instead:
{
Children::iterator nci;
Children new_children;
for (nci = _children.begin(); nci != _children.end(); ++nci) {
if ((*nci) == child) {
new_children.push_back(new_child);
} else if ((*nci) != new_child) {
new_children.push_back(*nci);
}
}
new_children.swap(_children);
}
return new_child;
}
}
AnimGroup *result = child->make_child_dynamic(name);
if (result != (AnimGroup *)NULL) {
return result;
}
}
return (AnimGroup *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: AnimGroup::fix_child
// Access: Public
// Description: replaces childs animation matrix with a fixed one
////////////////////////////////////////////////////////////////////
void AnimGroup::
fix_child(unsigned int index, const LMatrix4f &mat) {
AnimGroup *child = get_child(index);
AnimGroup *new_child = NULL;
if (child->is_of_type(AnimChannelMatrix::get_class_type())) {
AnimChannelMatrix *mchild = DCAST(AnimChannelMatrix, child);
AnimChannelMatrixFixed *new_mchild = new AnimChannelMatrixFixed(this, child->get_name(), mat);
new_child = new_mchild;
}
if(new_child != (AnimGroup*)NULL) {
new_child->_children.swap(child->_children);
nassertv(_children.back() == new_child);
_children[index] = new_child;
}
}
////////////////////////////////////////////////////////////////////
// Function: AnimGroup::get_value_type
// Access: Public, Virtual

View File

@ -52,7 +52,6 @@ PUBLISHED:
AnimGroup *get_child(int n) const;
AnimGroup *find_child(const string &name) const;
AnimGroup *make_child_dynamic(const string &name);
public:
virtual TypeHandle get_value_type() const;
@ -81,8 +80,6 @@ public:
static TypedWritable *make_AnimGroup(const FactoryParams &params);
void fix_child(unsigned int index, LMatrix4f const & mat);
protected:
void fillin(DatagramIterator& scan, BamReader* manager);

View File

@ -43,7 +43,36 @@ MovingPartBase(PartGroup *parent, const string &name)
// Description:
////////////////////////////////////////////////////////////////////
MovingPartBase::
MovingPartBase(){
MovingPartBase() {
}
////////////////////////////////////////////////////////////////////
// Function: MovingPartBase::clear_forced_channel
// Access: Published, Virtual
// Description: Undoes the effect of a previous call to
// apply_freeze() or apply_control(). Returns true if
// the joint was modified, false otherwise.
////////////////////////////////////////////////////////////////////
bool MovingPartBase::
clear_forced_channel() {
if (_forced_channel != (AnimChannelBase *)NULL) {
_forced_channel.clear();
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: MovingPartBase::get_forced_channel
// Access: Published, Virtual
// Description: Returns the AnimChannelBase that has been forced to
// this joint by a previous call to apply_freeze() or
// apply_control(), or NULL if no such channel has been
// applied.
////////////////////////////////////////////////////////////////////
AnimChannelBase *MovingPartBase::
get_forced_channel() const {
return _forced_channel;
}
////////////////////////////////////////////////////////////////////
@ -106,7 +135,10 @@ do_update(PartBundle *root, const CycleData *root_cdata, PartGroup *parent,
// See if any of the channel values have changed since last time.
{
if (_forced_channel != (AnimChannelBase *)NULL) {
needs_update = _forced_channel->has_changed(0.0, 0.0);
} else {
const PartBundle::CData *cdata = (const PartBundle::CData *)root_cdata;
PartBundle::ChannelBlend::const_iterator bci;
for (bci = cdata->_blend.begin();

View File

@ -51,6 +51,9 @@ public:
virtual AnimChannelBase *make_initial_channel() const=0;
PUBLISHED:
virtual bool clear_forced_channel();
virtual AnimChannelBase *get_forced_channel() const;
virtual void write(ostream &out, int indent_level) const;
virtual void write_with_value(ostream &out, int indent_level) const;
virtual void output_value(ostream &out) const=0;
@ -76,9 +79,9 @@ protected:
typedef pvector< PT(AnimChannelBase) > Channels;
Channels _channels;
PT(AnimChannelBase) _forced_channel;
public:
virtual TypeHandle get_type() const {
return get_class_type();
}

View File

@ -18,6 +18,7 @@
#include "movingPartMatrix.h"
#include "animChannelMatrixDynamic.h"
#include "animChannelMatrixFixed.h"
#include "compose_matrix.h"
#include "datagram.h"
@ -51,7 +52,7 @@ MovingPartMatrix::
////////////////////////////////////////////////////////////////////
AnimChannelBase *MovingPartMatrix::
make_initial_channel() const {
return new AnimChannelMatrixFixed(get_name(), _initial_value);
return new AnimChannelMatrixFixed(get_name(), TransformState::make_mat(_initial_value));
}
////////////////////////////////////////////////////////////////////
@ -63,6 +64,15 @@ make_initial_channel() const {
////////////////////////////////////////////////////////////////////
void MovingPartMatrix::
get_blend_value(const PartBundle *root) {
// If a forced channel is set on this particular joint, we always
// return that value instead of performing the blend. Furthermore,
// the frame number is always 0 for the forced channel.
if (_forced_channel != (AnimChannelBase *)NULL) {
ChannelType *channel = DCAST(ChannelType, _forced_channel);
channel->get_value(0, _value);
return;
}
PartBundle::CDReader cdata(root->_cycler);
if (cdata->_blend.empty()) {
@ -360,14 +370,43 @@ get_blend_value(const PartBundle *root) {
}
}
////////////////////////////////////////////////////////////////////
// Function: MovingPartMatrix::apply_freeze
// Access: Public, Virtual
// Description: Freezes this particular joint so that it will always
// hold the specified transform. Returns true if this
// is a joint that can be so frozen, false otherwise.
// This is called internally by
// PartBundle::freeze_joint().
////////////////////////////////////////////////////////////////////
bool MovingPartMatrix::
apply_freeze(const TransformState *transform) {
_forced_channel = new AnimChannelMatrixFixed(get_name(), transform);
}
////////////////////////////////////////////////////////////////////
// Function: MovingPartMatrix::apply_control
// Access: Public, Virtual
// Description: Specifies a node to influence this particular joint
// so that it will always hold the node's transform.
// Returns true if this is a joint that can be so
// controlled, false otherwise. This is called
// internally by PartBundle::control_joint().
////////////////////////////////////////////////////////////////////
bool MovingPartMatrix::
apply_control(PandaNode *node) {
AnimChannelMatrixDynamic *chan = new AnimChannelMatrixDynamic(get_name());
chan->set_value_node(node);
_forced_channel = chan;
}
////////////////////////////////////////////////////////////////////
// Function: MovingPartMatrix::make_MovingPartMatrix
// Access: Protected
// Description: Factory method to generate a MovingPartMatrix object
////////////////////////////////////////////////////////////////////
TypedWritable* MovingPartMatrix::
make_MovingPartMatrix(const FactoryParams &params)
{
make_MovingPartMatrix(const FactoryParams &params) {
MovingPartMatrix *me = new MovingPartMatrix;
DatagramIterator scan;
BamReader *manager;
@ -383,7 +422,6 @@ make_MovingPartMatrix(const FactoryParams &params)
// Description: Factory method to generate a MovingPartMatrix object
////////////////////////////////////////////////////////////////////
void MovingPartMatrix::
register_with_read_factory()
{
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_MovingPartMatrix);
}

View File

@ -46,6 +46,9 @@ public:
virtual AnimChannelBase *make_initial_channel() const;
virtual void get_blend_value(const PartBundle *root);
virtual bool apply_freeze(const TransformState *transform);
virtual bool apply_control(PandaNode *node);
protected:
INLINE MovingPartMatrix();

View File

@ -18,6 +18,7 @@
#include "movingPartScalar.h"
#include "animChannelScalarDynamic.h"
#include "datagram.h"
#include "datagramIterator.h"
#include "bamReader.h"
@ -48,6 +49,15 @@ MovingPartScalar::
////////////////////////////////////////////////////////////////////
void MovingPartScalar::
get_blend_value(const PartBundle *root) {
// If a forced channel is set on this particular scalar, we always
// return that value instead of performing the blend. Furthermore,
// the frame number is always 0 for the forced channel.
if (_forced_channel != (AnimChannelBase *)NULL) {
ChannelType *channel = DCAST(ChannelType, _forced_channel);
channel->get_value(0, _value);
return;
}
PartBundle::CDReader cdata(root->_cycler);
if (cdata->_blend.empty()) {
@ -111,14 +121,43 @@ get_blend_value(const PartBundle *root) {
}
}
////////////////////////////////////////////////////////////////////
// Function: MovingPartScalar::apply_freeze
// Access: Public, Virtual
// Description: Freezes this particular joint so that it will always
// hold the specified transform. Returns true if this
// is a joint that can be so frozen, false otherwise.
// This is called internally by
// PartBundle::freeze_joint().
////////////////////////////////////////////////////////////////////
bool MovingPartScalar::
apply_freeze(const TransformState *transform) {
_forced_channel = new AnimChannelFixed<ACScalarSwitchType>(get_name(), transform->get_pos()[0]);
}
////////////////////////////////////////////////////////////////////
// Function: MovingPartScalar::apply_control
// Access: Public, Virtual
// Description: Specifies a node to influence this particular joint
// so that it will always hold the node's transform.
// Returns true if this is a joint that can be so
// controlled, false otherwise. This is called
// internally by PartBundle::control_joint().
////////////////////////////////////////////////////////////////////
bool MovingPartScalar::
apply_control(PandaNode *node) {
AnimChannelScalarDynamic *chan = new AnimChannelScalarDynamic(get_name());
chan->set_value_node(node);
_forced_channel = chan;
}
////////////////////////////////////////////////////////////////////
// Function: MovingPartScalar::make_MovingPartScalar
// Access: Protected
// Description: Factory method to generate a MovingPartScalar object
////////////////////////////////////////////////////////////////////
TypedWritable* MovingPartScalar::
make_MovingPartScalar(const FactoryParams &params)
{
make_MovingPartScalar(const FactoryParams &params) {
MovingPartScalar *me = new MovingPartScalar;
DatagramIterator scan;
BamReader *manager;
@ -134,8 +173,7 @@ make_MovingPartScalar(const FactoryParams &params)
// Description: Factory method to generate a MovingPartScalar object
////////////////////////////////////////////////////////////////////
void MovingPartScalar::
register_with_read_factory()
{
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_MovingPartScalar);
}

View File

@ -43,6 +43,9 @@ public:
virtual void get_blend_value(const PartBundle *root);
virtual bool apply_freeze(const TransformState *transform);
virtual bool apply_control(PandaNode *node);
protected:
INLINE MovingPartScalar();

View File

@ -206,39 +206,3 @@ get_control_effect(AnimControl *control) const {
CDReader cdata(_cycler);
return do_get_control_effect(control, cdata);
}
////////////////////////////////////////////////////////////////////
// Function: PartBundle::get_modifies_anim_bundles
// Access: Published
// Description: getter for anim copying
////////////////////////////////////////////////////////////////////
INLINE bool PartBundle::
get_modifies_anim_bundles(){
return _modifies_anim_bundles;
}
////////////////////////////////////////////////////////////////////
// Function: PartBundle::set_modifies_anim_bundles
// Access: Published
// Description: setter for anim copying
////////////////////////////////////////////////////////////////////
INLINE void PartBundle::
set_modifies_anim_bundles(bool value){
_modifies_anim_bundles = value;
}
////////////////////////////////////////////////////////////////////
// Function: PartGroup::freeze
// Access: Published
// Description: stores a joint freeze for later binding
////////////////////////////////////////////////////////////////////
INLINE void PartBundle::
freeze_joint(const string &joint_name, LMatrix4f const &transform)
{
PT(PartGroup) pg = find_child(joint_name);
pg->freeze(transform);
_modifies_anim_bundles = true;
}

View File

@ -51,8 +51,7 @@ static ConfigVariableEnum<PartBundle::BlendType> anim_blend_type
////////////////////////////////////////////////////////////////////
PartBundle::
PartBundle(const PartBundle &copy) :
PartGroup(copy),
_modifies_anim_bundles(copy._modifies_anim_bundles)
PartGroup(copy)
{
CDWriter cdata(_cycler, true);
CDReader cdata_from(copy._cycler);
@ -71,8 +70,7 @@ PartBundle(const PartBundle &copy) :
////////////////////////////////////////////////////////////////////
PartBundle::
PartBundle(const string &name) :
PartGroup(name),
_modifies_anim_bundles(false)
PartGroup(name)
{
}
@ -224,10 +222,6 @@ bind_anim(AnimBundle *anim, int hierarchy_match_flags,
}
}
if(_modifies_anim_bundles) {
ptanim = ptanim->copy_bundle();
}
if (!check_hierarchy(anim, NULL, hierarchy_match_flags)) {
return NULL;
}
@ -250,6 +244,74 @@ bind_anim(AnimBundle *anim, int hierarchy_match_flags,
return new AnimControl(this, anim, channel_index, bound_joints);
}
////////////////////////////////////////////////////////////////////
// Function: PartBundle::freeze_joint
// Access: Published
// Description: Specifies that the joint with the indicated name
// should be frozen with the specified transform. It
// will henceforth always hold this fixed transform,
// regardless of any animations that may subsequently be
// bound to the joint.
//
// Returns true if the joint is successfully frozen, or
// false if the named child is not a joint (or slider)
// or does not exist.
////////////////////////////////////////////////////////////////////
bool PartBundle::
freeze_joint(const string &joint_name, const TransformState *transform) {
PartGroup *child = find_child(joint_name);
if (child == (PartGroup *)NULL) {
return false;
}
return child->apply_freeze(transform);
}
////////////////////////////////////////////////////////////////////
// Function: PartBundle::control_joint
// Access: Published
// Description: Specifies that the joint with the indicated name
// should be animated with the transform on the
// indicated node. It will henceforth always follow the
// node's transform, regardless of any animations that
// may subsequently be bound to the joint.
//
// Returns true if the joint is successfully controlled,
// or false if the named child is not a joint (or
// slider) or does not exist.
////////////////////////////////////////////////////////////////////
bool PartBundle::
control_joint(const string &joint_name, PandaNode *node) {
PartGroup *child = find_child(joint_name);
if (child == (PartGroup *)NULL) {
return false;
}
return child->apply_control(node);
}
////////////////////////////////////////////////////////////////////
// Function: PartBundle::release_joint
// Access: Published
// Description: Releases the named joint from the effects of a
// previous call to freeze_joint() or control_joint().
// It will henceforth once again follow whatever
// transforms are dictated by the animation.
//
// Returns true if the joint is released, or false if
// the named child was not previously controlled or
// frozen, or it does not exist.
////////////////////////////////////////////////////////////////////
bool PartBundle::
release_joint(const string &joint_name) {
PartGroup *child = find_child(joint_name);
if (child == (PartGroup *)NULL) {
return false;
}
return child->clear_forced_channel();
}
////////////////////////////////////////////////////////////////////
// Function: PartBundle::update
// Access: Published
@ -498,7 +560,6 @@ void PartBundle::
write_datagram(BamWriter *manager, Datagram &dg) {
PartGroup::write_datagram(manager, dg);
manager->write_cdata(dg, _cycler);
dg.add_bool(_modifies_anim_bundles);
}
////////////////////////////////////////////////////////////////////
@ -532,8 +593,9 @@ fillin(DatagramIterator &scan, BamReader *manager) {
if (manager->get_file_minor_ver() >= 10) {
manager->read_cdata(scan, _cycler);
}
if (manager->get_file_minor_ver() >= 11) {
_modifies_anim_bundles=scan.get_bool();
if (manager->get_file_minor_ver() == 11) {
// No longer need the _modifies_anim_bundles flag
scan.get_bool();
}
}

View File

@ -36,6 +36,7 @@
class AnimBundle;
class PartBundleNode;
class PartBundleNode;
class TransformState;
////////////////////////////////////////////////////////////////////
// Class : PartBundle
@ -120,14 +121,13 @@ PUBLISHED:
int hierarchy_match_flags = 0,
const PartSubset &subset = PartSubset());
INLINE void freeze_joint(const string &joint_name, LMatrix4f const &transform);
bool freeze_joint(const string &joint_name, const TransformState *transform);
bool control_joint(const string &joint_name, PandaNode *node);
bool release_joint(const string &joint_name);
bool update();
bool force_update();
INLINE bool get_modifies_anim_bundles();
INLINE void set_modifies_anim_bundles(bool value);
public:
// The following functions aren't really part of the public
// interface; they're just public so we don't have to declare a
@ -139,10 +139,6 @@ protected:
virtual void remove_node(PartBundleNode *node);
private:
//this is used to determine when to copy the anim bundle
bool _modifies_anim_bundles;
class CData;
void do_set_control_effect(AnimControl *control, float effect, CData *cdata);

View File

@ -27,8 +27,7 @@
INLINE PartGroup::
PartGroup(const string &name) :
Namable(name),
_children(get_class_type()),
_frozen(0)
_children(get_class_type())
{
}
@ -42,23 +41,8 @@ PartGroup(const string &name) :
INLINE PartGroup::
PartGroup(const PartGroup &copy) :
Namable(copy),
_children(get_class_type()),
_frozen(copy._frozen),
_frozen_transform(copy._frozen_transform)
_children(get_class_type())
{
// We don't copy children in the copy constructor. However,
// copy_subgraph() will do this.
}
////////////////////////////////////////////////////////////////////
// Function: PartGroup::freeze
// Access: Published
// Description: stores a joint freeze for later binding
////////////////////////////////////////////////////////////////////
INLINE void PartGroup::
freeze(LMatrix4f const &transform)
{
_frozen = true;
_frozen_transform=LMatrix4f(transform);
}

View File

@ -46,7 +46,6 @@ PartGroup(PartGroup *parent, const string &name) :
nassertv(parent != NULL);
parent->_children.push_back(this);
_frozen = false;
}
////////////////////////////////////////////////////////////////////
@ -139,6 +138,68 @@ find_child(const string &name) const {
return (PartGroup *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: PartGroup::apply_freeze
// Access: Published, Virtual
// Description: Freezes this particular joint so that it will always
// hold the specified transform. Returns true if this
// is a joint that can be so frozen, false otherwise.
//
// This is normally only called internally by
// PartBundle::freeze_joint(), but you may also call it
// directly.
////////////////////////////////////////////////////////////////////
bool PartGroup::
apply_freeze(const TransformState *transform) {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: PartGroup::apply_control
// Access: Published, Virtual
// Description: Specifies a node to influence this particular joint
// so that it will always hold the node's transform.
// Returns true if this is a joint that can be so
// controlled, false otherwise.
//
// This is normally only called internally by
// PartBundle::control_joint(), but you may also call it
// directly.
////////////////////////////////////////////////////////////////////
bool PartGroup::
apply_control(PandaNode *node) {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: PartGroup::clear_forced_channel
// Access: Published, Virtual
// Description: Undoes the effect of a previous call to
// apply_freeze() or apply_control(). Returns true if
// the joint was modified, false otherwise.
//
// This is normally only called internally by
// PartBundle::release_joint(), but you may also call it
// directly.
////////////////////////////////////////////////////////////////////
bool PartGroup::
clear_forced_channel() {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: PartGroup::get_forced_channel
// Access: Published, Virtual
// Description: Returns the AnimChannelBase that has been forced to
// this joint by a previous call to apply_freeze() or
// apply_control(), or NULL if no such channel has been
// applied.
////////////////////////////////////////////////////////////////////
AnimChannelBase *PartGroup::
get_forced_channel() const {
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: PartGroup::get_value_type
// Access: Public, Virtual
@ -192,9 +253,6 @@ sort_descendants() {
// PartGroup::HierarchyMatchFlags values indicating
// conditions that will be tolerated (but warnings will
// still be issued).
//
// If there is a discrepancy, it is reported to the
// indicated output stream, if it is non-null.
////////////////////////////////////////////////////////////////////
bool PartGroup::
check_hierarchy(const AnimGroup *anim, const PartGroup *,
@ -426,9 +484,6 @@ write_descendants_with_value(ostream &out, int indent_level) const {
}
}
////////////////////////////////////////////////////////////////////
// Function: PartGroup::pick_channel_index
// Access: Protected, Virtual
@ -468,10 +523,6 @@ bind_hierarchy(AnimGroup *anim, int channel_index, int &joint_index,
while (i < part_num_children && j < anim_num_children) {
PartGroup *pc = get_child(i);
if (pc->_frozen) {
anim->fix_child(j, pc->_frozen_transform);
}
AnimGroup *ac = anim->get_child(j);
if (pc->get_name() < ac->get_name()) {
@ -510,15 +561,10 @@ bind_hierarchy(AnimGroup *anim, int channel_index, int &joint_index,
// the particular object to a Datagram
////////////////////////////////////////////////////////////////////
void PartGroup::
write_datagram(BamWriter *manager, Datagram &me)
{
int i;
write_datagram(BamWriter *manager, Datagram &me) {
me.add_string(get_name());
me.add_bool(_frozen);
_frozen_transform.write_datagram(me);
me.add_uint16(_children.size());
for(i = 0; i < (int)_children.size(); i++)
{
for (size_t i = 0; i < _children.size(); i++) {
manager->write_pointer(me, _children[i]);
}
}
@ -532,46 +578,41 @@ write_datagram(BamWriter *manager, Datagram &me)
// place
////////////////////////////////////////////////////////////////////
void PartGroup::
fillin(DatagramIterator& scan, BamReader* manager)
{
int i;
fillin(DatagramIterator &scan, BamReader *manager) {
set_name(scan.get_string());
if (manager->get_file_minor_ver() >= 11) {
_frozen=scan.get_bool();
_frozen_transform.read_datagram(scan);
if (manager->get_file_minor_ver() == 11) {
// Skip over the old freeze-joint information, no longer stored here
scan.get_bool();
LMatrix4f mat;
mat.read_datagram(scan);
}
_num_children = scan.get_uint16();
for(i = 0; i < _num_children; i++)
{
int num_children = scan.get_uint16();
_children.reserve(num_children);
for (int i = 0; i < num_children; i++) {
manager->read_pointer(scan);
_children.push_back(NULL);
}
}
////////////////////////////////////////////////////////////////////
// Function: PartGroup::complete_pointers
// Access: Public
// Description: Takes in a vector of pointes to TypedWritable
// Description: Takes in a vector of pointers to TypedWritable
// objects that correspond to all the requests for
// pointers that this object made to BamReader.
////////////////////////////////////////////////////////////////////
int PartGroup::
complete_pointers(TypedWritable **p_list, BamReader*)
{
int i;
for(i = 0; i < _num_children; i++)
{
if (p_list[i] == TypedWritable::Null)
{
chan_cat->warning() << get_type().get_name()
<< " Ignoring null PartGroup" << endl;
}
else
{
_children.push_back(DCAST(PartGroup, p_list[i]));
}
complete_pointers(TypedWritable **p_list, BamReader *manager) {
int pi = TypedWritableReferenceCount::complete_pointers(p_list, manager);
Children::iterator ci;
for (ci = _children.begin(); ci != _children.end(); ++ci) {
(*ci) = DCAST(PartGroup, p_list[pi++]);
}
return _num_children;
return pi;
}
////////////////////////////////////////////////////////////////////
@ -580,8 +621,7 @@ complete_pointers(TypedWritable **p_list, BamReader*)
// Description: Factory method to generate a PartGroup object
////////////////////////////////////////////////////////////////////
TypedWritable* PartGroup::
make_PartGroup(const FactoryParams &params)
{
make_PartGroup(const FactoryParams &params) {
PartGroup *me = new PartGroup;
DatagramIterator scan;
BamReader *manager;
@ -597,8 +637,7 @@ make_PartGroup(const FactoryParams &params)
// Description: Factory method to generate a PartGroup object
////////////////////////////////////////////////////////////////////
void PartGroup::
register_with_read_factory()
{
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_PartGroup);
}

View File

@ -37,6 +37,9 @@ class BamReader;
class FactoryParams;
class BitArray;
class CycleData;
class TransformState;
class PandaNode;
class AnimChannelBase;
////////////////////////////////////////////////////////////////////
// Class : PartGroup
@ -76,11 +79,14 @@ PUBLISHED:
PartGroup *get_child(int n) const;
PartGroup *find_child(const string &name) const;
virtual bool apply_freeze(const TransformState *transform);
virtual bool apply_control(PandaNode *node);
virtual bool clear_forced_channel();
virtual AnimChannelBase *get_forced_channel() const;
virtual void write(ostream &out, int indent_level) const;
virtual void write_with_value(ostream &out, int indent_level) const;
INLINE void freeze(LMatrix4f const &transform);
public:
virtual TypeHandle get_value_type() const;
@ -118,14 +124,7 @@ public:
protected:
void fillin(DatagramIterator& scan, BamReader* manager);
private:
int _num_children;
bool _frozen;
LMatrix4f _frozen_transform;
public:
virtual TypeHandle get_type() const {
return get_class_type();
}
@ -141,13 +140,12 @@ public:
TypedWritableReferenceCount::get_class_type());
}
private:
static TypeHandle _type_handle;
friend class Character;
friend class CharacterJointBundle;
friend class PartBundle;
};
#include "partGroup.I"

View File

@ -89,6 +89,12 @@ remove_node(PartBundleNode *node) {
////////////////////////////////////////////////////////////////////
void CharacterJointBundle::
r_set_character(PartGroup *group, Character *character) {
if (group == (PartGroup *)NULL) {
// This might happen if we are in the middle of reading the
// Character's hierarchy from the bam file.
return;
}
if (group->is_of_type(CharacterJoint::get_class_type())) {
DCAST(CharacterJoint, group)->set_character(character);
}

View File

@ -36,7 +36,7 @@ static const unsigned short _bam_major_ver = 6;
// Bumped to major version 5 on 5/6/05 for new Geom implementation.
// Bumped to major version 6 on 2/11/06 to factor out PandaNode::CData.
static const unsigned short _bam_minor_ver = 11;
static const unsigned short _bam_minor_ver = 12;
// Bumped to minor version 1 on 3/12/06 to add Texture::_compression.
// Bumped to minor version 2 on 3/17/06 to add PandaNode::_draw_control_mask.
// Bumped to minor version 3 on 3/21/06 to add Texture::_ram_images.
@ -48,6 +48,7 @@ static const unsigned short _bam_minor_ver = 11;
// Bumped to minor version 9 on 5/15/07 to add PlaneNode::_clip_effect.
// Bumped to minor version 10 on 6/19/07 to properly write PartBundles.
// Bumped to minor version 11 on 6/20/07 to write frozen joints to PartGroups.
// Bumped to minor version 12 on 7/3/07 to rework control/frozen joints more.
#endif