Panda3D
 All Classes Functions Variables Enumerations
animChannelScalarTable.cxx
00001 // Filename: animChannelScalarTable.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 
00016 #include "animChannelScalarTable.h"
00017 #include "animBundle.h"
00018 #include "config_chan.h"
00019 
00020 #include "indent.h"
00021 #include "datagram.h"
00022 #include "datagramIterator.h"
00023 #include "bamReader.h"
00024 #include "bamWriter.h"
00025 #include "fftCompressor.h"
00026 
00027 TypeHandle AnimChannelScalarTable::_type_handle;
00028 
00029 ////////////////////////////////////////////////////////////////////
00030 //     Function: AnimChannelScalarTable::Constructor
00031 //       Access: Protected
00032 //  Description:
00033 ////////////////////////////////////////////////////////////////////
00034 AnimChannelScalarTable::
00035 AnimChannelScalarTable() : _table(get_class_type()) {
00036 }
00037 
00038 ////////////////////////////////////////////////////////////////////
00039 //     Function: AnimChannelScalarTable::Copy Constructor
00040 //       Access: Protected
00041 //  Description: Creates a new AnimChannelScalarTable, just like
00042 //               this one, without copying any children.  The new copy
00043 //               is added to the indicated parent.  Intended to be
00044 //               called by make_copy() only.
00045 ////////////////////////////////////////////////////////////////////
00046 AnimChannelScalarTable::
00047 AnimChannelScalarTable(AnimGroup *parent, const AnimChannelScalarTable &copy) : 
00048   AnimChannelScalar(parent, copy),
00049   _table(copy._table)
00050 {
00051 }
00052 
00053 ////////////////////////////////////////////////////////////////////
00054 //     Function: AnimChannelScalarTable::Constructor
00055 //       Access: Public
00056 //  Description:
00057 ////////////////////////////////////////////////////////////////////
00058 AnimChannelScalarTable::
00059 AnimChannelScalarTable(AnimGroup *parent, const string &name) :
00060   AnimChannelScalar(parent, name),
00061   _table(get_class_type())
00062 {
00063 }
00064 
00065 ////////////////////////////////////////////////////////////////////
00066 //     Function: AnimChannelScalarTable::has_changed
00067 //       Access: Public, Virtual
00068 //  Description: Returns true if the value has changed since the last
00069 //               call to has_changed().  last_frame is the frame
00070 //               number of the last call; this_frame is the current
00071 //               frame number.
00072 ////////////////////////////////////////////////////////////////////
00073 bool AnimChannelScalarTable::
00074 has_changed(int last_frame, double last_frac, 
00075             int this_frame, double this_frac) {
00076   if (_table.size() > 1) {
00077     if (last_frame != this_frame) {
00078       if (_table[last_frame % _table.size()] != 
00079           _table[this_frame % _table.size()]) {
00080         return true;
00081       }
00082     }
00083     if (last_frac != this_frac) {
00084       // If we have some fractional changes, also check the next
00085       // subsequent frame (since we'll be blending with that).
00086       if (_table[last_frame % _table.size()] != 
00087           _table[(this_frame + 1) % _table.size()]) {
00088         return true;
00089       }
00090     }
00091   }
00092 
00093   return false;
00094 }
00095 
00096 ////////////////////////////////////////////////////////////////////
00097 //     Function: AnimChannelScalarTable::get_value
00098 //       Access: Public, Virtual
00099 //  Description: Gets the value of the channel at the indicated frame.
00100 ////////////////////////////////////////////////////////////////////
00101 void AnimChannelScalarTable::
00102 get_value(int frame, PN_stdfloat &value) {
00103   if (_table.empty()) {
00104     value = 0.0f;
00105   } else {
00106     value = _table[frame % _table.size()];
00107   }
00108 }
00109 
00110 
00111 ////////////////////////////////////////////////////////////////////
00112 //     Function: AnimChannelScalarTable::set_table
00113 //       Access: Public
00114 //  Description: Assigns the data table.
00115 ////////////////////////////////////////////////////////////////////
00116 void AnimChannelScalarTable::
00117 set_table(const CPTA_stdfloat &table) {
00118   int num_frames = _root->get_num_frames();
00119 
00120   if (table.size() > 1 && (int)table.size() < num_frames) {
00121     // The new table has an invalid number of frames--it doesn't match
00122     // the bundle's requirement.
00123     nassertv(false);
00124     return;
00125   }
00126 
00127   _table = table;
00128 }
00129 
00130 ////////////////////////////////////////////////////////////////////
00131 //     Function: AnimChannelScalarTable::write
00132 //       Access: Public, Virtual
00133 //  Description: Writes a brief description of the table and all of
00134 //               its descendants.
00135 ////////////////////////////////////////////////////////////////////
00136 void AnimChannelScalarTable::
00137 write(ostream &out, int indent_level) const {
00138   indent(out, indent_level)
00139     << get_type() << " " << get_name() << " " << _table.size();
00140 
00141   if (!_children.empty()) {
00142     out << " {\n";
00143     write_descendants(out, indent_level + 2);
00144     indent(out, indent_level) << "}";
00145   }
00146 
00147   out << "\n";
00148 }
00149 
00150 ////////////////////////////////////////////////////////////////////
00151 //     Function: AnimChannelScalarTable::make_copy
00152 //       Access: Protected, Virtual
00153 //  Description: Returns a copy of this object, and attaches it to the
00154 //               indicated parent (which may be NULL only if this is
00155 //               an AnimBundle).  Intended to be called by
00156 //               copy_subtree() only.
00157 ////////////////////////////////////////////////////////////////////
00158 AnimGroup *AnimChannelScalarTable::
00159 make_copy(AnimGroup *parent) const {
00160   return new AnimChannelScalarTable(parent, *this);
00161 }
00162 
00163 ////////////////////////////////////////////////////////////////////
00164 //     Function: AnimChannelScalarTable::write_datagram
00165 //       Access: Public
00166 //  Description: Function to write the important information in
00167 //               the particular object to a Datagram
00168 ////////////////////////////////////////////////////////////////////
00169 void AnimChannelScalarTable::
00170 write_datagram(BamWriter *manager, Datagram &me) {
00171   AnimChannelScalar::write_datagram(manager, me);
00172 
00173   if (compress_channels && !FFTCompressor::is_compression_available()) {
00174     chan_cat.error()
00175       << "Compression is not available; writing uncompressed channels.\n";
00176     compress_channels = false;
00177   }
00178 
00179   me.add_bool(compress_channels);
00180   if (!compress_channels) {
00181     // Write out everything the old way, as floats.
00182     me.add_uint16(_table.size());
00183     for(int i = 0; i < (int)_table.size(); i++) {
00184       me.add_stdfloat(_table[i]);
00185     }
00186 
00187   } else {
00188     // Some channels, particularly blink channels, may involve only a
00189     // small number of discrete values.  If we come across one of
00190     // those, write it out losslessly, since the lossy compression
00191     // could damage it significantly (and we can achieve better
00192     // compression directly anyway).  We consider the channel value
00193     // only to the nearest 1000th for this purpose, because floats
00194     // aren't very good at being precisely equal to each other.
00195     static const int max_values = 16;
00196     static const PN_stdfloat scale = 1000.0f;
00197 
00198     pmap<int, int> index;
00199     int i;
00200     for (i = 0;
00201          i < (int)_table.size() && (int)index.size() <= max_values;
00202          i++) {
00203       int value = (int)cfloor(_table[i] * scale + 0.5f);
00204       index.insert(pmap<int, int>::value_type(value, index.size()));
00205     }
00206     int index_length = index.size();
00207     if (index_length <= max_values) {
00208       // All right, here's a blink channel.  Now we write out the
00209       // index table, and then a table of all the index values, two
00210       // per byte.
00211       me.add_uint8(index_length);
00212 
00213       if (index_length > 0) {
00214         // We need to write the index in order by its index number; for
00215         // this, we need to invert the index.
00216         vector_stdfloat reverse_index(index_length);
00217         pmap<int, int>::iterator mi;
00218         for (mi = index.begin(); mi != index.end(); ++mi) {
00219           PN_stdfloat f = (PN_stdfloat)(*mi).first / scale;
00220           int i = (*mi).second;
00221           nassertv(i >= 0 && i < (int)reverse_index.size());
00222           reverse_index[i] = f;
00223         }
00224 
00225         for (i = 0; i < index_length; i++) {
00226           me.add_stdfloat(reverse_index[i]);
00227         }
00228 
00229         // Now write out the actual channels.  We write these two at a
00230         // time, in the high and low nibbles of each byte.
00231         int table_length = _table.size();
00232         me.add_uint16(table_length);
00233 
00234         if (index_length == 1) {
00235           // In fact, we don't even need to write the channels at all,
00236           // if there weren't at least two different values.
00237 
00238         } else {
00239           for (i = 0; i < table_length - 1; i+= 2) {
00240             int value1 = (int)cfloor(_table[i] * scale + 0.5f);
00241             int value2 = (int)cfloor(_table[i + 1] * scale + 0.5f);
00242             int i1 = index[value1];
00243             int i2 = index[value2];
00244 
00245             me.add_uint8((i1 << 4) | i2);
00246           }
00247 
00248           // There might be one odd value.
00249           if (i < table_length) {
00250             int value1 = (int)cfloor(_table[i] * scale + 0.5f);
00251             int i1 = index[value1];
00252 
00253             me.add_uint8(i1 << 4);
00254           }
00255         }
00256       }
00257 
00258     } else {
00259       // No, we have continuous channels.  Write them out using lossy
00260       // compression.
00261       me.add_uint8(0xff);
00262 
00263       FFTCompressor compressor;
00264       compressor.set_quality(compress_chan_quality);
00265       compressor.set_use_error_threshold(true);
00266       compressor.write_header(me);
00267 
00268       compressor.write_reals(me, _table, _table.size());
00269     }
00270   }
00271 }
00272 
00273 ////////////////////////////////////////////////////////////////////
00274 //     Function: AnimChannelScalarTable::fillin
00275 //       Access: Protected
00276 //  Description: Function that reads out of the datagram (or asks
00277 //               manager to read) all of the data that is needed to
00278 //               re-create this object and stores it in the appropiate
00279 //               place
00280 ////////////////////////////////////////////////////////////////////
00281 void AnimChannelScalarTable::
00282 fillin(DatagramIterator& scan, BamReader* manager) {
00283   AnimChannelScalar::fillin(scan, manager);
00284 
00285   bool wrote_compressed = scan.get_bool();
00286 
00287   PTA_stdfloat temp_table = PTA_stdfloat::empty_array(0, get_class_type());
00288 
00289   if (!wrote_compressed) {
00290     // Regular floats.
00291     int size = scan.get_uint16();
00292     for(int i = 0; i < size; i++) {
00293       temp_table.push_back(scan.get_stdfloat());
00294     }
00295 
00296   } else {
00297     // Compressed channels.
00298     // Did we write them as discrete or continuous channel values?
00299     int index_length = scan.get_uint8();
00300 
00301     if (index_length < 0xff) {
00302       // Discrete.  Read in the index.
00303       if (index_length > 0) {
00304         PN_stdfloat *index = (PN_stdfloat *)alloca(index_length * sizeof(PN_stdfloat));
00305 
00306         int i;
00307         for (i = 0; i < index_length; i++) {
00308           index[i] = scan.get_stdfloat();
00309         }
00310 
00311         // Now read in the channel values.
00312         int table_length = scan.get_uint16();
00313         if (index_length == 1) {
00314           // With only one index value, we can infer the table.
00315           for (i = 0; i < table_length; i++) {
00316             temp_table.push_back(index[0]);
00317           }
00318         } else {
00319           // Otherwise, we must read it.
00320           for (i = 0; i < table_length - 1; i+= 2) {
00321             int num = scan.get_uint8();
00322             int i1 = (num >> 4) & 0xf;
00323             int i2 = num & 0xf;
00324             temp_table.push_back(index[i1]);
00325             temp_table.push_back(index[i2]);
00326           }
00327           // There might be one odd value.
00328           if (i < table_length) {
00329             int num = scan.get_uint8();
00330             int i1 = (num >> 4) & 0xf;
00331             temp_table.push_back(index[i1]);
00332           }
00333         }
00334       }
00335     } else {
00336       // Continuous channels.
00337       FFTCompressor compressor;
00338       compressor.read_header(scan, manager->get_file_minor_ver());
00339       compressor.read_reals(scan, temp_table.v());
00340     }
00341   }
00342 
00343   _table = temp_table;
00344 }
00345 
00346 ////////////////////////////////////////////////////////////////////
00347 //     Function: AnimChannelScalarTable::make_AnimChannelScalarTable
00348 //       Access: Protected
00349 //  Description: Factory method to generate a AnimChannelScalarTable object
00350 ////////////////////////////////////////////////////////////////////
00351 TypedWritable* AnimChannelScalarTable::
00352 make_AnimChannelScalarTable(const FactoryParams &params) {
00353   AnimChannelScalarTable *me = new AnimChannelScalarTable;
00354   DatagramIterator scan;
00355   BamReader *manager;
00356 
00357   parse_params(params, scan, manager);
00358   me->fillin(scan, manager);
00359   return me;
00360 }
00361 
00362 ////////////////////////////////////////////////////////////////////
00363 //     Function: AnimChannelScalarTable::register_with_factory
00364 //       Access: Public, Static
00365 //  Description: Factory method to generate a AnimChannelScalarTable object
00366 ////////////////////////////////////////////////////////////////////
00367 void AnimChannelScalarTable::
00368 register_with_read_factory() {
00369   BamReader::get_factory()->register_factory(get_class_type(), make_AnimChannelScalarTable);
00370 }
00371 
00372 
00373 
00374 
 All Classes Functions Variables Enumerations