00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
00035
00036
00037
00038 AnimChannelScalarTable::
00039 AnimChannelScalarTable(AnimGroup *parent, const string &name)
00040 : AnimChannelScalar(parent, name) {
00041 }
00042
00043
00044
00045
00046
00047
00048 AnimChannelScalarTable::
00049 AnimChannelScalarTable(void){
00050 }
00051
00052
00053
00054
00055
00056
00057
00058
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
00074
00075
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
00089
00090
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
00098
00099 return;
00100 }
00101
00102 _table = table;
00103 }
00104
00105
00106
00107
00108
00109
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
00127
00128
00129
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
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
00152
00153
00154
00155
00156
00157
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
00172
00173
00174 me.add_uint8(index_length);
00175
00176 if (index_length > 0) {
00177
00178
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
00193
00194 int table_length = _table.size();
00195 me.add_uint16(table_length);
00196
00197 if (index_length == 1) {
00198
00199
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
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
00223
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
00237
00238
00239
00240
00241
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
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
00261
00262 int index_length = scan.get_uint8();
00263
00264 if (index_length < 0xff) {
00265
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
00275 int table_length = scan.get_uint16();
00276 if (index_length == 1) {
00277
00278 for (i = 0; i < table_length; i++) {
00279 temp_table.push_back(index[0]);
00280 }
00281 } else {
00282
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
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
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
00311
00312
00313
00314 TypedWritable* AnimChannelScalarTable::
00315 make_AnimChannelScalarTable(const FactoryParams ¶ms)
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
00328
00329
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