Panda3D
|
00001 // Filename: eggJointData.cxx 00002 // Created by: drose (23Feb01) 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 "eggJointData.h" 00016 #include "eggJointNodePointer.h" 00017 #include "eggMatrixTablePointer.h" 00018 #include "pvector.h" 00019 #include "dcast.h" 00020 #include "eggGroup.h" 00021 #include "eggTable.h" 00022 #include "indent.h" 00023 #include "fftCompressor.h" 00024 #include "zStream.h" 00025 00026 TypeHandle EggJointData::_type_handle; 00027 00028 00029 //////////////////////////////////////////////////////////////////// 00030 // Function: EggJointData::Constructor 00031 // Access: Public 00032 // Description: 00033 //////////////////////////////////////////////////////////////////// 00034 EggJointData:: 00035 EggJointData(EggCharacterCollection *collection, 00036 EggCharacterData *char_data) : 00037 EggComponentData(collection, char_data) 00038 { 00039 _parent = (EggJointData *)NULL; 00040 _new_parent = (EggJointData *)NULL; 00041 _has_rest_frame = false; 00042 _rest_frames_differ = false; 00043 } 00044 00045 //////////////////////////////////////////////////////////////////// 00046 // Function: EggJointData::get_frame 00047 // Access: Public 00048 // Description: Returns the local transform matrix corresponding to 00049 // this joint position in the nth frame in the indicated 00050 // model. 00051 //////////////////////////////////////////////////////////////////// 00052 LMatrix4d EggJointData:: 00053 get_frame(int model_index, int n) const { 00054 EggBackPointer *back = get_model(model_index); 00055 if (back == (EggBackPointer *)NULL) { 00056 return LMatrix4d::ident_mat(); 00057 } 00058 00059 EggJointPointer *joint; 00060 DCAST_INTO_R(joint, back, LMatrix4d::ident_mat()); 00061 00062 return joint->get_frame(n); 00063 } 00064 00065 //////////////////////////////////////////////////////////////////// 00066 // Function: EggJointData::get_net_frame 00067 // Access: Public 00068 // Description: Returns the complete transform from the root 00069 // corresponding to this joint position in the nth frame 00070 // in the indicated model. 00071 //////////////////////////////////////////////////////////////////// 00072 LMatrix4d EggJointData:: 00073 get_net_frame(int model_index, int n, EggCharacterDb &db) const { 00074 EggBackPointer *back = get_model(model_index); 00075 if (back == (EggBackPointer *)NULL) { 00076 return LMatrix4d::ident_mat(); 00077 } 00078 00079 EggJointPointer *joint; 00080 DCAST_INTO_R(joint, back, LMatrix4d::ident_mat()); 00081 00082 LMatrix4d mat; 00083 if (!db.get_matrix(joint, EggCharacterDb::TT_net_frame, n, mat)) { 00084 // Compute this frame's net, and stuff it in. 00085 mat = get_frame(model_index, n); 00086 if (_parent != (EggJointData *)NULL) { 00087 mat = mat * _parent->get_net_frame(model_index, n, db); 00088 } 00089 db.set_matrix(joint, EggCharacterDb::TT_net_frame, n, mat); 00090 } 00091 00092 return mat; 00093 } 00094 00095 //////////////////////////////////////////////////////////////////// 00096 // Function: EggJointData::get_net_frame_inv 00097 // Access: Public 00098 // Description: Returns the inverse of get_net_frame(). 00099 //////////////////////////////////////////////////////////////////// 00100 LMatrix4d EggJointData:: 00101 get_net_frame_inv(int model_index, int n, EggCharacterDb &db) const { 00102 EggBackPointer *back = get_model(model_index); 00103 if (back == (EggBackPointer *)NULL) { 00104 return LMatrix4d::ident_mat(); 00105 } 00106 00107 EggJointPointer *joint; 00108 DCAST_INTO_R(joint, back, LMatrix4d::ident_mat()); 00109 00110 LMatrix4d mat; 00111 if (!db.get_matrix(joint, EggCharacterDb::TT_net_frame_inv, n, mat)) { 00112 // Compute this frame's net inverse, and stuff it in. 00113 LMatrix4d mat = get_net_frame(model_index, n, db); 00114 mat.invert_in_place(); 00115 db.set_matrix(joint, EggCharacterDb::TT_net_frame_inv, n, mat); 00116 } 00117 00118 return mat; 00119 } 00120 00121 //////////////////////////////////////////////////////////////////// 00122 // Function: EggJointData::force_initial_rest_frame 00123 // Access: Public 00124 // Description: Forces all of the joints to have the same rest frame 00125 // value as the first joint read in. This is a drastic 00126 // way to repair models whose rest frame values are 00127 // completely bogus, but should not be performed on 00128 // models that are otherwise correct. 00129 //////////////////////////////////////////////////////////////////// 00130 void EggJointData:: 00131 force_initial_rest_frame() { 00132 if (!has_rest_frame()) { 00133 return; 00134 } 00135 int num_models = get_num_models(); 00136 for (int model_index = 0; model_index < num_models; model_index++) { 00137 if (has_model(model_index)) { 00138 EggJointPointer *joint; 00139 DCAST_INTO_V(joint, get_model(model_index)); 00140 if (joint->is_of_type(EggJointNodePointer::get_class_type())) { 00141 joint->set_frame(0, get_rest_frame()); 00142 } 00143 } 00144 } 00145 _rest_frames_differ = false; 00146 } 00147 00148 //////////////////////////////////////////////////////////////////// 00149 // Function: EggJointData::move_vertices_to 00150 // Access: Public 00151 // Description: Moves the vertices assigned to this joint into the 00152 // indicated joint, without changing their weight 00153 // assignments. 00154 //////////////////////////////////////////////////////////////////// 00155 void EggJointData:: 00156 move_vertices_to(EggJointData *new_owner) { 00157 int num_models = get_num_models(); 00158 00159 if (new_owner == (EggJointData *)NULL) { 00160 for (int model_index = 0; model_index < num_models; model_index++) { 00161 if (has_model(model_index)) { 00162 EggJointPointer *joint; 00163 DCAST_INTO_V(joint, get_model(model_index)); 00164 joint->move_vertices_to((EggJointPointer *)NULL); 00165 } 00166 } 00167 } else { 00168 for (int model_index = 0; model_index < num_models; model_index++) { 00169 if (has_model(model_index) && new_owner->has_model(model_index)) { 00170 EggJointPointer *joint, *new_joint; 00171 DCAST_INTO_V(joint, get_model(model_index)); 00172 DCAST_INTO_V(new_joint, new_owner->get_model(model_index)); 00173 joint->move_vertices_to(new_joint); 00174 } 00175 } 00176 } 00177 } 00178 00179 //////////////////////////////////////////////////////////////////// 00180 // Function: EggJointData::score_reparent_to 00181 // Access: Public 00182 // Description: Computes a score >= 0 reflecting the similarity of 00183 // the current joint's animation (in world space) to 00184 // that of the indicated potential parent joint (in 00185 // world space). The lower the number, the more similar 00186 // the motion, and the more suitable is the proposed 00187 // parent-child relationship. Returns -1 if there is an 00188 // error. 00189 //////////////////////////////////////////////////////////////////// 00190 int EggJointData:: 00191 score_reparent_to(EggJointData *new_parent, EggCharacterDb &db) { 00192 if (!FFTCompressor::is_compression_available()) { 00193 // If we don't have compression compiled in, we can't meaningfully 00194 // score the joints. 00195 return -1; 00196 } 00197 00198 // First, build up a big array of the new transforms this joint 00199 // would receive in all frames of all models, were it reparented to 00200 // the indicated joint. 00201 vector_stdfloat i, j, k, a, b, c, x, y, z; 00202 pvector<LVecBase3> hprs; 00203 int num_rows = 0; 00204 00205 int num_models = get_num_models(); 00206 for (int model_index = 0; model_index < num_models; model_index++) { 00207 EggBackPointer *back = get_model(model_index); 00208 if (back != (EggBackPointer *)NULL) { 00209 EggJointPointer *joint; 00210 DCAST_INTO_R(joint, back, false); 00211 00212 int num_frames = get_num_frames(model_index); 00213 for (int n = 0; n < num_frames; n++) { 00214 LMatrix4d transform; 00215 if (_parent == new_parent) { 00216 // We already have this parent. 00217 transform = LMatrix4d::ident_mat(); 00218 00219 } else if (_parent == (EggJointData *)NULL) { 00220 // We are moving from outside the joint hierarchy to within it. 00221 transform = new_parent->get_net_frame_inv(model_index, n, db); 00222 00223 } else if (new_parent == (EggJointData *)NULL) { 00224 // We are moving from within the hierarchy to outside it. 00225 transform = _parent->get_net_frame(model_index, n, db); 00226 00227 } else { 00228 // We are changing parents within the hierarchy. 00229 transform = 00230 _parent->get_net_frame(model_index, n, db) * 00231 new_parent->get_net_frame_inv(model_index, n, db); 00232 } 00233 00234 transform = joint->get_frame(n) * transform; 00235 LVecBase3d scale, shear, hpr, translate; 00236 if (!decompose_matrix(transform, scale, shear, hpr, translate)) { 00237 // Invalid transform. 00238 return -1; 00239 } 00240 i.push_back(scale[0]); 00241 j.push_back(scale[1]); 00242 k.push_back(scale[2]); 00243 a.push_back(shear[0]); 00244 b.push_back(shear[1]); 00245 c.push_back(shear[2]); 00246 hprs.push_back(LCAST(PN_stdfloat, hpr)); 00247 x.push_back(translate[0]); 00248 y.push_back(translate[1]); 00249 z.push_back(translate[2]); 00250 num_rows++; 00251 } 00252 } 00253 } 00254 00255 if (num_rows == 0) { 00256 // No data, no score. 00257 return -1; 00258 } 00259 00260 // Now, we derive a score, by the simple expedient of using the 00261 // FFTCompressor to compress the generated transforms, and measuring 00262 // the length of the resulting bitstream. 00263 FFTCompressor compressor; 00264 Datagram dg; 00265 compressor.write_reals(dg, &i[0], num_rows); 00266 compressor.write_reals(dg, &j[0], num_rows); 00267 compressor.write_reals(dg, &k[0], num_rows); 00268 compressor.write_reals(dg, &a[0], num_rows); 00269 compressor.write_reals(dg, &b[0], num_rows); 00270 compressor.write_reals(dg, &c[0], num_rows); 00271 compressor.write_hprs(dg, &hprs[0], num_rows); 00272 compressor.write_reals(dg, &x[0], num_rows); 00273 compressor.write_reals(dg, &y[0], num_rows); 00274 compressor.write_reals(dg, &z[0], num_rows); 00275 00276 00277 #ifndef HAVE_ZLIB 00278 return dg.get_length(); 00279 00280 #else 00281 // The FFTCompressor does minimal run-length encoding, but to really 00282 // get an accurate measure we should zlib-compress the resulting 00283 // stream. 00284 ostringstream sstr; 00285 OCompressStream zstr(&sstr, false); 00286 zstr.write((const char *)dg.get_data(), dg.get_length()); 00287 zstr.flush(); 00288 return sstr.str().length(); 00289 #endif 00290 } 00291 00292 //////////////////////////////////////////////////////////////////// 00293 // Function: EggJointData::do_rebuild_all 00294 // Access: Public 00295 // Description: Calls do_rebuild() on all models, and recursively on 00296 // all joints at this node and below. Returns true if 00297 // all models returned true, false otherwise. 00298 //////////////////////////////////////////////////////////////////// 00299 bool EggJointData:: 00300 do_rebuild_all(EggCharacterDb &db) { 00301 bool all_ok = true; 00302 00303 BackPointers::iterator bpi; 00304 for (bpi = _back_pointers.begin(); bpi != _back_pointers.end(); ++bpi) { 00305 EggBackPointer *back = (*bpi); 00306 if (back != (EggBackPointer *)NULL) { 00307 EggJointPointer *joint; 00308 DCAST_INTO_R(joint, back, false); 00309 if (!joint->do_rebuild(db)) { 00310 all_ok = false; 00311 } 00312 } 00313 } 00314 00315 Children::iterator ci; 00316 for (ci = _children.begin(); ci != _children.end(); ++ci) { 00317 EggJointData *child = (*ci); 00318 if (!child->do_rebuild_all(db)) { 00319 all_ok = false; 00320 } 00321 } 00322 00323 return all_ok; 00324 } 00325 00326 //////////////////////////////////////////////////////////////////// 00327 // Function: EggJointData::optimize 00328 // Access: Public 00329 // Description: Calls optimize() on all models, and recursively on 00330 // all joints at this node and below. 00331 //////////////////////////////////////////////////////////////////// 00332 void EggJointData:: 00333 optimize() { 00334 BackPointers::iterator bpi; 00335 for (bpi = _back_pointers.begin(); bpi != _back_pointers.end(); ++bpi) { 00336 EggBackPointer *back = (*bpi); 00337 if (back != (EggBackPointer *)NULL) { 00338 EggJointPointer *joint; 00339 DCAST_INTO_V(joint, back); 00340 joint->optimize(); 00341 } 00342 } 00343 00344 Children::iterator ci; 00345 for (ci = _children.begin(); ci != _children.end(); ++ci) { 00346 EggJointData *child = (*ci); 00347 child->optimize(); 00348 } 00349 } 00350 00351 //////////////////////////////////////////////////////////////////// 00352 // Function: EggJointData::expose 00353 // Access: Public 00354 // Description: Calls expose() on all models for this joint, but does 00355 // not recurse downwards. 00356 //////////////////////////////////////////////////////////////////// 00357 void EggJointData:: 00358 expose(EggGroup::DCSType dcs_type) { 00359 BackPointers::iterator bpi; 00360 for (bpi = _back_pointers.begin(); bpi != _back_pointers.end(); ++bpi) { 00361 EggBackPointer *back = (*bpi); 00362 if (back != (EggBackPointer *)NULL) { 00363 EggJointPointer *joint; 00364 DCAST_INTO_V(joint, back); 00365 joint->expose(dcs_type); 00366 } 00367 } 00368 } 00369 00370 //////////////////////////////////////////////////////////////////// 00371 // Function: EggJointData::zero_channels 00372 // Access: Public 00373 // Description: Calls zero_channels() on all models for this joint, 00374 // but does not recurse downwards. 00375 //////////////////////////////////////////////////////////////////// 00376 void EggJointData:: 00377 zero_channels(const string &components) { 00378 BackPointers::iterator bpi; 00379 for (bpi = _back_pointers.begin(); bpi != _back_pointers.end(); ++bpi) { 00380 EggBackPointer *back = (*bpi); 00381 if (back != (EggBackPointer *)NULL) { 00382 EggJointPointer *joint; 00383 DCAST_INTO_V(joint, back); 00384 joint->zero_channels(components); 00385 } 00386 } 00387 } 00388 00389 //////////////////////////////////////////////////////////////////// 00390 // Function: EggJointData::quantize_channels 00391 // Access: Public 00392 // Description: Calls quantize_channels() on all models for this joint, 00393 // and then recurses downwards to all joints below. 00394 //////////////////////////////////////////////////////////////////// 00395 void EggJointData:: 00396 quantize_channels(const string &components, double quantum) { 00397 BackPointers::iterator bpi; 00398 for (bpi = _back_pointers.begin(); bpi != _back_pointers.end(); ++bpi) { 00399 EggBackPointer *back = (*bpi); 00400 if (back != (EggBackPointer *)NULL) { 00401 EggJointPointer *joint; 00402 DCAST_INTO_V(joint, back); 00403 joint->quantize_channels(components, quantum); 00404 } 00405 } 00406 00407 Children::iterator ci; 00408 for (ci = _children.begin(); ci != _children.end(); ++ci) { 00409 EggJointData *child = (*ci); 00410 child->quantize_channels(components, quantum); 00411 } 00412 } 00413 00414 //////////////////////////////////////////////////////////////////// 00415 // Function: EggJointData::apply_default_pose 00416 // Access: Public 00417 // Description: Applies the pose from the indicated frame of the 00418 // indicated source model_index as the initial pose for 00419 // this joint, and does this recursively on all joints 00420 // below. 00421 //////////////////////////////////////////////////////////////////// 00422 void EggJointData:: 00423 apply_default_pose(int source_model, int frame) { 00424 if (has_model(source_model)) { 00425 EggJointPointer *source_joint; 00426 DCAST_INTO_V(source_joint, _back_pointers[source_model]); 00427 BackPointers::iterator bpi; 00428 for (bpi = _back_pointers.begin(); bpi != _back_pointers.end(); ++bpi) { 00429 EggBackPointer *back = (*bpi); 00430 if (back != (EggBackPointer *)NULL) { 00431 EggJointPointer *joint; 00432 DCAST_INTO_V(joint, back); 00433 joint->apply_default_pose(source_joint, frame); 00434 } 00435 } 00436 } 00437 00438 Children::iterator ci; 00439 for (ci = _children.begin(); ci != _children.end(); ++ci) { 00440 EggJointData *child = (*ci); 00441 child->apply_default_pose(source_model, frame); 00442 } 00443 } 00444 00445 //////////////////////////////////////////////////////////////////// 00446 // Function: EggJointData::add_back_pointer 00447 // Access: Public, Virtual 00448 // Description: Adds the indicated model joint or anim table to the 00449 // data. 00450 //////////////////////////////////////////////////////////////////// 00451 void EggJointData:: 00452 add_back_pointer(int model_index, EggObject *egg_object) { 00453 nassertv(egg_object != (EggObject *)NULL); 00454 if (egg_object->is_of_type(EggGroup::get_class_type())) { 00455 // It must be a <Joint>. 00456 EggJointNodePointer *joint = new EggJointNodePointer(egg_object); 00457 set_model(model_index, joint); 00458 if (!_has_rest_frame) { 00459 _rest_frame = joint->get_frame(0); 00460 _has_rest_frame = true; 00461 00462 } else { 00463 // If this new node doesn't come within an acceptable tolerance 00464 // of our first reading of this joint's rest frame, set a 00465 // warning flag. 00466 if (!_rest_frame.almost_equal(joint->get_frame(0), 0.0001)) { 00467 _rest_frames_differ = true; 00468 } 00469 } 00470 00471 } else if (egg_object->is_of_type(EggTable::get_class_type())) { 00472 // It's a <Table> with an "xform" child beneath it. 00473 EggMatrixTablePointer *xform = new EggMatrixTablePointer(egg_object); 00474 set_model(model_index, xform); 00475 00476 } else { 00477 nout << "Invalid object added to joint for back pointer.\n"; 00478 } 00479 } 00480 00481 //////////////////////////////////////////////////////////////////// 00482 // Function: EggJointData::write 00483 // Access: Public, Virtual 00484 // Description: 00485 //////////////////////////////////////////////////////////////////// 00486 void EggJointData:: 00487 write(ostream &out, int indent_level) const { 00488 indent(out, indent_level) 00489 << "Joint " << get_name() 00490 << " (models:"; 00491 int num_models = get_num_models(); 00492 for (int model_index = 0; model_index < num_models; model_index++) { 00493 if (has_model(model_index)) { 00494 out << " " << model_index; 00495 } 00496 } 00497 out << ") {\n"; 00498 00499 Children::const_iterator ci; 00500 for (ci = _children.begin(); ci != _children.end(); ++ci) { 00501 (*ci)->write(out, indent_level + 2); 00502 } 00503 00504 indent(out, indent_level) << "}\n"; 00505 } 00506 00507 //////////////////////////////////////////////////////////////////// 00508 // Function: EggJointData::do_begin_reparent 00509 // Access: Protected 00510 // Description: Clears out the _children vector in preparation for 00511 // refilling it from the _new_parent information. 00512 //////////////////////////////////////////////////////////////////// 00513 void EggJointData:: 00514 do_begin_reparent() { 00515 _got_new_parent_depth = false; 00516 _children.clear(); 00517 } 00518 00519 //////////////////////////////////////////////////////////////////// 00520 // Function: EggJointData::calc_new_parent_depth 00521 // Access: Protected 00522 // Description: Calculates the number of joints above this joint in its 00523 // intended position, as specified by a recent call to 00524 // reparent_to(), and also checks for a cycle in the new 00525 // parent chain. Returns true if a cycle is detected, 00526 // and false otherwise. If a cycle is not detected, 00527 // _new_parent_depth can be consulted for the depth in 00528 // the new hierarchy. 00529 // 00530 // This is used by EggCharacterData::do_reparent() to 00531 // determine the order in which to apply the reparent 00532 // operations. It should be called after 00533 // do_begin_reparent(). 00534 //////////////////////////////////////////////////////////////////// 00535 bool EggJointData:: 00536 calc_new_parent_depth(pset<EggJointData *> &chain) { 00537 if (_got_new_parent_depth) { 00538 return false; 00539 } 00540 if (_new_parent == (EggJointData *)NULL) { 00541 // Here's the top of the new hierarchy. 00542 _got_new_parent_depth = true; 00543 _new_parent_depth = 0; 00544 return false; 00545 } 00546 if (!chain.insert(this).second) { 00547 // We've already visited this joint; that means there's a cycle. 00548 return true; 00549 } 00550 bool cycle = _new_parent->calc_new_parent_depth(chain); 00551 _new_parent_depth = _new_parent->_new_parent_depth + 1; 00552 return cycle; 00553 } 00554 00555 //////////////////////////////////////////////////////////////////// 00556 // Function: EggJointData::do_begin_compute_reparent 00557 // Access: Protected 00558 // Description: Eliminates any cached values before beginning a walk 00559 // through all the joints for do_compute_reparent(), for 00560 // a given model/frame. 00561 //////////////////////////////////////////////////////////////////// 00562 void EggJointData:: 00563 do_begin_compute_reparent() { 00564 _got_new_net_frame = false; 00565 _got_new_net_frame_inv = false; 00566 _computed_reparent = false; 00567 } 00568 00569 //////////////////////////////////////////////////////////////////// 00570 // Function: EggJointData::do_compute_reparent 00571 // Access: Protected 00572 // Description: Prepares the reparent operation by computing a new 00573 // transform for each frame of each model, designed to 00574 // keep the net transform the same when the joint is 00575 // moved to its new parent. Returns true on success, 00576 // false on failure. 00577 //////////////////////////////////////////////////////////////////// 00578 bool EggJointData:: 00579 do_compute_reparent(int model_index, int n, EggCharacterDb &db) { 00580 if (_computed_reparent) { 00581 // We've already done this joint. This is possible because we 00582 // have to recursively compute joints upwards, so we might visit 00583 // the same joint more than once. 00584 return _computed_ok; 00585 } 00586 _computed_reparent = true; 00587 00588 if (_parent == _new_parent) { 00589 // Trivial (and most common) case: we are not moving the joint. 00590 // No recomputation necessary. 00591 _computed_ok = true; 00592 return true; 00593 } 00594 00595 EggBackPointer *back = get_model(model_index); 00596 if (back == (EggBackPointer *)NULL) { 00597 // This joint doesn't have any data to modify. 00598 _computed_ok = true; 00599 return true; 00600 } 00601 00602 EggJointPointer *joint; 00603 DCAST_INTO_R(joint, back, false); 00604 00605 LMatrix4d transform; 00606 if (_parent == (EggJointData *)NULL) { 00607 // We are moving from outside the joint hierarchy to within it. 00608 transform = _new_parent->get_new_net_frame_inv(model_index, n, db); 00609 00610 } else if (_new_parent == (EggJointData *)NULL) { 00611 // We are moving from within the hierarchy to outside it. 00612 transform = _parent->get_net_frame(model_index, n, db); 00613 00614 } else { 00615 // We are changing parents within the hierarchy. 00616 transform = 00617 _parent->get_net_frame(model_index, n, db) * 00618 _new_parent->get_new_net_frame_inv(model_index, n, db); 00619 } 00620 00621 db.set_matrix(joint, EggCharacterDb::TT_rebuild_frame, n, 00622 joint->get_frame(n) * transform); 00623 _computed_ok = true; 00624 00625 return _computed_ok; 00626 } 00627 00628 //////////////////////////////////////////////////////////////////// 00629 // Function: EggJointData::do_joint_rebuild 00630 // Access: Protected 00631 // Description: Calls do_rebuild() on the joint for the indicated 00632 // model index. Returns true on success, false on 00633 // failure (false shouldn't be possible). 00634 //////////////////////////////////////////////////////////////////// 00635 bool EggJointData:: 00636 do_joint_rebuild(int model_index, EggCharacterDb &db) { 00637 bool all_ok = true; 00638 00639 EggJointPointer *parent_joint = NULL; 00640 if (_new_parent != NULL && _new_parent->has_model(model_index)) { 00641 DCAST_INTO_R(parent_joint, _new_parent->get_model(model_index), false); 00642 } 00643 00644 if (has_model(model_index)) { 00645 EggJointPointer *joint; 00646 DCAST_INTO_R(joint, get_model(model_index), false); 00647 if (!joint->do_rebuild(db)) { 00648 all_ok = false; 00649 } 00650 } 00651 00652 return all_ok; 00653 } 00654 00655 //////////////////////////////////////////////////////////////////// 00656 // Function: EggJointData::do_finish_reparent 00657 // Access: Protected 00658 // Description: Performs the actual reparenting operation 00659 // by removing all of the old children and replacing 00660 // them with the set of new children. 00661 //////////////////////////////////////////////////////////////////// 00662 void EggJointData:: 00663 do_finish_reparent() { 00664 int num_models = get_num_models(); 00665 for (int model_index = 0; model_index < num_models; model_index++) { 00666 EggJointPointer *parent_joint = NULL; 00667 if (_new_parent != NULL && _new_parent->has_model(model_index)) { 00668 DCAST_INTO_V(parent_joint, _new_parent->get_model(model_index)); 00669 } 00670 00671 if (has_model(model_index)) { 00672 EggJointPointer *joint; 00673 DCAST_INTO_V(joint, get_model(model_index)); 00674 joint->do_finish_reparent(parent_joint); 00675 } 00676 } 00677 00678 _parent = _new_parent; 00679 if (_parent != (EggJointData *)NULL) { 00680 _parent->_children.push_back(this); 00681 } 00682 } 00683 00684 //////////////////////////////////////////////////////////////////// 00685 // Function: EggJointData::make_new_joint 00686 // Access: Private 00687 // Description: Creates a new joint as a child of this joint and 00688 // returns it. This is intended to be called only from 00689 // EggCharacterData::make_new_joint(). 00690 //////////////////////////////////////////////////////////////////// 00691 EggJointData *EggJointData:: 00692 make_new_joint(const string &name) { 00693 EggJointData *child = new EggJointData(_collection, _char_data); 00694 child->set_name(name); 00695 child->_parent = this; 00696 child->_new_parent = this; 00697 _children.push_back(child); 00698 00699 // Also create new back pointers in each of the models. 00700 int num_models = get_num_models(); 00701 for (int i = 0; i < num_models; i++) { 00702 if (has_model(i)) { 00703 EggJointPointer *joint; 00704 DCAST_INTO_R(joint, get_model(i), NULL); 00705 EggJointPointer *new_joint = joint->make_new_joint(name); 00706 child->set_model(i, new_joint); 00707 } 00708 } 00709 00710 return child; 00711 } 00712 00713 //////////////////////////////////////////////////////////////////// 00714 // Function: EggJointData::find_joint_exact 00715 // Access: Private 00716 // Description: The recursive implementation of find_joint, this 00717 // flavor searches recursively for an exact match of the 00718 // preferred joint name. 00719 //////////////////////////////////////////////////////////////////// 00720 EggJointData *EggJointData:: 00721 find_joint_exact(const string &name) { 00722 Children::const_iterator ci; 00723 for (ci = _children.begin(); ci != _children.end(); ++ci) { 00724 EggJointData *child = (*ci); 00725 if (child->get_name() == name) { 00726 return child; 00727 } 00728 EggJointData *result = child->find_joint_exact(name); 00729 if (result != (EggJointData *)NULL) { 00730 return result; 00731 } 00732 } 00733 00734 return (EggJointData *)NULL; 00735 } 00736 00737 //////////////////////////////////////////////////////////////////// 00738 // Function: EggJointData::find_joint_matches 00739 // Access: Private 00740 // Description: The recursive implementation of find_joint, this 00741 // flavor searches recursively for any acceptable match. 00742 //////////////////////////////////////////////////////////////////// 00743 EggJointData *EggJointData:: 00744 find_joint_matches(const string &name) { 00745 Children::const_iterator ci; 00746 for (ci = _children.begin(); ci != _children.end(); ++ci) { 00747 EggJointData *child = (*ci); 00748 if (child->matches_name(name)) { 00749 return child; 00750 } 00751 EggJointData *result = child->find_joint_matches(name); 00752 if (result != (EggJointData *)NULL) { 00753 return result; 00754 } 00755 } 00756 00757 return (EggJointData *)NULL; 00758 } 00759 00760 //////////////////////////////////////////////////////////////////// 00761 // Function: EggJointData::is_new_ancestor 00762 // Access: Protected 00763 // Description: Returns true if this joint is an ancestor of the 00764 // indicated joint, in the "new" hierarchy (that is, the 00765 // one defined by _new_parent, as set by reparent_to() 00766 // before do_finish_reparent() is called). 00767 //////////////////////////////////////////////////////////////////// 00768 bool EggJointData:: 00769 is_new_ancestor(EggJointData *child) const { 00770 if (child == this) { 00771 return true; 00772 } 00773 00774 if (child->_new_parent == (EggJointData *)NULL) { 00775 return false; 00776 } 00777 00778 return is_new_ancestor(child->_new_parent); 00779 } 00780 00781 //////////////////////////////////////////////////////////////////// 00782 // Function: EggJointData::get_new_net_frame 00783 // Access: Private 00784 // Description: Similar to get_net_frame(), but computed for the 00785 // prospective new parentage of the node, before 00786 // do_finish_reparent() is called. This is generally 00787 // useful only when called within do_compute_reparent(). 00788 //////////////////////////////////////////////////////////////////// 00789 const LMatrix4d &EggJointData:: 00790 get_new_net_frame(int model_index, int n, EggCharacterDb &db) { 00791 if (!_got_new_net_frame) { 00792 _new_net_frame = get_new_frame(model_index, n, db); 00793 if (_new_parent != (EggJointData *)NULL) { 00794 _new_net_frame = _new_net_frame * _new_parent->get_new_net_frame(model_index, n, db); 00795 } 00796 _got_new_net_frame = true; 00797 } 00798 return _new_net_frame; 00799 } 00800 00801 //////////////////////////////////////////////////////////////////// 00802 // Function: EggJointData::get_new_net_frame_inv 00803 // Access: Private 00804 // Description: Returns the inverse of get_new_net_frame(). 00805 //////////////////////////////////////////////////////////////////// 00806 const LMatrix4d &EggJointData:: 00807 get_new_net_frame_inv(int model_index, int n, EggCharacterDb &db) { 00808 if (!_got_new_net_frame_inv) { 00809 _new_net_frame_inv.invert_from(get_new_frame(model_index, n, db)); 00810 if (_new_parent != (EggJointData *)NULL) { 00811 _new_net_frame_inv = _new_parent->get_new_net_frame_inv(model_index, n, db) * _new_net_frame_inv; 00812 } 00813 _got_new_net_frame_inv = true; 00814 } 00815 return _new_net_frame_inv; 00816 } 00817 00818 //////////////////////////////////////////////////////////////////// 00819 // Function: EggJointData::get_new_frame 00820 // Access: Private 00821 // Description: Returns the local transform matrix corresponding to 00822 // this joint position in the nth frame in the indicated 00823 // model, as it will be when do_finish_reparent() is 00824 // called. 00825 //////////////////////////////////////////////////////////////////// 00826 LMatrix4d EggJointData:: 00827 get_new_frame(int model_index, int n, EggCharacterDb &db) { 00828 do_compute_reparent(model_index, n, db); 00829 00830 EggBackPointer *back = get_model(model_index); 00831 if (back == (EggBackPointer *)NULL) { 00832 return LMatrix4d::ident_mat(); 00833 } 00834 00835 EggJointPointer *joint; 00836 DCAST_INTO_R(joint, back, LMatrix4d::ident_mat()); 00837 00838 LMatrix4d mat; 00839 if (!db.get_matrix(joint, EggCharacterDb::TT_rebuild_frame, n, mat)) { 00840 // No rebuild frame; return the regular frame. 00841 return joint->get_frame(n); 00842 } 00843 00844 // Return the rebuild frame, as computed. 00845 return mat; 00846 }