Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/chan/animChannelScalarTable.cxx

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

Generated on Fri May 2 00:35:01 2003 for Panda by doxygen1.3