From aa837381d311e0cf4a73da0324435278544eb52d Mon Sep 17 00:00:00 2001 From: David Rose Date: Fri, 20 Jan 2006 02:45:03 +0000 Subject: [PATCH] half-body animations --- panda/src/chan/Sources.pp | 9 +- panda/src/chan/animChannelMatrixDynamic.cxx | 3 +- panda/src/chan/animChannelMatrixFixed.I | 18 ++ panda/src/chan/animChannelMatrixFixed.cxx | 110 ++++++++++++ panda/src/chan/animChannelMatrixFixed.h | 77 ++++++++ panda/src/chan/chan_composite1.cxx | 21 ++- panda/src/chan/chan_composite2.cxx | 22 +-- panda/src/chan/config_chan.cxx | 2 + panda/src/chan/movingPartBase.cxx | 40 +++-- panda/src/chan/movingPartBase.h | 6 +- panda/src/chan/movingPartMatrix.cxx | 188 ++++++++++++-------- panda/src/chan/movingPartMatrix.h | 1 + panda/src/chan/movingPartScalar.cxx | 30 ++-- panda/src/chan/partBundle.cxx | 59 ++---- panda/src/chan/partBundle.h | 11 +- panda/src/chan/partGroup.cxx | 17 +- panda/src/chan/partGroup.h | 4 +- panda/src/chan/partSubset.I | 18 ++ panda/src/chan/partSubset.cxx | 178 ++++++++++++++++++ panda/src/chan/partSubset.h | 63 +++++++ 20 files changed, 683 insertions(+), 194 deletions(-) create mode 100644 panda/src/chan/animChannelMatrixFixed.I create mode 100644 panda/src/chan/animChannelMatrixFixed.cxx create mode 100644 panda/src/chan/animChannelMatrixFixed.h create mode 100644 panda/src/chan/partSubset.I create mode 100644 panda/src/chan/partSubset.cxx create mode 100644 panda/src/chan/partSubset.h diff --git a/panda/src/chan/Sources.pp b/panda/src/chan/Sources.pp index ef0ab78caa..221c18e930 100644 --- a/panda/src/chan/Sources.pp +++ b/panda/src/chan/Sources.pp @@ -14,6 +14,7 @@ animChannel.I animChannel.h animChannelBase.I \ animChannelBase.h \ animChannelMatrixDynamic.I animChannelMatrixDynamic.h \ + animChannelMatrixFixed.I animChannelMatrixFixed.h \ animChannelMatrixXfmTable.I animChannelMatrixXfmTable.h \ animChannelScalarDynamic.I animChannelScalarDynamic.h \ animChannelScalarTable.I animChannelScalarTable.h \ @@ -25,6 +26,7 @@ movingPartScalar.h partBundle.I partBundle.N partBundle.h \ partBundleNode.I partBundleNode.h \ partGroup.I partGroup.h \ + partSubset.I partSubset.h \ vector_PartGroupStar.h #define INCLUDED_SOURCES \ @@ -33,6 +35,7 @@ animChannel.cxx \ animChannelBase.cxx \ animChannelMatrixDynamic.cxx \ + animChannelMatrixFixed.cxx \ animChannelMatrixXfmTable.cxx \ animChannelScalarDynamic.cxx \ animChannelScalarTable.cxx \ @@ -41,7 +44,9 @@ config_chan.cxx movingPartBase.cxx movingPartMatrix.cxx \ movingPartScalar.cxx partBundle.cxx \ partBundleNode.cxx \ - partGroup.cxx vector_PartGroupStar.cxx + partGroup.cxx \ + partSubset.cxx \ + vector_PartGroupStar.cxx #define INSTALL_HEADERS \ animBundle.I animBundle.h \ @@ -49,6 +54,7 @@ animChannel.I animChannel.h animChannelBase.I animChannelBase.h \ animChannelFixed.I animChannelFixed.h \ animChannelMatrixDynamic.I animChannelMatrixDynamic.h \ + animChannelMatrixFixed.I animChannelMatrixFixed.h \ animChannelMatrixXfmTable.I animChannelMatrixXfmTable.h \ animChannelScalarDynamic.I animChannelScalarDynamic.h \ animChannelScalarTable.I animChannelScalarTable.h \ @@ -60,6 +66,7 @@ movingPartScalar.I movingPartScalar.h partBundle.I partBundle.h \ partBundleNode.I partBundleNode.h \ partGroup.I partGroup.h \ + partSubset.I partSubset.h \ vector_PartGroupStar.h #define IGATESCAN all diff --git a/panda/src/chan/animChannelMatrixDynamic.cxx b/panda/src/chan/animChannelMatrixDynamic.cxx index 96bd343298..c009e366d8 100644 --- a/panda/src/chan/animChannelMatrixDynamic.cxx +++ b/panda/src/chan/animChannelMatrixDynamic.cxx @@ -26,7 +26,6 @@ #include "datagramIterator.h" #include "bamReader.h" #include "bamWriter.h" -#include "fftCompressor.h" TypeHandle AnimChannelMatrixDynamic::_type_handle; @@ -101,7 +100,7 @@ get_value_no_scale_shear(int frame, LMatrix4f &mat) { // Description: Gets the scale value at the indicated frame. //////////////////////////////////////////////////////////////////// void AnimChannelMatrixDynamic:: -get_scale(int frame, LVecBase3f &scale) { +get_scale(int, LVecBase3f &scale) { scale = _value->get_scale(); } diff --git a/panda/src/chan/animChannelMatrixFixed.I b/panda/src/chan/animChannelMatrixFixed.I new file mode 100644 index 0000000000..e3c3a4fc4d --- /dev/null +++ b/panda/src/chan/animChannelMatrixFixed.I @@ -0,0 +1,18 @@ +// Filename: animChannelMatrixFixed.I +// Created by: drose (19Jan06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + diff --git a/panda/src/chan/animChannelMatrixFixed.cxx b/panda/src/chan/animChannelMatrixFixed.cxx new file mode 100644 index 0000000000..5013ee7317 --- /dev/null +++ b/panda/src/chan/animChannelMatrixFixed.cxx @@ -0,0 +1,110 @@ +// Filename: animChannelMatrixFixed.cxx +// Created by: drose (19Jan06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "animChannelMatrixFixed.h" +#include "compose_matrix.h" + +TypeHandle AnimChannelMatrixFixed::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: AnimChannelMatrixFixed::Constructor +// Access: Public +// Description: This flavor creates an AnimChannelMatrixFixed that is not +// in a hierarchy. +//////////////////////////////////////////////////////////////////// +AnimChannelMatrixFixed:: +AnimChannelMatrixFixed(const string &name, const LMatrix4f &value) + : AnimChannelFixed(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); +} + + +//////////////////////////////////////////////////////////////////// +// Function: AnimChannelMatrixFixed::get_value_no_scale_shear +// Access: Public, Virtual +// Description: Gets the value of the channel at the indicated frame, +// without any scale or shear information. +//////////////////////////////////////////////////////////////////// +void AnimChannelMatrixFixed:: +get_value_no_scale_shear(int frame, LMatrix4f &mat) { + mat = _value_no_scale_shear; +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimChannelMatrixFixed::get_scale +// Access: Public, Virtual +// Description: Gets the scale value at the indicated frame. +//////////////////////////////////////////////////////////////////// +void AnimChannelMatrixFixed:: +get_scale(int, LVecBase3f &scale) { + scale = _scale; +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimChannelMatrixFixed::get_hpr +// Access: Public, Virtual +// Description: Returns the h, p, and r components associated +// with the current frame. As above, this only makes +// sense for a matrix-type channel. +//////////////////////////////////////////////////////////////////// +void AnimChannelMatrixFixed:: +get_hpr(int, LVecBase3f &hpr) { + hpr = _hpr; +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimChannelMatrixFixed::get_quat +// Access: Public, Virtual +// Description: Returns the rotation component associated with the +// current frame, expressed as a quaternion. As above, +// this only makes sense for a matrix-type channel. +//////////////////////////////////////////////////////////////////// +void AnimChannelMatrixFixed:: +get_quat(int, LQuaternionf &quat) { + quat = _quat; +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimChannelMatrixFixed::get_pos +// Access: Public, Virtual +// Description: Returns the x, y, and z translation components +// associated with the current frame. As above, this +// only makes sense for a matrix-type channel. +//////////////////////////////////////////////////////////////////// +void AnimChannelMatrixFixed:: +get_pos(int, LVecBase3f &pos) { + pos = _pos; +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimChannelMatrixFixed::get_shear +// Access: Public, Virtual +// Description: Returns the a, b, and c shear components associated +// with the current frame. As above, this only makes +// sense for a matrix-type channel. +//////////////////////////////////////////////////////////////////// +void AnimChannelMatrixFixed:: +get_shear(int, LVecBase3f &shear) { + shear = _shear; +} diff --git a/panda/src/chan/animChannelMatrixFixed.h b/panda/src/chan/animChannelMatrixFixed.h new file mode 100644 index 0000000000..24de10805d --- /dev/null +++ b/panda/src/chan/animChannelMatrixFixed.h @@ -0,0 +1,77 @@ +// Filename: animChannelMatrixFixed.h +// Created by: drose (19Jan06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef ANIMCHANNELMATRIXFIXED_H +#define ANIMCHANNELMATRIXFIXED_H + +#include "pandabase.h" + +#include "animChannelFixed.h" +#include "luse.h" + +EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, AnimChannelFixed); + +//////////////////////////////////////////////////////////////////// +// Class : AnimChannelMatrixFixed +// Description : A specialization on AnimChannelFixed to add all the +// special matrix component operations. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA AnimChannelMatrixFixed : public AnimChannelFixed { +public: + AnimChannelMatrixFixed(const string &name, const 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); + virtual void get_quat(int frame, LQuaternionf &quat); + virtual void get_pos(int frame, LVecBase3f &pos); + virtual void get_shear(int frame, LVecBase3f &shear); + +private: + LMatrix4f _value_no_scale_shear; + LVecBase3f _scale; + LVecBase3f _hpr; + LQuaternionf _quat; + LVecBase3f _pos; + LVecBase3f _shear; + +public: + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + AnimChannelFixed::init_type(); + register_type(_type_handle, "AnimChannelMatrixFixed", + AnimChannelFixed::get_class_type()); + } + +private: + static TypeHandle _type_handle; +}; + +#include "animChannelMatrixFixed.I" + +#endif + + + diff --git a/panda/src/chan/chan_composite1.cxx b/panda/src/chan/chan_composite1.cxx index b88ac72832..411d6c0a9f 100644 --- a/panda/src/chan/chan_composite1.cxx +++ b/panda/src/chan/chan_composite1.cxx @@ -1,11 +1,14 @@ - #include "auto_bind.cxx" -#include "config_chan.cxx" -#include "movingPartBase.cxx" -#include "movingPartMatrix.cxx" -#include "movingPartScalar.cxx" -#include "partBundle.cxx" -#include "partBundleNode.cxx" -#include "partGroup.cxx" -#include "vector_PartGroupStar.cxx" +#include "animBundle.cxx" +#include "animBundleNode.cxx" +#include "animChannel.cxx" +#include "animChannelBase.cxx" +#include "animChannelMatrixDynamic.cxx" +#include "animChannelMatrixFixed.cxx" +#include "animChannelMatrixXfmTable.cxx" +#include "animChannelScalarDynamic.cxx" +#include "animChannelScalarTable.cxx" +#include "animControl.cxx" +#include "animControlCollection.cxx" +#include "animGroup.cxx" diff --git a/panda/src/chan/chan_composite2.cxx b/panda/src/chan/chan_composite2.cxx index fe8dbd1a3a..0b60ba1c72 100644 --- a/panda/src/chan/chan_composite2.cxx +++ b/panda/src/chan/chan_composite2.cxx @@ -1,13 +1,9 @@ - -#include "animBundle.cxx" -#include "animBundleNode.cxx" -#include "animChannel.cxx" -#include "animChannelBase.cxx" -#include "animChannelMatrixDynamic.cxx" -#include "animChannelMatrixXfmTable.cxx" -#include "animChannelScalarDynamic.cxx" -#include "animChannelScalarTable.cxx" -#include "animControl.cxx" -#include "animControlCollection.cxx" -#include "animGroup.cxx" - +#include "config_chan.cxx" +#include "movingPartBase.cxx" +#include "movingPartMatrix.cxx" +#include "movingPartScalar.cxx" +#include "partBundle.cxx" +#include "partBundleNode.cxx" +#include "partGroup.cxx" +#include "partSubset.cxx" +#include "vector_PartGroupStar.cxx" diff --git a/panda/src/chan/config_chan.cxx b/panda/src/chan/config_chan.cxx index 5b04fa23a8..30ae4e0bd0 100644 --- a/panda/src/chan/config_chan.cxx +++ b/panda/src/chan/config_chan.cxx @@ -23,6 +23,7 @@ #include "animChannelBase.h" #include "animChannelMatrixXfmTable.h" #include "animChannelMatrixDynamic.h" +#include "animChannelMatrixFixed.h" #include "animChannelScalarTable.h" #include "animChannelScalarDynamic.h" #include "animControl.h" @@ -89,6 +90,7 @@ ConfigureFn(config_chan) { AnimChannelBase::init_type(); AnimChannelMatrixXfmTable::init_type(); AnimChannelMatrixDynamic::init_type(); + AnimChannelMatrixFixed::init_type(); AnimChannelScalarTable::init_type(); AnimChannelScalarDynamic::init_type(); AnimControl::init_type(); diff --git a/panda/src/chan/movingPartBase.cxx b/panda/src/chan/movingPartBase.cxx index 016b6f2845..f171b571aa 100644 --- a/panda/src/chan/movingPartBase.cxx +++ b/panda/src/chan/movingPartBase.cxx @@ -47,7 +47,7 @@ MovingPartBase(){ //////////////////////////////////////////////////////////////////// // Function: MovingPartBase::write -// Access: Public, Virtual +// Access: Published, Virtual // Description: Writes a brief description of the channel and all of // its descendants. //////////////////////////////////////////////////////////////////// @@ -65,7 +65,7 @@ write(ostream &out, int indent_level) const { //////////////////////////////////////////////////////////////////// // Function: MovingPartBase::write_with_value -// Access: Public, Virtual +// Access: Published, Virtual // Description: Writes a brief description of the channel and all of // its descendants, along with their values. //////////////////////////////////////////////////////////////////// @@ -112,9 +112,9 @@ do_update(PartBundle *root, PartGroup *parent, int channel_index = control->get_channel_index(); nassertr(channel_index >= 0 && channel_index < (int)_channels.size(), false); AnimChannelBase *channel = _channels[channel_index]; - nassertr(channel != (AnimChannelBase*)0L, false); - - needs_update = control->channel_has_changed(channel); + if (channel != (AnimChannelBase*)NULL) { + needs_update = control->channel_has_changed(channel); + } } if (needs_update) { @@ -187,7 +187,7 @@ pick_channel_index(plist &holes, int &next) const { if (next < (int)_channels.size()) { int i; for (i = next; i < (int)_channels.size(); i++) { - if (_channels[i] == (AnimChannelBase*)0L) { + if (_channels[i] == (AnimChannelBase*)NULL) { // Here's a hole we do have. holes.push_back(i); } @@ -207,25 +207,29 @@ pick_channel_index(plist &holes, int &next) const { // hierarchy, at the given channel index number. //////////////////////////////////////////////////////////////////// void MovingPartBase:: -bind_hierarchy(AnimGroup *anim, int channel_index) { +bind_hierarchy(AnimGroup *anim, int channel_index, bool is_included, + const PartSubset &subset) { if (chan_cat.is_debug()) { chan_cat.debug() - << "binding " << *this << " to " << *anim << "\n"; + << "binding " << *this << " to " << *anim << ", is_included = " + << is_included << "\n"; } while ((int)_channels.size() <= channel_index) { - _channels.push_back((AnimChannelBase*)0L); + _channels.push_back((AnimChannelBase*)NULL); } - nassertv(_channels[channel_index] == (AnimChannelBase*)0L); + nassertv(_channels[channel_index] == (AnimChannelBase*)NULL); - if (anim == (AnimGroup*)0L) { - // If we're binding to the NULL anim, it means actually to create - // a default AnimChannel that just returns the part's initial - // value. - _channels[channel_index] = make_initial_channel(); - } else { - _channels[channel_index] = DCAST(AnimChannelBase, anim); + if (is_included) { + if (anim == (AnimGroup*)NULL) { + // If we're binding to the NULL anim, it means actually to create + // a default AnimChannel that just returns the part's initial + // value. + _channels[channel_index] = make_initial_channel(); + } else { + _channels[channel_index] = DCAST(AnimChannelBase, anim); + } } - PartGroup::bind_hierarchy(anim, channel_index); + PartGroup::bind_hierarchy(anim, channel_index, is_included, subset); } diff --git a/panda/src/chan/movingPartBase.h b/panda/src/chan/movingPartBase.h index 32c51b4f25..c8c76a5880 100644 --- a/panda/src/chan/movingPartBase.h +++ b/panda/src/chan/movingPartBase.h @@ -49,10 +49,13 @@ PUBLISHED: public: virtual TypeHandle get_value_type() const=0; virtual AnimChannelBase *make_initial_channel() const=0; + +PUBLISHED: 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; +public: virtual bool do_update(PartBundle *root, PartGroup *parent, bool parent_changed, bool anim_changed); @@ -64,7 +67,8 @@ protected: MovingPartBase(); virtual void pick_channel_index(plist &holes, int &next) const; - virtual void bind_hierarchy(AnimGroup *anim, int channel_index); + virtual void bind_hierarchy(AnimGroup *anim, int channel_index, + bool is_included, const PartSubset &subset); typedef pvector< PT(AnimChannelBase) > Channels; Channels _channels; diff --git a/panda/src/chan/movingPartMatrix.cxx b/panda/src/chan/movingPartMatrix.cxx index 1656794eaa..bf6bfc161e 100644 --- a/panda/src/chan/movingPartMatrix.cxx +++ b/panda/src/chan/movingPartMatrix.cxx @@ -41,6 +41,19 @@ MovingPartMatrix:: ~MovingPartMatrix() { } + +//////////////////////////////////////////////////////////////////// +// Function: MovingPartMatrix::make_initial_channel +// Access: Public, Virtual +// Description: Creates and returns a new AnimChannel that is not +// part of any hierarchy, but that returns the default +// value associated with this part. +//////////////////////////////////////////////////////////////////// +AnimChannelBase *MovingPartMatrix:: +make_initial_channel() const { + return new AnimChannelMatrixFixed(get_name(), _initial_value); +} + //////////////////////////////////////////////////////////////////// // Function: MovingPartMatrix::get_blend_value // Access: Public @@ -63,9 +76,13 @@ get_blend_value(const PartBundle *root) { int channel_index = control->get_channel_index(); nassertv(channel_index >= 0 && channel_index < (int)_channels.size()); ChannelType *channel = DCAST(ChannelType, _channels[channel_index]); - nassertv(channel != NULL); + if (channel == (ChannelType *)NULL) { + // Nothing is actually bound here. + _value = _initial_value; - channel->get_value(control->get_frame(), _value); + } else { + channel->get_value(control->get_frame(), _value); + } } else { // A blend of two or more values. @@ -90,17 +107,20 @@ get_blend_value(const PartBundle *root) { int channel_index = control->get_channel_index(); nassertv(channel_index >= 0 && channel_index < (int)_channels.size()); ChannelType *channel = DCAST(ChannelType, _channels[channel_index]); - nassertv(channel != NULL); - - ValueType v; - channel->get_value(control->get_frame(), v); - - _value += v * effect; - net += effect; + if (channel != (ChannelType *)NULL) { + ValueType v; + channel->get_value(control->get_frame(), v); + + _value += v * effect; + net += effect; + } } - nassertv(net != 0.0f); - _value /= net; + if (net == 0.0f) { + _value = _initial_value; + } else { + _value /= net; + } } break; @@ -126,30 +146,34 @@ get_blend_value(const PartBundle *root) { int channel_index = control->get_channel_index(); nassertv(channel_index >= 0 && channel_index < (int)_channels.size()); ChannelType *channel = DCAST(ChannelType, _channels[channel_index]); - nassertv(channel != NULL); - - ValueType v; - channel->get_value_no_scale_shear(control->get_frame(), v); - LVecBase3f iscale, ishear; - channel->get_scale(control->get_frame(), iscale); - channel->get_shear(control->get_frame(), ishear); - - _value += v * effect; - scale += iscale * effect; - shear += ishear * effect; - net += effect; + if (channel != (ChannelType *)NULL) { + ValueType v; + channel->get_value_no_scale_shear(control->get_frame(), v); + LVecBase3f iscale, ishear; + channel->get_scale(control->get_frame(), iscale); + channel->get_shear(control->get_frame(), ishear); + + _value += v * effect; + scale += iscale * effect; + shear += ishear * effect; + net += effect; + } } - nassertv(net != 0.0f); - _value /= net; - scale /= net; - shear /= net; - - // Now rebuild the matrix with the correct scale values. - - LVector3f false_scale, false_shear, hpr, translate; - decompose_matrix(_value, false_scale, false_shear, hpr, translate); - compose_matrix(_value, scale, shear, hpr, translate); + if (net == 0.0f) { + _value = _initial_value; + + } else { + _value /= net; + scale /= net; + shear /= net; + + // Now rebuild the matrix with the correct scale values. + + LVector3f false_scale, false_shear, hpr, translate; + decompose_matrix(_value, false_scale, false_shear, hpr, translate); + compose_matrix(_value, scale, shear, hpr, translate); + } } break; @@ -171,28 +195,32 @@ get_blend_value(const PartBundle *root) { int channel_index = control->get_channel_index(); nassertv(channel_index >= 0 && channel_index < (int)_channels.size()); ChannelType *channel = DCAST(ChannelType, _channels[channel_index]); - nassertv(channel != NULL); - - LVecBase3f iscale, ihpr, ipos, ishear; - channel->get_scale(control->get_frame(), iscale); - channel->get_hpr(control->get_frame(), ihpr); - channel->get_pos(control->get_frame(), ipos); - channel->get_shear(control->get_frame(), ishear); - - scale += iscale * effect; - hpr += ihpr * effect; - pos += ipos * effect; - shear += ishear * effect; - net += effect; + if (channel != (ChannelType *)NULL) { + LVecBase3f iscale, ihpr, ipos, ishear; + channel->get_scale(control->get_frame(), iscale); + channel->get_hpr(control->get_frame(), ihpr); + channel->get_pos(control->get_frame(), ipos); + channel->get_shear(control->get_frame(), ishear); + + scale += iscale * effect; + hpr += ihpr * effect; + pos += ipos * effect; + shear += ishear * effect; + net += effect; + } } - nassertv(net != 0.0f); - scale /= net; - hpr /= net; - pos /= net; - shear /= net; - - compose_matrix(_value, scale, shear, hpr, pos); + if (net == 0.0f) { + _value = _initial_value; + + } else { + scale /= net; + hpr /= net; + pos /= net; + shear /= net; + + compose_matrix(_value, scale, shear, hpr, pos); + } } break; @@ -215,34 +243,38 @@ get_blend_value(const PartBundle *root) { int channel_index = control->get_channel_index(); nassertv(channel_index >= 0 && channel_index < (int)_channels.size()); ChannelType *channel = DCAST(ChannelType, _channels[channel_index]); - nassertv(channel != NULL); - - LVecBase3f iscale, ipos, ishear; - LQuaternionf iquat; - channel->get_scale(control->get_frame(), iscale); - channel->get_quat(control->get_frame(), iquat); - channel->get_pos(control->get_frame(), ipos); - channel->get_shear(control->get_frame(), ishear); - - scale += iscale * effect; - quat += iquat * effect; - pos += ipos * effect; - shear += ishear * effect; - net += effect; + if (channel != (ChannelType *)NULL) { + LVecBase3f iscale, ipos, ishear; + LQuaternionf iquat; + channel->get_scale(control->get_frame(), iscale); + channel->get_quat(control->get_frame(), iquat); + channel->get_pos(control->get_frame(), ipos); + channel->get_shear(control->get_frame(), ishear); + + scale += iscale * effect; + quat += iquat * effect; + pos += ipos * effect; + shear += ishear * effect; + net += effect; + } } - nassertv(net != 0.0f); - scale /= net; - quat /= net; - pos /= net; - shear /= net; + if (net == 0.0f) { + _value = _initial_value; - // There should be no need to normalize the quaternion, - // assuming all of the input quaternions were already - // normalized. - - _value = LMatrix4f::scale_shear_mat(scale, shear) * quat; - _value.set_row(3, pos); + } else { + scale /= net; + quat /= net; + pos /= net; + shear /= net; + + // There should be no need to normalize the quaternion, + // assuming all of the input quaternions were already + // normalized. + + _value = LMatrix4f::scale_shear_mat(scale, shear) * quat; + _value.set_row(3, pos); + } } break; } diff --git a/panda/src/chan/movingPartMatrix.h b/panda/src/chan/movingPartMatrix.h index b60897bff5..3721a103b8 100644 --- a/panda/src/chan/movingPartMatrix.h +++ b/panda/src/chan/movingPartMatrix.h @@ -43,6 +43,7 @@ public: LMatrix4f::ident_mat()); virtual ~MovingPartMatrix(); + virtual AnimChannelBase *make_initial_channel() const; virtual void get_blend_value(const PartBundle *root); protected: diff --git a/panda/src/chan/movingPartScalar.cxx b/panda/src/chan/movingPartScalar.cxx index f0b713196d..abccd4a047 100644 --- a/panda/src/chan/movingPartScalar.cxx +++ b/panda/src/chan/movingPartScalar.cxx @@ -61,9 +61,13 @@ get_blend_value(const PartBundle *root) { int channel_index = control->get_channel_index(); nassertv(channel_index >= 0 && channel_index < (int)_channels.size()); ChannelType *channel = DCAST(ChannelType, _channels[channel_index]); - nassertv(channel != NULL); + if (channel == NULL) { + // Nothing is actually bound here. + _value = _initial_value; - channel->get_value(control->get_frame(), _value); + } else { + channel->get_value(control->get_frame(), _value); + } } else { // A blend of two or more values. @@ -79,17 +83,21 @@ get_blend_value(const PartBundle *root) { int channel_index = control->get_channel_index(); nassertv(channel_index >= 0 && channel_index < (int)_channels.size()); ChannelType *channel = DCAST(ChannelType, _channels[channel_index]); - nassertv(channel != NULL); - - ValueType v; - channel->get_value(control->get_frame(), v); - - _value += v * effect; - net += effect; + if (channel != NULL) { + ValueType v; + channel->get_value(control->get_frame(), v); + + _value += v * effect; + net += effect; + } } - nassertv(net != 0.0f); - _value /= net; + if (net == 0.0f) { + _value = _initial_value; + + } else { + _value /= net; + } } } diff --git a/panda/src/chan/partBundle.cxx b/panda/src/chan/partBundle.cxx index fccc616705..bce962adf4 100644 --- a/panda/src/chan/partBundle.cxx +++ b/panda/src/chan/partBundle.cxx @@ -43,8 +43,6 @@ PartBundle(const PartBundle ©) : PartGroup(copy), _blend_type(copy._blend_type) { - // We don't invoke the AnimControlCollection's copy, or any of the - // bound animations. _last_control_set = NULL; _net_blend = 0.0f; _anim_changed = false; @@ -250,16 +248,18 @@ write(ostream &out, int indent_level) const { // conditions that will be tolerated (but warnings will // still be issued). // -// This flavor of bind_anim() does not associate a name -// with the channel, and the AnimControl is not stored -// within the PartBundle; it is the user's -// responsibility to maintain the pointer. The -// animation will automatically unbind itself when the -// AnimControl destructs (i.e. its reference count goes -// to zero). +// If subset is specified, it restricts the binding only +// to the named subtree of joints. +// +// The AnimControl is not stored within the PartBundle; +// it is the user's responsibility to maintain the +// pointer. The animation will automatically unbind +// itself when the AnimControl destructs (i.e. its +// reference count goes to zero). //////////////////////////////////////////////////////////////////// PT(AnimControl) PartBundle:: -bind_anim(AnimBundle *anim, int hierarchy_match_flags) { +bind_anim(AnimBundle *anim, int hierarchy_match_flags, + const PartSubset &subset) { if ((hierarchy_match_flags & HMF_ok_wrong_root_name) == 0) { // Make sure the root names match. if (get_name() != anim->get_name()) { @@ -285,47 +285,10 @@ bind_anim(AnimBundle *anim, int hierarchy_match_flags) { channel_index = holes.front(); } - bind_hierarchy(anim, channel_index); + bind_hierarchy(anim, channel_index, subset.is_empty(), subset); return new AnimControl(this, anim, channel_index); } -//////////////////////////////////////////////////////////////////// -// Function: PartBundle::bind_anim -// Access: Published -// Description: Binds the animation to the bundle, if possible, and -// returns a new AnimControl that can be used to start -// and stop the animation. If the anim hierarchy does -// not match the part hierarchy, returns NULL. -// -// If hierarchy_match_flags is 0, only an exact match is -// accepted; otherwise, it may contain a union of -// PartGroup::HierarchyMatchFlags values indicating -// conditions that will be tolerated (but warnings will -// still be issued). -// -// This flavor of bind_anim() automatically stores the -// bound AnimControl in the PartBundle with the -// indicated name, so that it may later be referenced by -// name. This means that the animation will not be -// unbound until another animation with the same name is -// bound, or it is explicitly unbound with -// unbind_anim(). -// -// The return value is true if the animation was -// successfully bound, false if there was some error. -//////////////////////////////////////////////////////////////////// -bool PartBundle:: -bind_anim(AnimBundle *anim, const string &name, - int hierarchy_match_flags) { - PT(AnimControl) control = bind_anim(anim, hierarchy_match_flags); - if (control == (AnimControl *)NULL) { - return false; - } - - store_anim(control, name); - return true; -} - //////////////////////////////////////////////////////////////////// // Function: PartBundle::update // Access: Public diff --git a/panda/src/chan/partBundle.h b/panda/src/chan/partBundle.h index 6e51356216..1ef67878fc 100644 --- a/panda/src/chan/partBundle.h +++ b/panda/src/chan/partBundle.h @@ -23,8 +23,7 @@ #include "partGroup.h" #include "animControl.h" -#include "animControlCollection.h" - +#include "partSubset.h" #include "pointerTo.h" #include "iterator_types.h" @@ -38,7 +37,7 @@ class PartBundleNode; // defines the hierarchy of moving parts that make up an // animatable object. //////////////////////////////////////////////////////////////////// -class EXPCL_PANDA PartBundle : public PartGroup, public AnimControlCollection { +class EXPCL_PANDA PartBundle : public PartGroup { public: // This is passed down through the MovingParts during the @@ -113,10 +112,8 @@ PUBLISHED: virtual void write(ostream &out, int indent_level) const; PT(AnimControl) bind_anim(AnimBundle *anim, - int hierarchy_match_flags = 0); - - bool bind_anim(AnimBundle *anim, const string &name, - int hierarchy_match_flags = 0); + int hierarchy_match_flags = 0, + const PartSubset &subset = PartSubset()); public: // The following functions may be used to traverse the set of diff --git a/panda/src/chan/partGroup.cxx b/panda/src/chan/partGroup.cxx index 649743236e..eb5e75933f 100644 --- a/panda/src/chan/partGroup.cxx +++ b/panda/src/chan/partGroup.cxx @@ -16,10 +16,10 @@ // //////////////////////////////////////////////////////////////////// - #include "partGroup.h" #include "animGroup.h" #include "config_chan.h" +#include "partSubset.h" #include "indent.h" #include "datagram.h" @@ -432,7 +432,14 @@ pick_channel_index(plist &holes, int &next) const { // hierarchy, at the given channel index number. //////////////////////////////////////////////////////////////////// void PartGroup:: -bind_hierarchy(AnimGroup *anim, int channel_index) { +bind_hierarchy(AnimGroup *anim, int channel_index, bool is_included, + const PartSubset &subset) { + if (subset.matches_include(get_name())) { + is_included = true; + } else if (subset.matches_exclude(get_name())) { + is_included = false; + } + int i = 0, j = 0; int part_num_children = get_num_children(); int anim_num_children = (anim == NULL) ? 0 : anim->get_num_children(); @@ -444,12 +451,12 @@ bind_hierarchy(AnimGroup *anim, int channel_index) { if (pc->get_name() < ac->get_name()) { // Here's a part, not in the anim. Bind it to the special NULL // anim. - pc->bind_hierarchy(NULL, channel_index); + pc->bind_hierarchy(NULL, channel_index, is_included, subset); i++; } else if (ac->get_name() < pc->get_name()) { j++; } else { - pc->bind_hierarchy(ac, channel_index); + pc->bind_hierarchy(ac, channel_index, is_included, subset); i++; j++; } @@ -458,7 +465,7 @@ bind_hierarchy(AnimGroup *anim, int channel_index) { // Now pick up any more parts, not in the anim. while (i < part_num_children) { PartGroup *pc = get_child(i); - pc->bind_hierarchy(NULL, channel_index); + pc->bind_hierarchy(NULL, channel_index, is_included, subset); i++; } } diff --git a/panda/src/chan/partGroup.h b/panda/src/chan/partGroup.h index ed791137df..3ed0fd3c76 100644 --- a/panda/src/chan/partGroup.h +++ b/panda/src/chan/partGroup.h @@ -31,6 +31,7 @@ class AnimControl; class AnimGroup; class PartBundle; +class PartSubset; class BamReader; class FactoryParams; @@ -91,7 +92,8 @@ protected: void write_descendants_with_value(ostream &out, int indent_level) const; virtual void pick_channel_index(plist &holes, int &next) const; - virtual void bind_hierarchy(AnimGroup *anim, int channel_index); + virtual void bind_hierarchy(AnimGroup *anim, int channel_index, + bool is_included, const PartSubset &subset); typedef pvector< PT(PartGroup) > Children; Children _children; diff --git a/panda/src/chan/partSubset.I b/panda/src/chan/partSubset.I new file mode 100644 index 0000000000..0bb2868cc3 --- /dev/null +++ b/panda/src/chan/partSubset.I @@ -0,0 +1,18 @@ +// Filename: partSubset.I +// Created by: drose (19Jan06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + diff --git a/panda/src/chan/partSubset.cxx b/panda/src/chan/partSubset.cxx new file mode 100644 index 0000000000..e020e1973b --- /dev/null +++ b/panda/src/chan/partSubset.cxx @@ -0,0 +1,178 @@ +// Filename: partSubset.cxx +// Created by: drose (19Jan06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "partSubset.h" + +//////////////////////////////////////////////////////////////////// +// Function: PartSubset::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +PartSubset:: +PartSubset() { +} + +//////////////////////////////////////////////////////////////////// +// Function: PartSubset::Copy Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +PartSubset:: +PartSubset(const PartSubset ©) : + _include_joints(copy._include_joints), + _exclude_joints(copy._exclude_joints) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: PartSubset::Copy Assignment Operator +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void PartSubset:: +operator = (const PartSubset ©) { + _include_joints = copy._include_joints; + _exclude_joints = copy._exclude_joints; +} + +//////////////////////////////////////////////////////////////////// +// Function: PartSubset::add_include_joint +// Access: Published +// Description: Adds the named joint to the list of joints that will +// be explicitly included in the subset. Any joint at +// or below a named node will be included in the subset +// (unless a lower node is also listed in the exclude +// list). +// +// Since the name is a GlobPattern, it may of course +// include filename globbing characters like * and ?. +//////////////////////////////////////////////////////////////////// +void PartSubset:: +add_include_joint(const GlobPattern &name) { + _include_joints.push_back(name); +} + +//////////////////////////////////////////////////////////////////// +// Function: PartSubset::add_exclude_joint +// Access: Published +// Description: Adds the named joint to the list of joints that will +// be explicitly exlcluded from the subset. Any joint at +// or below a named node will not be included in the +// subset (unless a lower node is also listed in the +// include list). +// +// Since the name is a GlobPattern, it may of course +// include filename globbing characters like * and ?. +//////////////////////////////////////////////////////////////////// +void PartSubset:: +add_exclude_joint(const GlobPattern &name) { + _exclude_joints.push_back(name); +} + +//////////////////////////////////////////////////////////////////// +// Function: PartSubset::append +// Access: Published +// Description: Appends the include and exclude list from the other +// object onto this object's lists. +//////////////////////////////////////////////////////////////////// +void PartSubset:: +append(const PartSubset &other) { + Joints::const_iterator ji; + for (ji = other._include_joints.begin(); + ji != other._include_joints.end(); + ++ji) { + _include_joints.push_back(*ji); + } + for (ji = other._exclude_joints.begin(); + ji != other._exclude_joints.end(); + ++ji) { + _exclude_joints.push_back(*ji); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: PartSubset::output +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void PartSubset:: +output(ostream &out) const { + if (_include_joints.empty() && _exclude_joints.empty()) { + out << "PartSubset, empty"; + } else { + out << "PartSubset, include: ["; + Joints::const_iterator ji; + for (ji = _include_joints.begin(); ji != _include_joints.end(); ++ji) { + out << " " << (*ji); + } + out << " ], exclude: ["; + for (ji = _exclude_joints.begin(); ji != _exclude_joints.end(); ++ji) { + out << " " << (*ji); + } + out << " ]"; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: PartSubset::is_empty +// Access: Published +// Description: Returns true if the PartSubset is completely empty, +// false otherwise. If it is empty, it is the same +// thing as including all joints. +//////////////////////////////////////////////////////////////////// +bool PartSubset:: +is_empty() const { + return _include_joints.empty() && _exclude_joints.empty(); +} + +//////////////////////////////////////////////////////////////////// +// Function: PartSubset::matches_include +// Access: Published +// Description: Returns true if the indicated name matches a name on +// the include list, false otherwise. +//////////////////////////////////////////////////////////////////// +bool PartSubset:: +matches_include(const string &joint_name) const { + Joints::const_iterator ji; + for (ji = _include_joints.begin(); ji != _include_joints.end(); ++ji) { + if ((*ji).matches(joint_name)) { + return true; + } + } + + return false; +} + + +//////////////////////////////////////////////////////////////////// +// Function: PartSubset::matches_exclude +// Access: Published +// Description: Returns true if the indicated name matches a name on +// the exclude list, false otherwise. +//////////////////////////////////////////////////////////////////// +bool PartSubset:: +matches_exclude(const string &joint_name) const { + Joints::const_iterator ji; + for (ji = _exclude_joints.begin(); ji != _exclude_joints.end(); ++ji) { + if ((*ji).matches(joint_name)) { + return true; + } + } + + return false; +} diff --git a/panda/src/chan/partSubset.h b/panda/src/chan/partSubset.h new file mode 100644 index 0000000000..3bf9767fc3 --- /dev/null +++ b/panda/src/chan/partSubset.h @@ -0,0 +1,63 @@ +// Filename: partSubset.h +// Created by: drose (19Jan06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef PARTSUBSET_H +#define PARTSUBSET_H + +#include "pandabase.h" +#include "globPattern.h" + +//////////////////////////////////////////////////////////////////// +// Class : PartSubset +// Description : This class is used to define a subset of part names +// to apply to the PartBundle::bind_anim() operation. +// Only those part names within the subset will be +// included in the bind. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA PartSubset { +PUBLISHED: + PartSubset(); + PartSubset(const PartSubset ©); + void operator = (const PartSubset ©); + + void add_include_joint(const GlobPattern &name); + void add_exclude_joint(const GlobPattern &name); + + void append(const PartSubset &other); + + void output(ostream &out) const; + + bool is_empty() const; + bool matches_include(const string &joint_name) const; + bool matches_exclude(const string &joint_name) const; + +private: + typedef pvector Joints; + Joints _include_joints; + Joints _exclude_joints; +}; + +INLINE ostream &operator << (ostream &out, const PartSubset &subset) { + subset.output(out); + return out; +} + +#include "partSubset.I" + +#endif +