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: Public 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: Public 00050 // Description: 00051 //////////////////////////////////////////////////////////////////// 00052 PartGroup:: 00053 ~PartGroup() { 00054 } 00055 00056 //////////////////////////////////////////////////////////////////// 00057 // Function: PartGroup::is_character_joint 00058 // Access: Public, 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: Public, 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: Public 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: Public 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: Public 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: Public 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: Public 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 //////////////////////////////////////////////////////////////////// 00174 // Function: PartGroup::apply_freeze 00175 // Access: Published 00176 // Description: Freezes this particular joint so that it will always 00177 // hold the specified transform. Returns true if this 00178 // is a joint that can be so frozen, false otherwise. 00179 // 00180 // This is normally only called internally by 00181 // PartBundle::freeze_joint(), but you may also call it 00182 // directly. 00183 //////////////////////////////////////////////////////////////////// 00184 bool PartGroup:: 00185 apply_freeze(const TransformState *transform) { 00186 return apply_freeze_matrix(transform->get_pos(), transform->get_hpr(), transform->get_scale()) || apply_freeze_scalar(transform->get_pos()[0]); 00187 } 00188 00189 //////////////////////////////////////////////////////////////////// 00190 // Function: PartGroup::apply_freeze_matrix 00191 // Access: Published, Virtual 00192 // Description: Freezes this particular joint so that it will always 00193 // hold the specified transform. Returns true if this 00194 // is a joint that can be so frozen, false otherwise. 00195 // 00196 // This is normally only called internally by 00197 // PartBundle::freeze_joint(), but you may also call it 00198 // directly. 00199 //////////////////////////////////////////////////////////////////// 00200 bool PartGroup:: 00201 apply_freeze_matrix(const LVecBase3f &pos, const LVecBase3f &hpr, const LVecBase3f &scale) { 00202 return false; 00203 } 00204 00205 //////////////////////////////////////////////////////////////////// 00206 // Function: PartGroup::apply_freeze_scalar 00207 // Access: Published, Virtual 00208 // Description: Freezes this particular joint so that it will always 00209 // hold the specified transform. Returns true if this 00210 // is a joint that can be so frozen, false otherwise. 00211 // 00212 // This is normally only called internally by 00213 // PartBundle::freeze_joint(), but you may also call it 00214 // directly. 00215 //////////////////////////////////////////////////////////////////// 00216 bool PartGroup:: 00217 apply_freeze_scalar(float value) { 00218 return false; 00219 } 00220 00221 00222 //////////////////////////////////////////////////////////////////// 00223 // Function: PartGroup::apply_control 00224 // Access: Published, Virtual 00225 // Description: Specifies a node to influence this particular joint 00226 // so that it will always hold the node's transform. 00227 // Returns true if this is a joint that can be so 00228 // controlled, false otherwise. 00229 // 00230 // This is normally only called internally by 00231 // PartBundle::control_joint(), but you may also call it 00232 // directly. 00233 //////////////////////////////////////////////////////////////////// 00234 bool PartGroup:: 00235 apply_control(PandaNode *node) { 00236 return false; 00237 } 00238 00239 //////////////////////////////////////////////////////////////////// 00240 // Function: PartGroup::clear_forced_channel 00241 // Access: Published, Virtual 00242 // Description: Undoes the effect of a previous call to 00243 // apply_freeze() or apply_control(). Returns true if 00244 // the joint was modified, false otherwise. 00245 // 00246 // This is normally only called internally by 00247 // PartBundle::release_joint(), but you may also call it 00248 // directly. 00249 //////////////////////////////////////////////////////////////////// 00250 bool PartGroup:: 00251 clear_forced_channel() { 00252 return false; 00253 } 00254 00255 //////////////////////////////////////////////////////////////////// 00256 // Function: PartGroup::get_forced_channel 00257 // Access: Published, Virtual 00258 // Description: Returns the AnimChannelBase that has been forced to 00259 // this joint by a previous call to apply_freeze() or 00260 // apply_control(), or NULL if no such channel has been 00261 // applied. 00262 //////////////////////////////////////////////////////////////////// 00263 AnimChannelBase *PartGroup:: 00264 get_forced_channel() const { 00265 return NULL; 00266 } 00267 00268 //////////////////////////////////////////////////////////////////// 00269 // Function: PartGroup::get_value_type 00270 // Access: Public, Virtual 00271 // Description: Returns the TypeHandle associated with the ValueType 00272 // we are concerned with. This is provided to allow a 00273 // bit of run-time checking that joints and channels are 00274 // matching properly in type. 00275 //////////////////////////////////////////////////////////////////// 00276 TypeHandle PartGroup:: 00277 get_value_type() const { 00278 return TypeHandle::none(); 00279 } 00280 00281 00282 // An STL object to sort a list of children into alphabetical order. 00283 class PartGroupAlphabeticalOrder { 00284 public: 00285 bool operator()(const PT(PartGroup) &a, const PT(PartGroup) &b) const { 00286 return a->get_name() < b->get_name(); 00287 } 00288 }; 00289 00290 //////////////////////////////////////////////////////////////////// 00291 // Function: PartGroup::sort_descendants 00292 // Access: Public 00293 // Description: Sorts the children nodes at each level of the 00294 // hierarchy into alphabetical order. This should be 00295 // done after creating the hierarchy, to guarantee that 00296 // the correct names will match up together when the 00297 // AnimBundle is later bound to a PlayerRoot. 00298 //////////////////////////////////////////////////////////////////// 00299 void PartGroup:: 00300 sort_descendants() { 00301 stable_sort(_children.begin(), _children.end(), PartGroupAlphabeticalOrder()); 00302 00303 Children::iterator ci; 00304 for (ci = _children.begin(); ci != _children.end(); ++ci) { 00305 (*ci)->sort_descendants(); 00306 } 00307 } 00308 00309 //////////////////////////////////////////////////////////////////// 00310 // Function: PartGroup::check_hierarchy 00311 // Access: Public 00312 // Description: Walks the part hierarchy in tandem with the indicated 00313 // anim hierarchy, and returns true if the hierarchies 00314 // match, false otherwise. 00315 // 00316 // If hierarchy_match_flags is 0, only an exact match is 00317 // accepted; otherwise, it may contain a union of 00318 // PartGroup::HierarchyMatchFlags values indicating 00319 // conditions that will be tolerated (but warnings will 00320 // still be issued). 00321 //////////////////////////////////////////////////////////////////// 00322 bool PartGroup:: 00323 check_hierarchy(const AnimGroup *anim, const PartGroup *, 00324 int hierarchy_match_flags) const { 00325 Thread::consider_yield(); 00326 if (anim->get_value_type() != get_value_type()) { 00327 if (chan_cat.is_error()) { 00328 chan_cat.error() 00329 << "Part " << get_name() << " expects type " << get_value_type() 00330 << " while matching anim node has type " << anim->get_value_type() 00331 << ".\n"; 00332 } 00333 return false; 00334 } 00335 00336 if (chan_cat.is_info()) { 00337 // If we're issuing error messages, check ahead of time if the set 00338 // of children agrees. If it does not, we'll write a one-line 00339 // warning, and then list the set of children that differ. 00340 00341 bool match = true; 00342 if (anim->get_num_children() != get_num_children()) { 00343 // If the only difference is "morph", ignore it. We treat 00344 // "morph" as a special case, because it's common for the model 00345 // and animation files to differ meaninglessly here. Any 00346 // differences here remain unreported. 00347 if (anim->get_num_children() == get_num_children() + 1 && 00348 anim->get_child_named("morph") != NULL && 00349 get_child_named("morph") == NULL) { 00350 // Anim has "morph" and model does not, but there are no other 00351 // differences. 00352 00353 } else if (get_num_children() == anim->get_num_children() + 1 && 00354 get_child_named("morph") != NULL && 00355 anim->get_child_named("morph") == NULL) { 00356 // Model has "morph" and anim does not, but there are no other 00357 // differences. 00358 00359 } else { 00360 chan_cat.info() 00361 << "Part " << get_name() << " has " << get_num_children() 00362 << " children, while matching anim node has " 00363 << anim->get_num_children() << ":\n"; 00364 match = false; 00365 } 00366 00367 } else { 00368 for (int i = 0; match && i < get_num_children(); i++) { 00369 PartGroup *pc = get_child(i); 00370 AnimGroup *ac = anim->get_child(i); 00371 00372 match = (pc->get_name() == ac->get_name()); 00373 } 00374 if (!match) { 00375 chan_cat.info() 00376 << "Part " << get_name() << " has a different set of children " 00377 << " than matching anim node:\n"; 00378 } 00379 } 00380 if (!match) { 00381 int i = 0, j = 0; 00382 while (i < get_num_children() && 00383 j < anim->get_num_children()) { 00384 PartGroup *pc = get_child(i); 00385 AnimGroup *ac = anim->get_child(j); 00386 00387 if (pc->get_name() < ac->get_name()) { 00388 chan_cat.info() 00389 << " part has " << pc->get_name() 00390 << ", not in anim.\n"; 00391 i++; 00392 } else if (ac->get_name() < pc->get_name()) { 00393 chan_cat.info() 00394 << " anim has " << ac->get_name() 00395 << ", not in part.\n"; 00396 j++; 00397 } else { 00398 // chan_cat.info() << " part and anim both have " << ac->get_name() << "\n"; 00399 i++; 00400 j++; 00401 } 00402 } 00403 00404 while (i < get_num_children()) { 00405 PartGroup *pc = get_child(i); 00406 chan_cat.info() 00407 << " part has " << pc->get_name() 00408 << ", not in anim.\n"; 00409 i++; 00410 } 00411 00412 while (j < anim->get_num_children()) { 00413 AnimGroup *ac = anim->get_child(j); 00414 chan_cat.info() 00415 << " anim has " << ac->get_name() 00416 << ", not in part.\n"; 00417 j++; 00418 } 00419 } 00420 } 00421 00422 // Now walk the list of children and check the matching 00423 // sub-hierarchies only. 00424 00425 int i = 0, j = 0; 00426 while (i < get_num_children() && 00427 j < anim->get_num_children()) { 00428 PartGroup *pc = get_child(i); 00429 AnimGroup *ac = anim->get_child(j); 00430 00431 if (pc->get_name() < ac->get_name()) { 00432 if (pc->get_name() == "morph") { 00433 // Model has "morph", not in anim. Ignore. 00434 } else { 00435 if ((hierarchy_match_flags & HMF_ok_part_extra) == 0) { 00436 return false; 00437 } 00438 } 00439 i++; 00440 } else if (ac->get_name() < pc->get_name()) { 00441 if (ac->get_name() == "morph") { 00442 // Anim has "morph", not in model. Ignore. 00443 } else { 00444 if ((hierarchy_match_flags & HMF_ok_anim_extra) == 0) { 00445 return false; 00446 } 00447 } 00448 j++; 00449 } else { 00450 if (!pc->check_hierarchy(ac, this, hierarchy_match_flags)) { 00451 return false; 00452 } 00453 i++; 00454 j++; 00455 } 00456 } 00457 00458 while (i < get_num_children()) { 00459 // There's at least one extra part. 00460 PartGroup *pc = get_child(i); 00461 00462 if (pc->get_name() == "morph") { 00463 // Model has "morph", not in anim. Ignore. 00464 } else { 00465 if ((hierarchy_match_flags & HMF_ok_part_extra) == 0) { 00466 return false; 00467 } 00468 } 00469 i++; 00470 } 00471 00472 while (j < anim->get_num_children()) { 00473 // There's at least one extra anim channel. 00474 AnimGroup *ac = anim->get_child(j); 00475 00476 if (ac->get_name() == "morph") { 00477 // Anim has "morph", not in model. Ignore. 00478 } else { 00479 if ((hierarchy_match_flags & HMF_ok_anim_extra) == 0) { 00480 return false; 00481 } 00482 } 00483 j++; 00484 } 00485 00486 return true; 00487 } 00488 00489 //////////////////////////////////////////////////////////////////// 00490 // Function: PartGroup::write 00491 // Access: Public, Virtual 00492 // Description: Writes a brief description of the group and all of 00493 // its descendants. 00494 //////////////////////////////////////////////////////////////////// 00495 void PartGroup:: 00496 write(ostream &out, int indent_level) const { 00497 indent(out, indent_level) 00498 << get_type() << " " << get_name() << " {\n"; 00499 write_descendants(out, indent_level + 2); 00500 indent(out, indent_level) << "}\n"; 00501 } 00502 00503 //////////////////////////////////////////////////////////////////// 00504 // Function: PartGroup::write_with_value 00505 // Access: Public, Virtual 00506 // Description: Writes a brief description of the group, showing its 00507 // current value, and that of all of its descendants. 00508 //////////////////////////////////////////////////////////////////// 00509 void PartGroup:: 00510 write_with_value(ostream &out, int indent_level) const { 00511 indent(out, indent_level) 00512 << get_type() << " " << get_name() << " {\n"; 00513 write_descendants_with_value(out, indent_level + 2); 00514 indent(out, indent_level) << "}\n"; 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 LMatrix4f &mat, const LMatrix4f &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 LMatrix4f 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