Panda3D
|
00001 // Filename: bamFile.cxx 00002 // Created by: drose (02Jul00) 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 #include "bamFile.h" 00016 #include "config_pgraph.h" 00017 00018 #include "bam.h" 00019 #include "bamCacheRecord.h" 00020 #include "config_util.h" 00021 #include "bamReader.h" 00022 #include "bamWriter.h" 00023 #include "filename.h" 00024 #include "config_express.h" 00025 #include "virtualFileSystem.h" 00026 #include "dcast.h" 00027 00028 //////////////////////////////////////////////////////////////////// 00029 // Function: BamFile::Constructor 00030 // Access: Public 00031 // Description: 00032 //////////////////////////////////////////////////////////////////// 00033 BamFile:: 00034 BamFile() { 00035 _reader = NULL; 00036 _writer = NULL; 00037 } 00038 00039 //////////////////////////////////////////////////////////////////// 00040 // Function: BamFile::Destructor 00041 // Access: Public 00042 // Description: 00043 //////////////////////////////////////////////////////////////////// 00044 BamFile:: 00045 ~BamFile() { 00046 close(); 00047 } 00048 00049 //////////////////////////////////////////////////////////////////// 00050 // Function: BamFile::open_read 00051 // Access: Public 00052 // Description: Attempts to open the indicated filename for reading. 00053 // Returns true if successful, false on error. 00054 //////////////////////////////////////////////////////////////////// 00055 bool BamFile:: 00056 open_read(const Filename &bam_filename, bool report_errors) { 00057 close(); 00058 00059 if (!_din.open(bam_filename)) { 00060 return false; 00061 } 00062 00063 loader_cat.info() 00064 << "Reading " << bam_filename << "\n"; 00065 00066 return continue_open_read(bam_filename, report_errors); 00067 } 00068 00069 //////////////////////////////////////////////////////////////////// 00070 // Function: BamFile::open_read 00071 // Access: Public 00072 // Description: Attempts to open the indicated stream for reading. 00073 // The filename is just for information purposes only. 00074 // Returns true if successful, false on error. 00075 //////////////////////////////////////////////////////////////////// 00076 bool BamFile:: 00077 open_read(istream &in, const string &bam_filename, bool report_errors) { 00078 close(); 00079 00080 if (!_din.open(in)) { 00081 return false; 00082 } 00083 00084 return continue_open_read(bam_filename, report_errors); 00085 } 00086 00087 //////////////////////////////////////////////////////////////////// 00088 // Function: BamFile::read_object 00089 // Access: Public 00090 // Description: Reads and returns the next object from the Bam file, 00091 // or NULL if the end of the file has been reached, or 00092 // if there is an error condition. Use is_eof() to 00093 // differentiate these two cases. 00094 // 00095 // The pointers returned by this method will not be 00096 // valid for use until resolve() is subsequently called. 00097 //////////////////////////////////////////////////////////////////// 00098 TypedWritable *BamFile:: 00099 read_object() { 00100 if (_reader == (BamReader *)NULL) { 00101 return NULL; 00102 } 00103 00104 return _reader->read_object(); 00105 } 00106 00107 //////////////////////////////////////////////////////////////////// 00108 // Function: BamFile::is_eof 00109 // Access: Public 00110 // Description: Returns true if the reader has reached end-of-file, 00111 // false otherwise. This call is only valid after a 00112 // call to read_object(). 00113 //////////////////////////////////////////////////////////////////// 00114 bool BamFile:: 00115 is_eof() const { 00116 return _reader != (BamReader *)NULL && _reader->is_eof(); 00117 } 00118 00119 //////////////////////////////////////////////////////////////////// 00120 // Function: BamFile::resolve 00121 // Access: Public 00122 // Description: This must be called after one or more objects have 00123 // been read via calls to read_object() in order to 00124 // resolve all internal pointer references in the 00125 // objects read and make all the pointers valid. It 00126 // returns true if all objects are successfully 00127 // resolved, or false if some have not been (in which 00128 // case you must call resolve() again later). 00129 //////////////////////////////////////////////////////////////////// 00130 bool BamFile:: 00131 resolve() { 00132 if (_reader == (BamReader *)NULL) { 00133 return false; 00134 } 00135 00136 return _reader->resolve(); 00137 } 00138 00139 //////////////////////////////////////////////////////////////////// 00140 // Function: BamFile::read_node 00141 // Access: Public 00142 // Description: Although the bam file format is general enough to 00143 // store a list of objects of arbitrary type, bam files 00144 // on disk usually contain just one object, a PandaNode 00145 // that is the root of a scene graph. (Bam files that 00146 // store other kinds of things are usually given the 00147 // extension "boo", for "binary other objects", to 00148 // differentiate them from the normal scene graph type 00149 // file.) 00150 // 00151 // This is a convenience method for when you believe you 00152 // are reading a scene graph bam file. It reads the one 00153 // PandaNode and returns it. It also calls resolve() to 00154 // fully resolve the object, since we expect this will 00155 // be the only object in the file. 00156 // 00157 // If the bam file contains something other than a 00158 // PandaNode, an error is printed and NULL is returned. 00159 //////////////////////////////////////////////////////////////////// 00160 PT(PandaNode) BamFile:: 00161 read_node(bool report_errors) { 00162 PT(PandaNode) result; 00163 00164 TypedWritable *object = read_object(); 00165 00166 if (object != (TypedWritable *)NULL && 00167 object->is_exact_type(BamCacheRecord::get_class_type())) { 00168 // Here's a special case: if the first object in the file is a 00169 // BamCacheRecord, it's really a cache data file and not a true 00170 // bam file; but skip over the cache data record and let the user 00171 // treat it like an ordinary bam file. 00172 object = read_object(); 00173 } 00174 00175 if (object == TypedWritable::Null) { 00176 if (report_errors) { 00177 loader_cat.error() << "Bam file " << _bam_filename << " is empty.\n"; 00178 } 00179 00180 } else if (!object->is_of_type(PandaNode::get_class_type())) { 00181 if (report_errors) { 00182 loader_cat.error() 00183 << "Bam file " << _bam_filename 00184 << " contains a " << object->get_type() << ", not a PandaNode.\n"; 00185 } 00186 00187 } else { 00188 result = DCAST(PandaNode, object); 00189 00190 if (report_errors) { 00191 read_object(); 00192 if (!is_eof()) { 00193 loader_cat.warning() 00194 << "Ignoring extra objects in " << _bam_filename << "\n"; 00195 } 00196 } 00197 } 00198 00199 if (!resolve()) { 00200 if (report_errors) { 00201 loader_cat.error() 00202 << "Unable to resolve Bam file.\n"; 00203 } 00204 result = (PandaNode *)NULL; 00205 } 00206 00207 return result; 00208 } 00209 00210 00211 //////////////////////////////////////////////////////////////////// 00212 // Function: BamFile::open_write 00213 // Access: Public 00214 // Description: Attempts to open the indicated file for writing. If 00215 // another file by the same name already exists, it will 00216 // be silently removed. Returns true if successful, 00217 // false otherwise. 00218 //////////////////////////////////////////////////////////////////// 00219 bool BamFile:: 00220 open_write(const Filename &bam_filename, bool report_errors) { 00221 close(); 00222 00223 loader_cat.info() << "Writing " << bam_filename << "\n"; 00224 00225 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); 00226 vfs->delete_file(bam_filename); 00227 if (!_dout.open(bam_filename)) { 00228 if (report_errors) { 00229 loader_cat.error() << "Unable to open " << bam_filename << "\n"; 00230 } 00231 return false; 00232 } 00233 00234 return continue_open_write(bam_filename, report_errors); 00235 } 00236 00237 //////////////////////////////////////////////////////////////////// 00238 // Function: BamFile::open_write 00239 // Access: Public 00240 // Description: Attempts to open the indicated stream for writing. 00241 // The filename is just for information purposes only. 00242 // Returns true if successful, false on error. 00243 //////////////////////////////////////////////////////////////////// 00244 bool BamFile:: 00245 open_write(ostream &out, const string &bam_filename, bool report_errors) { 00246 close(); 00247 00248 if (!_dout.open(out)) { 00249 loader_cat.error() << "Could not write bam: " << bam_filename << "\n"; 00250 return false; 00251 } 00252 00253 return continue_open_write(bam_filename, report_errors); 00254 } 00255 00256 //////////////////////////////////////////////////////////////////// 00257 // Function: BamFile::write_object 00258 // Access: Public 00259 // Description: Writes the indicated object to the Bam file. Returns 00260 // true if successful, false on error. 00261 //////////////////////////////////////////////////////////////////// 00262 bool BamFile:: 00263 write_object(const TypedWritable *object) { 00264 if (_writer == (BamWriter *)NULL) { 00265 return false; 00266 } 00267 00268 if (!_writer->write_object(object)) { 00269 close(); 00270 return false; 00271 } 00272 00273 return true; 00274 } 00275 00276 //////////////////////////////////////////////////////////////////// 00277 // Function: BamFile::close 00278 // Access: Public 00279 // Description: Closes the input or output stream. 00280 //////////////////////////////////////////////////////////////////// 00281 void BamFile:: 00282 close() { 00283 if (_reader != (BamReader *)NULL) { 00284 // resolve(); 00285 delete _reader; 00286 _reader = NULL; 00287 } 00288 if (_writer != (BamWriter *)NULL) { 00289 delete _writer; 00290 _writer = NULL; 00291 } 00292 _din.close(); 00293 _dout.close(); 00294 } 00295 00296 00297 //////////////////////////////////////////////////////////////////// 00298 // Function: BamFile::get_file_major_ver 00299 // Access: Public 00300 // Description: Returns the major version number of the file 00301 // currently being read, or the system current major 00302 // version number if no file is currently open for 00303 // reading. 00304 //////////////////////////////////////////////////////////////////// 00305 int BamFile:: 00306 get_file_major_ver() { 00307 if (_reader == (BamReader *)NULL) { 00308 return _bam_major_ver; 00309 } 00310 return _reader->get_file_major_ver(); 00311 } 00312 00313 //////////////////////////////////////////////////////////////////// 00314 // Function: BamFile::get_file_minor_ver 00315 // Access: Public 00316 // Description: Returns the minor version number of the file 00317 // currently being read, or the system current minor 00318 // version number if no file is currently open for 00319 // reading. 00320 //////////////////////////////////////////////////////////////////// 00321 int BamFile:: 00322 get_file_minor_ver() { 00323 if (_reader == (BamReader *)NULL) { 00324 return _bam_minor_ver; 00325 } 00326 return _reader->get_file_minor_ver(); 00327 } 00328 00329 //////////////////////////////////////////////////////////////////// 00330 // Function: BamFile::get_file_endian 00331 // Access: Public 00332 // Description: Returns the endian preference indicated by the Bam 00333 // file currently being read or written. 00334 //////////////////////////////////////////////////////////////////// 00335 BamFile::BamEndian BamFile:: 00336 get_file_endian() const { 00337 if (_writer != (BamWriter *)NULL) { 00338 return _writer->get_file_endian(); 00339 } 00340 if (_reader != (BamReader *)NULL) { 00341 return _reader->get_file_endian(); 00342 } 00343 00344 return bam_endian; 00345 } 00346 00347 //////////////////////////////////////////////////////////////////// 00348 // Function: BamFile::get_file_stdfloat_double 00349 // Access: Public 00350 // Description: Returns true if the file stores all "standard" 00351 // floats as 64-bit doubles, or false if they are 32-bit 00352 // floats. 00353 //////////////////////////////////////////////////////////////////// 00354 bool BamFile:: 00355 get_file_stdfloat_double() const { 00356 if (_writer != (BamWriter *)NULL) { 00357 return _writer->get_file_stdfloat_double(); 00358 } 00359 if (_reader != (BamReader *)NULL) { 00360 return _reader->get_file_stdfloat_double(); 00361 } 00362 00363 return bam_stdfloat_double; 00364 } 00365 00366 //////////////////////////////////////////////////////////////////// 00367 // Function: BamFile::get_current_major_ver 00368 // Access: Public 00369 // Description: Returns the system current major version number. 00370 // This is the version number that will be assigned to 00371 // any generated Bam files. 00372 //////////////////////////////////////////////////////////////////// 00373 int BamFile:: 00374 get_current_major_ver() { 00375 return _bam_major_ver; 00376 } 00377 00378 //////////////////////////////////////////////////////////////////// 00379 // Function: BamFile::get_current_minor_ver 00380 // Access: Public 00381 // Description: Returns the system current minor version number. 00382 // This is the version number that will be assigned to 00383 // any generated Bam files. 00384 //////////////////////////////////////////////////////////////////// 00385 int BamFile:: 00386 get_current_minor_ver() { 00387 return _bam_minor_ver; 00388 } 00389 00390 //////////////////////////////////////////////////////////////////// 00391 // Function: BamFile::get_reader 00392 // Access: Public 00393 // Description: Returns the BamReader in charge of performing the 00394 // read operations. This will return NULL unless 00395 // open_read() was called. 00396 //////////////////////////////////////////////////////////////////// 00397 BamReader *BamFile:: 00398 get_reader() { 00399 return _reader; 00400 } 00401 00402 //////////////////////////////////////////////////////////////////// 00403 // Function: BamFile::get_writer 00404 // Access: Public 00405 // Description: Returns the BamWriter in charge of performing the 00406 // write operations. This will return NULL unless 00407 // open_write() was called. 00408 //////////////////////////////////////////////////////////////////// 00409 BamWriter *BamFile:: 00410 get_writer() { 00411 return _writer; 00412 } 00413 00414 //////////////////////////////////////////////////////////////////// 00415 // Function: BamFile::continue_open_read 00416 // Access: Private 00417 // Description: Reads the header of the recently-opened bam stream 00418 // and prepares to read the contents of the file. 00419 // Returns true if successful, false otherwise. 00420 //////////////////////////////////////////////////////////////////// 00421 bool BamFile:: 00422 continue_open_read(const string &bam_filename, bool report_errors) { 00423 _bam_filename = bam_filename; 00424 00425 string head; 00426 if (!_din.read_header(head, _bam_header.size())) { 00427 if (report_errors) { 00428 loader_cat.error() << _bam_filename << " is not a valid BAM file.\n"; 00429 } 00430 return false; 00431 } 00432 00433 if (head != _bam_header) { 00434 if (report_errors) { 00435 loader_cat.error() << _bam_filename << " is not a valid BAM file.\n"; 00436 } 00437 return false; 00438 } 00439 00440 _reader = new BamReader(&_din); 00441 if (!_reader->init()) { 00442 close(); 00443 return false; 00444 } 00445 00446 return true; 00447 } 00448 00449 //////////////////////////////////////////////////////////////////// 00450 // Function: BamFile::continue_open_write 00451 // Access: Private 00452 // Description: Writers the header of the recently-opened bam stream 00453 // and prepares to write the contents of the file. 00454 // Returns true if successful, false otherwise. 00455 //////////////////////////////////////////////////////////////////// 00456 bool BamFile:: 00457 continue_open_write(const string &bam_filename, bool report_errors) { 00458 _bam_filename = bam_filename; 00459 00460 if (!_dout.write_header(_bam_header)) { 00461 if (report_errors) { 00462 loader_cat.error() << "Unable to write to " << _bam_filename << "\n"; 00463 } 00464 return false; 00465 } 00466 00467 _writer = new BamWriter(&_dout); 00468 00469 if (!_writer->init()) { 00470 close(); 00471 return false; 00472 } 00473 00474 return true; 00475 }