Panda3D
 All Classes Functions Variables Enumerations
animChannelMatrixXfmTable.cxx
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 &copy) : 
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 &params) {
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 
 All Classes Functions Variables Enumerations