00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
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
00031
00032
00033
00034 AnimChannelScalarTable::
00035 AnimChannelScalarTable() : _table(get_class_type()) {
00036 }
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 AnimChannelScalarTable::
00047 AnimChannelScalarTable(AnimGroup *parent, const AnimChannelScalarTable ©) :
00048 AnimChannelScalar(parent, copy),
00049 _table(copy._table)
00050 {
00051 }
00052
00053
00054
00055
00056
00057
00058 AnimChannelScalarTable::
00059 AnimChannelScalarTable(AnimGroup *parent, const string &name) :
00060 AnimChannelScalar(parent, name),
00061 _table(get_class_type())
00062 {
00063 }
00064
00065
00066
00067
00068
00069
00070
00071
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
00085
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
00098
00099
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
00113
00114
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
00122
00123 nassertv(false);
00124 return;
00125 }
00126
00127 _table = table;
00128 }
00129
00130
00131
00132
00133
00134
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
00152
00153
00154
00155
00156
00157
00158 AnimGroup *AnimChannelScalarTable::
00159 make_copy(AnimGroup *parent) const {
00160 return new AnimChannelScalarTable(parent, *this);
00161 }
00162
00163
00164
00165
00166
00167
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
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
00189
00190
00191
00192
00193
00194
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
00209
00210
00211 me.add_uint8(index_length);
00212
00213 if (index_length > 0) {
00214
00215
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
00230
00231 int table_length = _table.size();
00232 me.add_uint16(table_length);
00233
00234 if (index_length == 1) {
00235
00236
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
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
00260
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
00275
00276
00277
00278
00279
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
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
00298
00299 int index_length = scan.get_uint8();
00300
00301 if (index_length < 0xff) {
00302
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
00312 int table_length = scan.get_uint16();
00313 if (index_length == 1) {
00314
00315 for (i = 0; i < table_length; i++) {
00316 temp_table.push_back(index[0]);
00317 }
00318 } else {
00319
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
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
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
00348
00349
00350
00351 TypedWritable* AnimChannelScalarTable::
00352 make_AnimChannelScalarTable(const FactoryParams ¶ms) {
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
00364
00365
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