Panda3D

partGroup.cxx

00001 // Filename: partGroup.cxx
00002 // Created by:  drose (22Feb99)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "partGroup.h"
00016 #include "animGroup.h"
00017 #include "config_chan.h"
00018 #include "partSubset.h"
00019 
00020 #include "indent.h"
00021 #include "datagram.h"
00022 #include "datagramIterator.h"
00023 #include "bamReader.h"
00024 #include "bamWriter.h"
00025 
00026 #include <algorithm>
00027 
00028 TypeHandle PartGroup::_type_handle;
00029 
00030 ////////////////////////////////////////////////////////////////////
00031 //     Function: PartGroup::Constructor
00032 //       Access: Published
00033 //  Description: Creates the PartGroup, and adds it to the indicated
00034 //               parent.  The only way to delete it subsequently is to
00035 //               delete the entire hierarchy.
00036 ////////////////////////////////////////////////////////////////////
00037 PartGroup::
00038 PartGroup(PartGroup *parent, const string &name) : 
00039   Namable(name),
00040   _children(get_class_type())
00041 {
00042   nassertv(parent != NULL);
00043   
00044   parent->_children.push_back(this);
00045 }
00046 
00047 ////////////////////////////////////////////////////////////////////
00048 //     Function: PartGroup::Destructor
00049 //       Access: Published
00050 //  Description:
00051 ////////////////////////////////////////////////////////////////////
00052 PartGroup::
00053 ~PartGroup() {
00054 }
00055 
00056 ////////////////////////////////////////////////////////////////////
00057 //     Function: PartGroup::is_character_joint
00058 //       Access: Published, Virtual
00059 //  Description: Returns true if this part is a CharacterJoint, false
00060 //               otherwise.  This is a tiny optimization over
00061 //               is_of_type(CharacterType::get_class_type()).
00062 ////////////////////////////////////////////////////////////////////
00063 bool PartGroup::
00064 is_character_joint() const {
00065   return false;
00066 }
00067 
00068 ////////////////////////////////////////////////////////////////////
00069 //     Function: PartGroup::make_copy
00070 //       Access: Published, Virtual
00071 //  Description: Allocates and returns a new copy of the node.
00072 //               Children are not copied, but see copy_subgraph().
00073 ////////////////////////////////////////////////////////////////////
00074 PartGroup *PartGroup::
00075 make_copy() const {
00076   return new PartGroup(*this);
00077 }
00078 
00079 ////////////////////////////////////////////////////////////////////
00080 //     Function: PartGroup::copy_subgraph
00081 //       Access: Published
00082 //  Description: Allocates and returns a new copy of this node and of
00083 //               all of its children.
00084 ////////////////////////////////////////////////////////////////////
00085 PartGroup *PartGroup::
00086 copy_subgraph() const {
00087   PartGroup *root = make_copy();
00088 
00089   if (root->get_type() != get_type()) {
00090     chan_cat.warning()
00091       << "Don't know how to copy " << get_type() << "\n";
00092   }
00093 
00094   Children::const_iterator ci;
00095   for (ci = _children.begin(); ci != _children.end(); ++ci) {
00096     PartGroup *child = (*ci)->copy_subgraph();
00097     root->_children.push_back(child);
00098   }
00099 
00100   return root;
00101 }
00102 
00103 
00104 ////////////////////////////////////////////////////////////////////
00105 //     Function: PartGroup::get_num_children
00106 //       Access: Published
00107 //  Description: Returns the number of child nodes of the group.
00108 ////////////////////////////////////////////////////////////////////
00109 int PartGroup::
00110 get_num_children() const {
00111   return _children.size();
00112 }
00113 
00114 
00115 ////////////////////////////////////////////////////////////////////
00116 //     Function: PartGroup::get_child
00117 //       Access: Published
00118 //  Description: Returns the nth child of the group.
00119 ////////////////////////////////////////////////////////////////////
00120 PartGroup *PartGroup::
00121 get_child(int n) const {
00122   nassertr(n >= 0 && n < (int)_children.size(), NULL);
00123   return _children[n];
00124 }
00125 
00126 ////////////////////////////////////////////////////////////////////
00127 //     Function: PartGroup::get_child_named
00128 //       Access: Published
00129 //  Description: Returns the first child found with the indicated
00130 //               name, or NULL if no such child exists.  This method
00131 //               searches only the children of this particular
00132 //               PartGroup; it does not recursively search the entire
00133 //               graph.  See also find_child().
00134 ////////////////////////////////////////////////////////////////////
00135 PartGroup *PartGroup::
00136 get_child_named(const string &name) const {
00137   Children::const_iterator ci;
00138   for (ci = _children.begin(); ci != _children.end(); ++ci) {
00139     PartGroup *child = (*ci);
00140     if (child->get_name() == name) {
00141       return child;
00142     }
00143   }
00144 
00145   return (PartGroup *)NULL;
00146 }
00147 
00148 ////////////////////////////////////////////////////////////////////
00149 //     Function: PartGroup::find_child
00150 //       Access: Published
00151 //  Description: Returns the first descendant found with the indicated
00152 //               name, or NULL if no such descendant exists.  This
00153 //               method searches the entire graph beginning at this
00154 //               PartGroup; see also get_child_named().
00155 ////////////////////////////////////////////////////////////////////
00156 PartGroup *PartGroup::
00157 find_child(const string &name) const {
00158   Children::const_iterator ci;
00159   for (ci = _children.begin(); ci != _children.end(); ++ci) {
00160     PartGroup *child = (*ci);
00161     if (child->get_name() == name) {
00162       return child;
00163     }
00164     PartGroup *result = child->find_child(name);
00165     if (result != (PartGroup *)NULL) {
00166       return result;
00167     }
00168   }
00169 
00170   return (PartGroup *)NULL;
00171 }
00172 
00173 // An STL object to sort a list of children into alphabetical order.
00174 class PartGroupAlphabeticalOrder {
00175 public:
00176   bool operator()(const PT(PartGroup) &a, const PT(PartGroup) &b) const {
00177     return a->get_name() < b->get_name();
00178   }
00179 };
00180 
00181 ////////////////////////////////////////////////////////////////////
00182 //     Function: PartGroup::sort_descendants
00183 //       Access: Published
00184 //  Description: Sorts the children nodes at each level of the
00185 //               hierarchy into alphabetical order.  This should be
00186 //               done after creating the hierarchy, to guarantee that
00187 //               the correct names will match up together when the
00188 //               AnimBundle is later bound to a PlayerRoot.
00189 ////////////////////////////////////////////////////////////////////
00190 void PartGroup::
00191 sort_descendants() {
00192   stable_sort(_children.begin(), _children.end(), PartGroupAlphabeticalOrder());
00193 
00194   Children::iterator ci;
00195   for (ci = _children.begin(); ci != _children.end(); ++ci) {
00196     (*ci)->sort_descendants();
00197   }
00198 }
00199 
00200 ////////////////////////////////////////////////////////////////////
00201 //     Function: PartGroup::apply_freeze
00202 //       Access: Published
00203 //  Description: Freezes this particular joint so that it will always
00204 //               hold the specified transform.  Returns true if this
00205 //               is a joint that can be so frozen, false otherwise.
00206 //
00207 //               This is normally only called internally by
00208 //               PartBundle::freeze_joint(), but you may also call it
00209 //               directly.
00210 ////////////////////////////////////////////////////////////////////
00211 bool PartGroup::
00212 apply_freeze(const TransformState *transform) {
00213   return apply_freeze_matrix(transform->get_pos(), transform->get_hpr(), transform->get_scale()) || apply_freeze_scalar(transform->get_pos()[0]);
00214 }
00215 
00216 ////////////////////////////////////////////////////////////////////
00217 //     Function: PartGroup::apply_freeze_matrix
00218 //       Access: Published, Virtual
00219 //  Description: Freezes this particular joint so that it will always
00220 //               hold the specified transform.  Returns true if this
00221 //               is a joint that can be so frozen, false otherwise.
00222 //
00223 //               This is normally only called internally by
00224 //               PartBundle::freeze_joint(), but you may also call it
00225 //               directly.
00226 ////////////////////////////////////////////////////////////////////
00227 bool PartGroup::
00228 apply_freeze_matrix(const LVecBase3 &pos, const LVecBase3 &hpr, const LVecBase3 &scale) {
00229   return false;
00230 }
00231 
00232 ////////////////////////////////////////////////////////////////////
00233 //     Function: PartGroup::apply_freeze_scalar
00234 //       Access: Published, Virtual
00235 //  Description: Freezes this particular joint so that it will always
00236 //               hold the specified transform.  Returns true if this
00237 //               is a joint that can be so frozen, false otherwise.
00238 //
00239 //               This is normally only called internally by
00240 //               PartBundle::freeze_joint(), but you may also call it
00241 //               directly.
00242 ////////////////////////////////////////////////////////////////////
00243 bool PartGroup::
00244 apply_freeze_scalar(PN_stdfloat value) {
00245   return false;
00246 }
00247 
00248 
00249 ////////////////////////////////////////////////////////////////////
00250 //     Function: PartGroup::apply_control
00251 //       Access: Published, Virtual
00252 //  Description: Specifies a node to influence this particular joint
00253 //               so that it will always hold the node's transform.
00254 //               Returns true if this is a joint that can be so
00255 //               controlled, false otherwise.
00256 //
00257 //               This is normally only called internally by
00258 //               PartBundle::control_joint(), but you may also call it
00259 //               directly.
00260 ////////////////////////////////////////////////////////////////////
00261 bool PartGroup::
00262 apply_control(PandaNode *node) {
00263   return false;
00264 }
00265 
00266 ////////////////////////////////////////////////////////////////////
00267 //     Function: PartGroup::clear_forced_channel
00268 //       Access: Published, Virtual
00269 //  Description: Undoes the effect of a previous call to
00270 //               apply_freeze() or apply_control().  Returns true if
00271 //               the joint was modified, false otherwise.
00272 //
00273 //               This is normally only called internally by
00274 //               PartBundle::release_joint(), but you may also call it
00275 //               directly.
00276 ////////////////////////////////////////////////////////////////////
00277 bool PartGroup::
00278 clear_forced_channel() {
00279   return false;
00280 }
00281 
00282 ////////////////////////////////////////////////////////////////////
00283 //     Function: PartGroup::get_forced_channel
00284 //       Access: Published, Virtual
00285 //  Description: Returns the AnimChannelBase that has been forced to
00286 //               this joint by a previous call to apply_freeze() or
00287 //               apply_control(), or NULL if no such channel has been
00288 //               applied.
00289 ////////////////////////////////////////////////////////////////////
00290 AnimChannelBase *PartGroup::
00291 get_forced_channel() const {
00292   return NULL;
00293 }
00294 
00295 
00296 ////////////////////////////////////////////////////////////////////
00297 //     Function: PartGroup::write
00298 //       Access: Published, Virtual
00299 //  Description: Writes a brief description of the group and all of
00300 //               its descendants.
00301 ////////////////////////////////////////////////////////////////////
00302 void PartGroup::
00303 write(ostream &out, int indent_level) const {
00304   indent(out, indent_level)
00305     << get_type() << " " << get_name() << " {\n";
00306   write_descendants(out, indent_level + 2);
00307   indent(out, indent_level) << "}\n";
00308 }
00309 
00310 ////////////////////////////////////////////////////////////////////
00311 //     Function: PartGroup::write_with_value
00312 //       Access: Published, Virtual
00313 //  Description: Writes a brief description of the group, showing its
00314 //               current value, and that of all of its descendants.
00315 ////////////////////////////////////////////////////////////////////
00316 void PartGroup::
00317 write_with_value(ostream &out, int indent_level) const {
00318   indent(out, indent_level)
00319     << get_type() << " " << get_name() << " {\n";
00320   write_descendants_with_value(out, indent_level + 2);
00321   indent(out, indent_level) << "}\n";
00322 }
00323 
00324 ////////////////////////////////////////////////////////////////////
00325 //     Function: PartGroup::get_value_type
00326 //       Access: Public, Virtual
00327 //  Description: Returns the TypeHandle associated with the ValueType
00328 //               we are concerned with.  This is provided to allow a
00329 //               bit of run-time checking that joints and channels are
00330 //               matching properly in type.
00331 ////////////////////////////////////////////////////////////////////
00332 TypeHandle PartGroup::
00333 get_value_type() const {
00334   return TypeHandle::none();
00335 }
00336 
00337 ////////////////////////////////////////////////////////////////////
00338 //     Function: PartGroup::check_hierarchy
00339 //       Access: Public
00340 //  Description: Walks the part hierarchy in tandem with the indicated
00341 //               anim hierarchy, and returns true if the hierarchies
00342 //               match, false otherwise.
00343 //
00344 //               If hierarchy_match_flags is 0, only an exact match is
00345 //               accepted; otherwise, it may contain a union of
00346 //               PartGroup::HierarchyMatchFlags values indicating
00347 //               conditions that will be tolerated (but warnings will
00348 //               still be issued).
00349 ////////////////////////////////////////////////////////////////////
00350 bool PartGroup::
00351 check_hierarchy(const AnimGroup *anim, const PartGroup *,
00352                 int hierarchy_match_flags) const {
00353   Thread::consider_yield();
00354   if (anim->get_value_type() != get_value_type()) {
00355     if (chan_cat.is_error()) {
00356       chan_cat.error()
00357         << "Part " << get_name() << " expects type " << get_value_type()
00358         << " while matching anim node has type " << anim->get_value_type()
00359         << ".\n";
00360     }
00361     return false;
00362   }
00363 
00364   if (chan_cat.is_info()) {
00365     // If we're issuing error messages, check ahead of time if the set
00366     // of children agrees.  If it does not, we'll write a one-line
00367     // warning, and then list the set of children that differ.
00368 
00369     bool match = true;
00370     if (anim->get_num_children() != get_num_children()) {
00371       // If the only difference is "morph", ignore it.  We treat
00372       // "morph" as a special case, because it's common for the model
00373       // and animation files to differ meaninglessly here.  Any
00374       // differences here remain unreported.
00375       if (anim->get_num_children() == get_num_children() + 1 &&
00376           anim->get_child_named("morph") != NULL &&
00377           get_child_named("morph") == NULL) {
00378         // Anim has "morph" and model does not, but there are no other
00379         // differences.
00380 
00381       } else if (get_num_children() == anim->get_num_children() + 1 &&
00382                  get_child_named("morph") != NULL &&
00383                  anim->get_child_named("morph") == NULL) {
00384         // Model has "morph" and anim does not, but there are no other
00385         // differences.
00386 
00387       } else {
00388         chan_cat.info()
00389           << "Part " << get_name() << " has " << get_num_children()
00390           << " children, while matching anim node has "
00391           << anim->get_num_children() << ":\n";
00392         match = false;
00393       }
00394 
00395     } else {
00396       for (int i = 0; match && i < get_num_children(); i++) {
00397         PartGroup *pc = get_child(i);
00398         AnimGroup *ac = anim->get_child(i);
00399 
00400         match = (pc->get_name() == ac->get_name());
00401       }
00402       if (!match) {
00403         chan_cat.info()
00404           << "Part " << get_name() << " has a different set of children "
00405           << " than matching anim node:\n";
00406       }
00407     }
00408     if (!match) {
00409       int i = 0, j = 0;
00410       while (i < get_num_children() &&
00411              j < anim->get_num_children()) {
00412         PartGroup *pc = get_child(i);
00413         AnimGroup *ac = anim->get_child(j);
00414 
00415         if (pc->get_name() < ac->get_name()) {
00416           chan_cat.info()
00417             << "  part has " << pc->get_name()
00418             << ", not in anim.\n";
00419           i++;
00420         } else if (ac->get_name() < pc->get_name()) {
00421           chan_cat.info()
00422             << "  anim has " << ac->get_name()
00423             << ", not in part.\n";
00424           j++;
00425         } else {
00426           //      chan_cat.info() << "  part and anim both have " << ac->get_name() << "\n";
00427           i++;
00428           j++;
00429         }
00430       }
00431 
00432       while (i < get_num_children()) {
00433         PartGroup *pc = get_child(i);
00434         chan_cat.info()
00435           << "  part has " << pc->get_name()
00436           << ", not in anim.\n";
00437         i++;
00438       }
00439 
00440       while (j < anim->get_num_children()) {
00441         AnimGroup *ac = anim->get_child(j);
00442         chan_cat.info()
00443           << "  anim has " << ac->get_name()
00444           << ", not in part.\n";
00445         j++;
00446       }
00447     }
00448   }
00449 
00450   // Now walk the list of children and check the matching
00451   // sub-hierarchies only.
00452 
00453   int i = 0, j = 0;
00454   while (i < get_num_children() &&
00455          j < anim->get_num_children()) {
00456     PartGroup *pc = get_child(i);
00457     AnimGroup *ac = anim->get_child(j);
00458 
00459     if (pc->get_name() < ac->get_name()) {
00460       if (pc->get_name() == "morph") {
00461         // Model has "morph", not in anim.  Ignore.
00462       } else {
00463         if ((hierarchy_match_flags & HMF_ok_part_extra) == 0) {
00464           return false;
00465         }
00466       }
00467       i++;
00468     } else if (ac->get_name() < pc->get_name()) {
00469       if (ac->get_name() == "morph") {
00470         // Anim has "morph", not in model.  Ignore.
00471       } else {
00472         if ((hierarchy_match_flags & HMF_ok_anim_extra) == 0) {
00473           return false;
00474         }
00475       }
00476       j++;
00477     } else {
00478       if (!pc->check_hierarchy(ac, this, hierarchy_match_flags)) {
00479         return false;
00480       }
00481       i++;
00482       j++;
00483     }
00484   }
00485 
00486   while (i < get_num_children()) {
00487     // There's at least one extra part.
00488     PartGroup *pc = get_child(i);
00489     
00490     if (pc->get_name() == "morph") {
00491       // Model has "morph", not in anim.  Ignore.
00492     } else {
00493       if ((hierarchy_match_flags & HMF_ok_part_extra) == 0) {
00494         return false;
00495       }
00496     }
00497     i++;
00498   }
00499 
00500   while (j < anim->get_num_children()) {
00501     // There's at least one extra anim channel.
00502     AnimGroup *ac = anim->get_child(j);
00503 
00504     if (ac->get_name() == "morph") {
00505       // Anim has "morph", not in model.  Ignore.
00506     } else {
00507       if ((hierarchy_match_flags & HMF_ok_anim_extra) == 0) {
00508         return false;
00509       }
00510     }
00511     j++;
00512   }
00513 
00514   return true;
00515 }
00516 
00517 
00518 ////////////////////////////////////////////////////////////////////
00519 //     Function: PartGroup::do_update
00520 //       Access: Public, Virtual
00521 //  Description: Recursively update this particular part and all of
00522 //               its descendents for the current frame.  This is not
00523 //               really public and is not intended to be called
00524 //               directly; it is called from the top of the tree by
00525 //               PartBundle::update().
00526 //
00527 //               The return value is true if any part has changed,
00528 //               false otherwise.
00529 ////////////////////////////////////////////////////////////////////
00530 bool PartGroup::
00531 do_update(PartBundle *root, const CycleData *root_cdata, PartGroup *,
00532           bool parent_changed, bool anim_changed, Thread *current_thread) {
00533   bool any_changed = false;
00534 
00535   Children::iterator ci;
00536   for (ci = _children.begin(); ci != _children.end(); ++ci) {
00537     if ((*ci)->do_update(root, root_cdata, this, parent_changed, 
00538                          anim_changed, current_thread)) {
00539       any_changed = true;
00540     }
00541   }
00542 
00543   return any_changed;
00544 }
00545 
00546 ////////////////////////////////////////////////////////////////////
00547 //     Function: PartGroup::do_xform
00548 //       Access: Public, Virtual
00549 //  Description: Called by PartBundle::xform(), this indicates the
00550 //               indicated transform is being applied to the root
00551 //               joint.
00552 ////////////////////////////////////////////////////////////////////
00553 void PartGroup::
00554 do_xform(const LMatrix4 &mat, const LMatrix4 &inv_mat) {
00555   Children::const_iterator ci;
00556 
00557   for (ci = _children.begin(); ci != _children.end(); ++ci) {
00558     (*ci)->do_xform(mat, inv_mat);
00559   }
00560 }
00561 
00562 ////////////////////////////////////////////////////////////////////
00563 //     Function: PartGroup::determine_effective_channels
00564 //       Access: Public, Virtual
00565 //  Description: Should be called whenever the ChannelBlend values
00566 //               have changed, this recursively updates the
00567 //               _effective_channel member in each part.
00568 ////////////////////////////////////////////////////////////////////
00569 void PartGroup::
00570 determine_effective_channels(const CycleData *root_cdata) {
00571   Children::iterator ci;
00572   for (ci = _children.begin(); ci != _children.end(); ++ci) {
00573     (*ci)->determine_effective_channels(root_cdata);
00574   }
00575 }
00576 
00577 
00578 ////////////////////////////////////////////////////////////////////
00579 //     Function: PartGroup::write_descendants
00580 //       Access: Protected
00581 //  Description: Writes a brief description of all of the group's
00582 //               descendants.
00583 ////////////////////////////////////////////////////////////////////
00584 void PartGroup::
00585 write_descendants(ostream &out, int indent_level) const {
00586   Children::const_iterator ci;
00587 
00588   for (ci = _children.begin(); ci != _children.end(); ++ci) {
00589     (*ci)->write(out, indent_level);
00590   }
00591 }
00592 
00593 ////////////////////////////////////////////////////////////////////
00594 //     Function: PartGroup::write_descendants_with_value
00595 //       Access: Protected
00596 //  Description: Writes a brief description of all of the group's
00597 //               descendants and their values.
00598 ////////////////////////////////////////////////////////////////////
00599 void PartGroup::
00600 write_descendants_with_value(ostream &out, int indent_level) const {
00601   Children::const_iterator ci;
00602 
00603   for (ci = _children.begin(); ci != _children.end(); ++ci) {
00604     (*ci)->write_with_value(out, indent_level);
00605   }
00606 }
00607 
00608 ////////////////////////////////////////////////////////////////////
00609 //     Function: PartGroup::pick_channel_index
00610 //       Access: Protected, Virtual
00611 //  Description: Walks the part hierarchy, looking for a suitable
00612 //               channel index number to use.  Available index numbers
00613 //               are the elements of the holes set, as well as next to
00614 //               infinity.
00615 ////////////////////////////////////////////////////////////////////
00616 void PartGroup::
00617 pick_channel_index(plist<int> &holes, int &next) const {
00618   Children::const_iterator ci;
00619   for (ci = _children.begin(); ci != _children.end(); ++ci) {
00620     (*ci)->pick_channel_index(holes, next);
00621   }
00622 }
00623 
00624 
00625 ////////////////////////////////////////////////////////////////////
00626 //     Function: PartGroup::bind_hierarchy
00627 //       Access: Protected, Virtual
00628 //  Description: Binds the indicated anim hierarchy to the part
00629 //               hierarchy, at the given channel index number.
00630 ////////////////////////////////////////////////////////////////////
00631 void PartGroup::
00632 bind_hierarchy(AnimGroup *anim, int channel_index, int &joint_index, 
00633                bool is_included, BitArray &bound_joints,
00634                const PartSubset &subset) {
00635   Thread::consider_yield();
00636   if (subset.matches_include(get_name())) {
00637     is_included = true;
00638   } else if (subset.matches_exclude(get_name())) {
00639     is_included = false;
00640   }
00641 
00642   int i = 0, j = 0;
00643   int part_num_children = get_num_children();
00644   int anim_num_children = (anim == NULL) ? 0 : anim->get_num_children();
00645 
00646   while (i < part_num_children && j < anim_num_children) {
00647     PartGroup *pc = get_child(i);
00648     AnimGroup *ac = anim->get_child(j);
00649 
00650     if (pc->get_name() < ac->get_name()) {
00651       // Here's a part, not in the anim.  Bind it to the special NULL
00652       // anim.
00653       pc->bind_hierarchy(NULL, channel_index, joint_index, is_included, 
00654                          bound_joints, subset);
00655       i++;
00656 
00657     } else if (ac->get_name() < pc->get_name()) {
00658       // Here's an anim, not in the part.  Ignore it.
00659       j++;
00660 
00661     } else {
00662       // Here's a matched part and anim pair.
00663       pc->bind_hierarchy(ac, channel_index, joint_index, is_included, 
00664                          bound_joints, subset);
00665       i++;
00666       j++;
00667     }
00668   }
00669 
00670   // Now pick up any more parts, not in the anim.
00671   while (i < part_num_children) {
00672     PartGroup *pc = get_child(i);
00673     pc->bind_hierarchy(NULL, channel_index, joint_index, is_included, 
00674                        bound_joints, subset);
00675     i++;
00676   }
00677 }
00678 
00679 ////////////////////////////////////////////////////////////////////
00680 //     Function: PartGroup::find_bound_joints
00681 //       Access: Protected, Virtual
00682 //  Description: Similar to bind_hierarchy, but does not actually
00683 //               perform any binding.  All it does is compute the
00684 //               BitArray bount_joints according to the specified
00685 //               subset.  This is useful in preparation for
00686 //               asynchronous binding--in this case, we may need to
00687 //               know bound_joints immediately, without having to wait
00688 //               for the animation itself to load and bind.
00689 ////////////////////////////////////////////////////////////////////
00690 void PartGroup::
00691 find_bound_joints(int &joint_index, bool is_included, BitArray &bound_joints,
00692                   const PartSubset &subset) {
00693   if (subset.matches_include(get_name())) {
00694     is_included = true;
00695   } else if (subset.matches_exclude(get_name())) {
00696     is_included = false;
00697   }
00698 
00699   int part_num_children = get_num_children();
00700   for (int i = 0; i < part_num_children; ++i) {
00701     PartGroup *pc = get_child(i);
00702     pc->find_bound_joints(joint_index, is_included, bound_joints, subset);
00703   }
00704 }
00705   
00706 ////////////////////////////////////////////////////////////////////
00707 //     Function: PartGroup::write_datagram
00708 //       Access: Public
00709 //  Description: Function to write the important information in
00710 //               the particular object to a Datagram
00711 ////////////////////////////////////////////////////////////////////
00712 void PartGroup::
00713 write_datagram(BamWriter *manager, Datagram &me) {
00714   me.add_string(get_name());
00715   me.add_uint16(_children.size());
00716   for (size_t i = 0; i < _children.size(); i++) {
00717     manager->write_pointer(me, _children[i]);
00718   }
00719 }
00720 
00721 ////////////////////////////////////////////////////////////////////
00722 //     Function: PartGroup::fillin
00723 //       Access: Protected
00724 //  Description: Function that reads out of the datagram (or asks
00725 //               manager to read) all of the data that is needed to
00726 //               re-create this object and stores it in the appropiate
00727 //               place
00728 ////////////////////////////////////////////////////////////////////
00729 void PartGroup::
00730 fillin(DatagramIterator &scan, BamReader *manager) {
00731   set_name(scan.get_string());
00732 
00733   if (manager->get_file_minor_ver() == 11) {
00734     // Skip over the old freeze-joint information, no longer stored here
00735     scan.get_bool();
00736     LMatrix4 mat;
00737     mat.read_datagram(scan);
00738   }
00739 
00740   int num_children = scan.get_uint16();
00741   _children.reserve(num_children);
00742   for (int i = 0; i < num_children; i++) {
00743     manager->read_pointer(scan);
00744     _children.push_back(NULL);
00745   }
00746 }
00747 
00748 ////////////////////////////////////////////////////////////////////
00749 //     Function: PartGroup::complete_pointers
00750 //       Access: Public
00751 //  Description: Takes in a vector of pointers to TypedWritable
00752 //               objects that correspond to all the requests for
00753 //               pointers that this object made to BamReader.
00754 ////////////////////////////////////////////////////////////////////
00755 int PartGroup::
00756 complete_pointers(TypedWritable **p_list, BamReader *manager) {
00757   int pi = TypedWritableReferenceCount::complete_pointers(p_list, manager);
00758   
00759   Children::iterator ci;
00760   for (ci = _children.begin(); ci != _children.end(); ++ci) {
00761     (*ci) = DCAST(PartGroup, p_list[pi++]);
00762   }
00763 
00764   return pi;
00765 }
00766 
00767 ////////////////////////////////////////////////////////////////////
00768 //     Function: PartGroup::make_PartGroup
00769 //       Access: Protected
00770 //  Description: Factory method to generate a PartGroup object
00771 ////////////////////////////////////////////////////////////////////
00772 TypedWritable* PartGroup::
00773 make_PartGroup(const FactoryParams &params) {
00774   PartGroup *me = new PartGroup;
00775   DatagramIterator scan;
00776   BamReader *manager;
00777 
00778   parse_params(params, scan, manager);
00779   me->fillin(scan, manager);
00780   return me;
00781 }
00782 
00783 ////////////////////////////////////////////////////////////////////
00784 //     Function: PartGroup::register_with_factory
00785 //       Access: Public, Static
00786 //  Description: Factory method to generate a PartGroup object
00787 ////////////////////////////////////////////////////////////////////
00788 void PartGroup::
00789 register_with_read_factory() {
00790   BamReader::get_factory()->register_factory(get_class_type(), make_PartGroup);
00791 }
00792 
 All Classes Functions Variables Enumerations