Panda3D
|
00001 // Filename: animChannelMatrixXfmTable.cxx 00002 // Created by: drose (20Feb99) 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 00016 #include "animChannelMatrixXfmTable.h" 00017 #include "animBundle.h" 00018 #include "config_chan.h" 00019 00020 #include "compose_matrix.h" 00021 #include "indent.h" 00022 #include "datagram.h" 00023 #include "datagramIterator.h" 00024 #include "bamReader.h" 00025 #include "bamWriter.h" 00026 #include "fftCompressor.h" 00027 #include "config_linmath.h" 00028 00029 TypeHandle AnimChannelMatrixXfmTable::_type_handle; 00030 00031 //////////////////////////////////////////////////////////////////// 00032 // Function: AnimChannelMatrixXfmTable::Constructor 00033 // Access: Protected 00034 // Description: Used only for bam loader. 00035 ///////////////////////////////////////////////////////////// 00036 AnimChannelMatrixXfmTable:: 00037 AnimChannelMatrixXfmTable() { 00038 for (int i = 0; i < num_matrix_components; i++) { 00039 _tables[i] = CPTA_stdfloat(get_class_type()); 00040 } 00041 } 00042 00043 //////////////////////////////////////////////////////////////////// 00044 // Function: AnimChannelMatrixXfmTable::Copy Constructor 00045 // Access: Protected 00046 // Description: Creates a new AnimChannelMatrixXfmTable, just like 00047 // this one, without copying any children. The new copy 00048 // is added to the indicated parent. Intended to be 00049 // called by make_copy() only. 00050 //////////////////////////////////////////////////////////////////// 00051 AnimChannelMatrixXfmTable:: 00052 AnimChannelMatrixXfmTable(AnimGroup *parent, const AnimChannelMatrixXfmTable ©) : 00053 AnimChannelMatrix(parent, copy) 00054 { 00055 for (int i = 0; i < num_matrix_components; i++) { 00056 _tables[i] = copy._tables[i]; 00057 } 00058 } 00059 00060 //////////////////////////////////////////////////////////////////// 00061 // Function: AnimChannelMatrixXfmTable::Constructor 00062 // Access: Public 00063 // Description: 00064 //////////////////////////////////////////////////////////////////// 00065 AnimChannelMatrixXfmTable:: 00066 AnimChannelMatrixXfmTable(AnimGroup *parent, const string &name) 00067 : AnimChannelMatrix(parent, name) 00068 { 00069 for (int i = 0; i < num_matrix_components; i++) { 00070 _tables[i] = CPTA_stdfloat(get_class_type()); 00071 } 00072 } 00073 00074 //////////////////////////////////////////////////////////////////// 00075 // Function: AnimChannelMatrixXfmTable::Destructor 00076 // Access: Public, Virtual 00077 // Description: 00078 ///////////////////////////////////////////////////////////// 00079 AnimChannelMatrixXfmTable:: 00080 ~AnimChannelMatrixXfmTable() { 00081 } 00082 00083 00084 //////////////////////////////////////////////////////////////////// 00085 // Function: AnimChannelMatrixXfmTable::has_changed 00086 // Access: Public, Virtual 00087 // Description: Returns true if the value has changed since the last 00088 // call to has_changed(). last_frame is the frame 00089 // number of the last call; this_frame is the current 00090 // frame number. 00091 //////////////////////////////////////////////////////////////////// 00092 bool AnimChannelMatrixXfmTable:: 00093 has_changed(int last_frame, double last_frac, 00094 int this_frame, double this_frac) { 00095 if (last_frame != this_frame) { 00096 for (int i = 0; i < num_matrix_components; i++) { 00097 if (_tables[i].size() > 1) { 00098 if (_tables[i][last_frame % _tables[i].size()] != 00099 _tables[i][this_frame % _tables[i].size()]) { 00100 return true; 00101 } 00102 } 00103 } 00104 } 00105 00106 if (last_frac != this_frac) { 00107 // If we have some fractional changes, also check the next 00108 // subsequent frame (since we'll be blending with that). 00109 for (int i = 0; i < num_matrix_components; i++) { 00110 if (_tables[i].size() > 1) { 00111 if (_tables[i][last_frame % _tables[i].size()] != 00112 _tables[i][(this_frame + 1) % _tables[i].size()]) { 00113 return true; 00114 } 00115 } 00116 } 00117 } 00118 00119 return false; 00120 } 00121 00122 //////////////////////////////////////////////////////////////////// 00123 // Function: AnimChannelMatrixXfmTable::get_value 00124 // Access: Public, Virtual 00125 // Description: Gets the value of the channel at the indicated frame. 00126 //////////////////////////////////////////////////////////////////// 00127 void AnimChannelMatrixXfmTable:: 00128 get_value(int frame, LMatrix4 &mat) { 00129 PN_stdfloat components[num_matrix_components]; 00130 00131 for (int i = 0; i < num_matrix_components; i++) { 00132 if (_tables[i].empty()) { 00133 components[i] = get_default_value(i); 00134 } else { 00135 components[i] = _tables[i][frame % _tables[i].size()]; 00136 } 00137 } 00138 00139 compose_matrix(mat, components); 00140 } 00141 00142 //////////////////////////////////////////////////////////////////// 00143 // Function: AnimChannelMatrixXfmTable::get_value_no_scale_shear 00144 // Access: Public, Virtual 00145 // Description: Gets the value of the channel at the indicated frame, 00146 // without any scale or shear information. 00147 //////////////////////////////////////////////////////////////////// 00148 void AnimChannelMatrixXfmTable:: 00149 get_value_no_scale_shear(int frame, LMatrix4 &mat) { 00150 PN_stdfloat components[num_matrix_components]; 00151 components[0] = 1.0f; 00152 components[1] = 1.0f; 00153 components[2] = 1.0f; 00154 components[3] = 0.0f; 00155 components[4] = 0.0f; 00156 components[5] = 0.0f; 00157 00158 for (int i = 6; i < num_matrix_components; i++) { 00159 if (_tables[i].empty()) { 00160 components[i] = get_default_value(i); 00161 } else { 00162 components[i] = _tables[i][frame % _tables[i].size()]; 00163 } 00164 } 00165 00166 compose_matrix(mat, components); 00167 } 00168 00169 //////////////////////////////////////////////////////////////////// 00170 // Function: AnimChannelMatrixXfmTable::get_scale 00171 // Access: Public, Virtual 00172 // Description: Gets the scale value at the indicated frame. 00173 //////////////////////////////////////////////////////////////////// 00174 void AnimChannelMatrixXfmTable:: 00175 get_scale(int frame, LVecBase3 &scale) { 00176 for (int i = 0; i < 3; i++) { 00177 if (_tables[i].empty()) { 00178 scale[i] = 1.0f; 00179 } else { 00180 scale[i] = _tables[i][frame % _tables[i].size()]; 00181 } 00182 } 00183 } 00184 00185 //////////////////////////////////////////////////////////////////// 00186 // Function: AnimChannelMatrixXfmTable::get_hpr 00187 // Access: Public, Virtual 00188 // Description: Returns the h, p, and r components associated 00189 // with the current frame. As above, this only makes 00190 // sense for a matrix-type channel. 00191 //////////////////////////////////////////////////////////////////// 00192 void AnimChannelMatrixXfmTable:: 00193 get_hpr(int frame, LVecBase3 &hpr) { 00194 for (int i = 0; i < 3; i++) { 00195 if (_tables[i + 6].empty()) { 00196 hpr[i] = 0.0f; 00197 } else { 00198 hpr[i] = _tables[i + 6][frame % _tables[i + 6].size()]; 00199 } 00200 } 00201 } 00202 00203 //////////////////////////////////////////////////////////////////// 00204 // Function: AnimChannelMatrixXfmTable::get_quat 00205 // Access: Public, Virtual 00206 // Description: Returns the rotation component associated with the 00207 // current frame, expressed as a quaternion. As above, 00208 // this only makes sense for a matrix-type channel. 00209 //////////////////////////////////////////////////////////////////// 00210 void AnimChannelMatrixXfmTable:: 00211 get_quat(int frame, LQuaternion &quat) { 00212 LVecBase3 hpr; 00213 for (int i = 0; i < 3; i++) { 00214 if (_tables[i + 6].empty()) { 00215 hpr[i] = 0.0f; 00216 } else { 00217 hpr[i] = _tables[i + 6][frame % _tables[i + 6].size()]; 00218 } 00219 } 00220 00221 quat.set_hpr(hpr); 00222 } 00223 00224 //////////////////////////////////////////////////////////////////// 00225 // Function: AnimChannelMatrixXfmTable::get_pos 00226 // Access: Public, Virtual 00227 // Description: Returns the x, y, and z translation components 00228 // associated with the current frame. As above, this 00229 // only makes sense for a matrix-type channel. 00230 //////////////////////////////////////////////////////////////////// 00231 void AnimChannelMatrixXfmTable:: 00232 get_pos(int frame, LVecBase3 &pos) { 00233 for (int i = 0; i < 3; i++) { 00234 if (_tables[i + 9].empty()) { 00235 pos[i] = 0.0f; 00236 } else { 00237 pos[i] = _tables[i + 9][frame % _tables[i + 9].size()]; 00238 } 00239 } 00240 } 00241 00242 //////////////////////////////////////////////////////////////////// 00243 // Function: AnimChannelMatrixXfmTable::get_shear 00244 // Access: Public, Virtual 00245 // Description: Returns the a, b, and c shear components associated 00246 // with the current frame. As above, this only makes 00247 // sense for a matrix-type channel. 00248 //////////////////////////////////////////////////////////////////// 00249 void AnimChannelMatrixXfmTable:: 00250 get_shear(int frame, LVecBase3 &shear) { 00251 for (int i = 0; i < 3; i++) { 00252 if (_tables[i + 3].empty()) { 00253 shear[i] = 0.0f; 00254 } else { 00255 shear[i] = _tables[i + 3][frame % _tables[i + 3].size()]; 00256 } 00257 } 00258 } 00259 00260 //////////////////////////////////////////////////////////////////// 00261 // Function: AnimChannelMatrixXfmTable::set_table 00262 // Access: Public 00263 // Description: Assigns the indicated table. table_id is one of 'i', 00264 // 'j', 'k', for scale, 'a', 'b', 'c' for shear, 'h', 00265 // 'p', 'r', for rotation, and 'x', 'y', 'z', for 00266 // translation. The new table must have either zero, 00267 // one, or get_num_frames() frames. 00268 //////////////////////////////////////////////////////////////////// 00269 void AnimChannelMatrixXfmTable:: 00270 set_table(char table_id, const CPTA_stdfloat &table) { 00271 int num_frames = _root->get_num_frames(); 00272 00273 if (table.size() > 1 && (int)table.size() < num_frames) { 00274 // The new table has an invalid number of frames--it doesn't match 00275 // the bundle's requirement. 00276 nassertv(false); 00277 return; 00278 } 00279 00280 int i = get_table_index(table_id); 00281 if (i < 0) { 00282 return; 00283 } 00284 00285 _tables[i] = table; 00286 } 00287 00288 00289 //////////////////////////////////////////////////////////////////// 00290 // Function: AnimChannelMatrixXfmTable::clear_all_tables 00291 // Access: Published 00292 // Description: Removes all the tables from the channel, and resets 00293 // it to its initial state. 00294 //////////////////////////////////////////////////////////////////// 00295 void AnimChannelMatrixXfmTable:: 00296 clear_all_tables() { 00297 for (int i = 0; i < num_matrix_components; i++) { 00298 _tables[i] = CPTA_stdfloat(get_class_type()); 00299 } 00300 } 00301 00302 //////////////////////////////////////////////////////////////////// 00303 // Function: AnimChannelMatrixXfmTable::write 00304 // Access: Public, Virtual 00305 // Description: Writes a brief description of the table and all of 00306 // its descendants. 00307 //////////////////////////////////////////////////////////////////// 00308 void AnimChannelMatrixXfmTable:: 00309 write(ostream &out, int indent_level) const { 00310 indent(out, indent_level) 00311 << get_type() << " " << get_name() << " "; 00312 00313 // Write a list of all the sub-tables that have data. 00314 bool found_any = false; 00315 for (int i = 0; i < num_matrix_components; i++) { 00316 if (!_tables[i].empty()) { 00317 out << get_table_id(i) << _tables[i].size(); 00318 found_any = true; 00319 } 00320 } 00321 00322 if (!found_any) { 00323 out << "(no data)"; 00324 } 00325 00326 if (!_children.empty()) { 00327 out << " {\n"; 00328 write_descendants(out, indent_level + 2); 00329 indent(out, indent_level) << "}"; 00330 } 00331 00332 out << "\n"; 00333 } 00334 00335 //////////////////////////////////////////////////////////////////// 00336 // Function: AnimChannelMatrixXfmTable::make_copy 00337 // Access: Protected, Virtual 00338 // Description: Returns a copy of this object, and attaches it to the 00339 // indicated parent (which may be NULL only if this is 00340 // an AnimBundle). Intended to be called by 00341 // copy_subtree() only. 00342 //////////////////////////////////////////////////////////////////// 00343 AnimGroup *AnimChannelMatrixXfmTable:: 00344 make_copy(AnimGroup *parent) const { 00345 return new AnimChannelMatrixXfmTable(parent, *this); 00346 } 00347 00348 //////////////////////////////////////////////////////////////////// 00349 // Function: AnimChannelMatrixXfmTable::get_table_index 00350 // Access: Protected, Static 00351 // Description: Returns the table index number, a value between 0 and 00352 // num_matrix_components, that corresponds to the 00353 // indicated table id. Returns -1 if the table id is 00354 // invalid. 00355 //////////////////////////////////////////////////////////////////// 00356 int AnimChannelMatrixXfmTable:: 00357 get_table_index(char table_id) { 00358 for (int i = 0; i < num_matrix_components; i++) { 00359 if (table_id == get_table_id(i)) { 00360 return i; 00361 } 00362 } 00363 00364 return -1; 00365 } 00366 00367 //////////////////////////////////////////////////////////////////// 00368 // Function: AnimChannelMatrixXfmTable::write_datagram 00369 // Access: Public 00370 // Description: Function to write the important information in 00371 // the particular object to a Datagram 00372 //////////////////////////////////////////////////////////////////// 00373 void AnimChannelMatrixXfmTable:: 00374 write_datagram(BamWriter *manager, Datagram &me) { 00375 AnimChannelMatrix::write_datagram(manager, me); 00376 00377 if (compress_channels && !FFTCompressor::is_compression_available()) { 00378 chan_cat.error() 00379 << "Compression is not available; writing uncompressed channels.\n"; 00380 compress_channels = false; 00381 } 00382 00383 me.add_bool(compress_channels); 00384 me.add_bool(temp_hpr_fix); 00385 00386 if (!compress_channels) { 00387 // Write out everything uncompressed, as a stream of floats. 00388 for (int i = 0; i < num_matrix_components; i++) { 00389 me.add_uint16(_tables[i].size()); 00390 for(int j = 0; j < (int)_tables[i].size(); j++) { 00391 me.add_stdfloat(_tables[i][j]); 00392 } 00393 } 00394 00395 } else { 00396 // Write out everything using lossy compression. 00397 FFTCompressor compressor; 00398 compressor.set_quality(compress_chan_quality); 00399 compressor.set_use_error_threshold(true); 00400 compressor.write_header(me); 00401 00402 // First, write out the scales and shears. 00403 int i; 00404 for (i = 0; i < 6; i++) { 00405 compressor.write_reals(me, _tables[i], _tables[i].size()); 00406 } 00407 00408 // Now, write out the joint angles. For these we need to build up 00409 // a HPR array. 00410 pvector<LVecBase3> hprs; 00411 int hprs_length = max(max(_tables[6].size(), _tables[7].size()), _tables[8].size()); 00412 hprs.reserve(hprs_length); 00413 for (i = 0; i < hprs_length; i++) { 00414 PN_stdfloat h = _tables[6].empty() ? 0.0f : _tables[6][i % _tables[6].size()]; 00415 PN_stdfloat p = _tables[7].empty() ? 0.0f : _tables[7][i % _tables[7].size()]; 00416 PN_stdfloat r = _tables[8].empty() ? 0.0f : _tables[8][i % _tables[8].size()]; 00417 hprs.push_back(LVecBase3(h, p, r)); 00418 } 00419 const LVecBase3 *hprs_array = NULL; 00420 if (hprs_length != 0) { 00421 hprs_array = &hprs[0]; 00422 } 00423 compressor.write_hprs(me, hprs_array, hprs_length); 00424 00425 // And now the translations. 00426 for(i = 9; i < num_matrix_components; i++) { 00427 compressor.write_reals(me, _tables[i], _tables[i].size()); 00428 } 00429 } 00430 } 00431 00432 //////////////////////////////////////////////////////////////////// 00433 // Function: AnimChannelMatrixXfmTable::fillin 00434 // Access: Protected 00435 // Description: Function that reads out of the datagram (or asks 00436 // manager to read) all of the data that is needed to 00437 // re-create this object and stores it in the appropiate 00438 // place 00439 //////////////////////////////////////////////////////////////////// 00440 void AnimChannelMatrixXfmTable:: 00441 fillin(DatagramIterator &scan, BamReader *manager) { 00442 AnimChannelMatrix::fillin(scan, manager); 00443 00444 bool wrote_compressed = scan.get_bool(); 00445 00446 bool new_hpr = scan.get_bool(); 00447 00448 if (!wrote_compressed) { 00449 // Regular floats. 00450 00451 for (int i = 0; i < num_matrix_components; i++) { 00452 int size = scan.get_uint16(); 00453 PTA_stdfloat ind_table(get_class_type()); 00454 for (int j = 0; j < size; j++) { 00455 ind_table.push_back(scan.get_stdfloat()); 00456 } 00457 _tables[i] = ind_table; 00458 } 00459 00460 if ((!new_hpr && temp_hpr_fix) || (new_hpr && !temp_hpr_fix)) { 00461 // Convert between the old HPR form and the new HPR form. 00462 size_t num_hprs = max(max(_tables[6].size(), _tables[7].size()), 00463 _tables[8].size()); 00464 00465 LVecBase3 default_hpr(0.0, 0.0, 0.0); 00466 if (!_tables[6].empty()) { 00467 default_hpr[0] = _tables[6][0]; 00468 } 00469 if (!_tables[7].empty()) { 00470 default_hpr[1] = _tables[7][0]; 00471 } 00472 if (!_tables[8].empty()) { 00473 default_hpr[2] = _tables[8][0]; 00474 } 00475 00476 PTA_stdfloat h_table = PTA_stdfloat::empty_array(num_hprs, get_class_type()); 00477 PTA_stdfloat p_table = PTA_stdfloat::empty_array(num_hprs, get_class_type()); 00478 PTA_stdfloat r_table = PTA_stdfloat::empty_array(num_hprs, get_class_type()); 00479 00480 for (size_t hi = 0; hi < num_hprs; hi++) { 00481 PN_stdfloat h = (hi < _tables[6].size() ? _tables[6][hi] : default_hpr[0]); 00482 PN_stdfloat p = (hi < _tables[7].size() ? _tables[7][hi] : default_hpr[1]); 00483 PN_stdfloat r = (hi < _tables[8].size() ? _tables[8][hi] : default_hpr[2]); 00484 00485 LVecBase3 hpr; 00486 if (temp_hpr_fix) { 00487 hpr = old_to_new_hpr(LVecBase3(h, p, r)); 00488 } else { 00489 hpr = new_to_old_hpr(LVecBase3(h, p, r)); 00490 } 00491 h_table[hi] = hpr[0]; 00492 p_table[hi] = hpr[1]; 00493 r_table[hi] = hpr[2]; 00494 } 00495 _tables[6] = h_table; 00496 _tables[7] = p_table; 00497 _tables[8] = r_table; 00498 } 00499 00500 } else { 00501 // Compressed channels. 00502 if (!read_compressed_channels) { 00503 chan_cat.info() 00504 << "Not reading compressed animation channels.\n"; 00505 clear_all_tables(); 00506 return; 00507 } 00508 00509 FFTCompressor compressor; 00510 compressor.read_header(scan, manager->get_file_minor_ver()); 00511 00512 int i; 00513 // First, read in the scales and shears. 00514 for (i = 0; i < 6; i++) { 00515 PTA_stdfloat ind_table = PTA_stdfloat::empty_array(0, get_class_type()); 00516 compressor.read_reals(scan, ind_table.v()); 00517 _tables[i] = ind_table; 00518 } 00519 00520 // Read in the HPR array and store it back in the joint angles. 00521 pvector<LVecBase3> hprs; 00522 compressor.read_hprs(scan, hprs, new_hpr); 00523 PTA_stdfloat h_table = PTA_stdfloat::empty_array(hprs.size(), get_class_type()); 00524 PTA_stdfloat p_table = PTA_stdfloat::empty_array(hprs.size(), get_class_type()); 00525 PTA_stdfloat r_table = PTA_stdfloat::empty_array(hprs.size(), get_class_type()); 00526 00527 for (i = 0; i < (int)hprs.size(); i++) { 00528 if (!new_hpr && temp_hpr_fix) { 00529 // Convert the old HPR form to the new HPR form. 00530 LVecBase3 hpr = old_to_new_hpr(hprs[i]); 00531 h_table[i] = hpr[0]; 00532 p_table[i] = hpr[1]; 00533 r_table[i] = hpr[2]; 00534 00535 } else if (new_hpr && !temp_hpr_fix) { 00536 // Convert the new HPR form to the old HPR form. 00537 LVecBase3 hpr = new_to_old_hpr(hprs[i]); 00538 h_table[i] = hpr[0]; 00539 p_table[i] = hpr[1]; 00540 r_table[i] = hpr[2]; 00541 00542 } else { 00543 // Store the HPR angle directly. 00544 h_table[i] = hprs[i][0]; 00545 p_table[i] = hprs[i][1]; 00546 r_table[i] = hprs[i][2]; 00547 } 00548 } 00549 _tables[6] = h_table; 00550 _tables[7] = p_table; 00551 _tables[8] = r_table; 00552 00553 // Now read in the translations. 00554 for (i = 9; i < num_matrix_components; i++) { 00555 PTA_stdfloat ind_table = PTA_stdfloat::empty_array(0, get_class_type()); 00556 compressor.read_reals(scan, ind_table.v()); 00557 _tables[i] = ind_table; 00558 } 00559 } 00560 } 00561 00562 //////////////////////////////////////////////////////////////////// 00563 // Function: AnimChannelMatrixXfmTable::make_AnimChannelMatrixXfmTable 00564 // Access: Protected 00565 // Description: Factory method to generate an 00566 // AnimChannelMatrixXfmTable object. 00567 //////////////////////////////////////////////////////////////////// 00568 TypedWritable *AnimChannelMatrixXfmTable:: 00569 make_AnimChannelMatrixXfmTable(const FactoryParams ¶ms) { 00570 AnimChannelMatrixXfmTable *me = new AnimChannelMatrixXfmTable; 00571 DatagramIterator scan; 00572 BamReader *manager; 00573 00574 parse_params(params, scan, manager); 00575 me->fillin(scan, manager); 00576 return me; 00577 } 00578 00579 //////////////////////////////////////////////////////////////////// 00580 // Function: AnimChannelMatrixXfmTable::register_with_factory 00581 // Access: Public, Static 00582 // Description: Factory method to generate an 00583 // AnimChannelMatrixXfmTable object. 00584 //////////////////////////////////////////////////////////////////// 00585 void AnimChannelMatrixXfmTable:: 00586 register_with_read_factory() { 00587 BamReader::get_factory()->register_factory(get_class_type(), make_AnimChannelMatrixXfmTable); 00588 } 00589 00590