Panda3D
|
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 ¶ms) { 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