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 bam_filename.unlink(); 00226 if (!_dout.open(bam_filename)) { 00227 if (report_errors) { 00228 loader_cat.error() << "Unable to open " << bam_filename << "\n"; 00229 } 00230 return false; 00231 } 00232 00233 return continue_open_write(bam_filename, report_errors); 00234 } 00235 00236 //////////////////////////////////////////////////////////////////// 00237 // Function: BamFile::open_write 00238 // Access: Public 00239 // Description: Attempts to open the indicated stream for writing. 00240 // The filename is just for information purposes only. 00241 // Returns true if successful, false on error. 00242 //////////////////////////////////////////////////////////////////// 00243 bool BamFile:: 00244 open_write(ostream &out, const string &bam_filename, bool report_errors) { 00245 close(); 00246 00247 if (!_dout.open(out)) { 00248 loader_cat.error() << "Could not write bam: " << bam_filename << "\n"; 00249 return false; 00250 } 00251 00252 return continue_open_write(bam_filename, report_errors); 00253 } 00254 00255 //////////////////////////////////////////////////////////////////// 00256 // Function: BamFile::write_object 00257 // Access: Public 00258 // Description: Writes the indicated object to the Bam file. Returns 00259 // true if successful, false on error. 00260 //////////////////////////////////////////////////////////////////// 00261 bool BamFile:: 00262 write_object(const TypedWritable *object) { 00263 if (_writer == (BamWriter *)NULL) { 00264 return false; 00265 } 00266 00267 if (!_writer->write_object(object)) { 00268 close(); 00269 return false; 00270 } 00271 00272 return true; 00273 } 00274 00275 //////////////////////////////////////////////////////////////////// 00276 // Function: BamFile::close 00277 // Access: Public 00278 // Description: Closes the input or output stream. 00279 //////////////////////////////////////////////////////////////////// 00280 void BamFile:: 00281 close() { 00282 if (_reader != (BamReader *)NULL) { 00283 // resolve(); 00284 delete _reader; 00285 _reader = NULL; 00286 } 00287 if (_writer != (BamWriter *)NULL) { 00288 delete _writer; 00289 _writer = NULL; 00290 } 00291 _din.close(); 00292 _dout.close(); 00293 } 00294 00295 00296 //////////////////////////////////////////////////////////////////// 00297 // Function: BamFile::get_file_major_ver 00298 // Access: Public 00299 // Description: Returns the major version number of the file 00300 // currently being read, or the system current major 00301 // version number if no file is currently open for 00302 // reading. 00303 //////////////////////////////////////////////////////////////////// 00304 int BamFile:: 00305 get_file_major_ver() { 00306 if (_reader == (BamReader *)NULL) { 00307 return _bam_major_ver; 00308 } 00309 return _reader->get_file_major_ver(); 00310 } 00311 00312 //////////////////////////////////////////////////////////////////// 00313 // Function: BamFile::get_file_minor_ver 00314 // Access: Public 00315 // Description: Returns the minor version number of the file 00316 // currently being read, or the system current minor 00317 // version number if no file is currently open for 00318 // reading. 00319 //////////////////////////////////////////////////////////////////// 00320 int BamFile:: 00321 get_file_minor_ver() { 00322 if (_reader == (BamReader *)NULL) { 00323 return _bam_minor_ver; 00324 } 00325 return _reader->get_file_minor_ver(); 00326 } 00327 00328 //////////////////////////////////////////////////////////////////// 00329 // Function: BamFile::get_file_endian 00330 // Access: Public 00331 // Description: Returns the endian preference indicated by the Bam 00332 // file currently being read or written. 00333 //////////////////////////////////////////////////////////////////// 00334 BamFile::BamEndian BamFile:: 00335 get_file_endian() const { 00336 if (_writer != (BamWriter *)NULL) { 00337 return _writer->get_file_endian(); 00338 } 00339 if (_reader != (BamReader *)NULL) { 00340 return _reader->get_file_endian(); 00341 } 00342 00343 return bam_endian; 00344 } 00345 00346 //////////////////////////////////////////////////////////////////// 00347 // Function: BamFile::get_current_major_ver 00348 // Access: Public 00349 // Description: Returns the system current major version number. 00350 // This is the version number that will be assigned to 00351 // any generated Bam files. 00352 //////////////////////////////////////////////////////////////////// 00353 int BamFile:: 00354 get_current_major_ver() { 00355 return _bam_major_ver; 00356 } 00357 00358 //////////////////////////////////////////////////////////////////// 00359 // Function: BamFile::get_current_minor_ver 00360 // Access: Public 00361 // Description: Returns the system current minor version number. 00362 // This is the version number that will be assigned to 00363 // any generated Bam files. 00364 //////////////////////////////////////////////////////////////////// 00365 int BamFile:: 00366 get_current_minor_ver() { 00367 return _bam_minor_ver; 00368 } 00369 00370 //////////////////////////////////////////////////////////////////// 00371 // Function: BamFile::get_reader 00372 // Access: Public 00373 // Description: Returns the BamReader in charge of performing the 00374 // read operations. This will return NULL unless 00375 // open_read() was called. 00376 //////////////////////////////////////////////////////////////////// 00377 BamReader *BamFile:: 00378 get_reader() { 00379 return _reader; 00380 } 00381 00382 //////////////////////////////////////////////////////////////////// 00383 // Function: BamFile::get_writer 00384 // Access: Public 00385 // Description: Returns the BamWriter in charge of performing the 00386 // write operations. This will return NULL unless 00387 // open_write() was called. 00388 //////////////////////////////////////////////////////////////////// 00389 BamWriter *BamFile:: 00390 get_writer() { 00391 return _writer; 00392 } 00393 00394 //////////////////////////////////////////////////////////////////// 00395 // Function: BamFile::continue_open_read 00396 // Access: Private 00397 // Description: Reads the header of the recently-opened bam stream 00398 // and prepares to read the contents of the file. 00399 // Returns true if successful, false otherwise. 00400 //////////////////////////////////////////////////////////////////// 00401 bool BamFile:: 00402 continue_open_read(const string &bam_filename, bool report_errors) { 00403 _bam_filename = bam_filename; 00404 00405 string head; 00406 if (!_din.read_header(head, _bam_header.size())) { 00407 if (report_errors) { 00408 loader_cat.error() << _bam_filename << " is not a valid BAM file.\n"; 00409 } 00410 return false; 00411 } 00412 00413 if (head != _bam_header) { 00414 if (report_errors) { 00415 loader_cat.error() << _bam_filename << " is not a valid BAM file.\n"; 00416 } 00417 return false; 00418 } 00419 00420 _reader = new BamReader(&_din, _bam_filename); 00421 if (!_reader->init()) { 00422 close(); 00423 return false; 00424 } 00425 00426 return true; 00427 } 00428 00429 //////////////////////////////////////////////////////////////////// 00430 // Function: BamFile::continue_open_write 00431 // Access: Private 00432 // Description: Writers the header of the recently-opened bam stream 00433 // and prepares to write the contents of the file. 00434 // Returns true if successful, false otherwise. 00435 //////////////////////////////////////////////////////////////////// 00436 bool BamFile:: 00437 continue_open_write(const string &bam_filename, bool report_errors) { 00438 _bam_filename = bam_filename; 00439 00440 if (!_dout.write_header(_bam_header)) { 00441 if (report_errors) { 00442 loader_cat.error() << "Unable to write to " << _bam_filename << "\n"; 00443 } 00444 return false; 00445 } 00446 00447 _writer = new BamWriter(&_dout, _bam_filename); 00448 00449 if (!_writer->init()) { 00450 close(); 00451 return false; 00452 } 00453 00454 return true; 00455 }