Panda3D
|
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 ©) : 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 ¶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 // 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