Panda3D
|
00001 // Filename: fltHeader.cxx 00002 // Created by: drose (24Aug00) 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 "fltHeader.h" 00016 #include "fltRecordReader.h" 00017 #include "fltRecordWriter.h" 00018 #include "fltUnsupportedRecord.h" 00019 #include "config_flt.h" 00020 #include "zStream.h" 00021 #include "nearly_zero.h" 00022 #include "virtualFileSystem.h" 00023 00024 #include <assert.h> 00025 #include <math.h> 00026 00027 TypeHandle FltHeader::_type_handle; 00028 00029 //////////////////////////////////////////////////////////////////// 00030 // Function: FltHeader::Constructor 00031 // Access: Public 00032 // Description: The FltHeader constructor accepts a PathReplace 00033 // pointer; it uses this object to automatically convert 00034 // all external filename and texture references. (This 00035 // is necessary because the FltHeader has to look in the 00036 // same directory as the texture to find the .attr file, 00037 // so it must pre-convert at least the texture 00038 // references.) 00039 // 00040 // Most of the other file converters do not have this 00041 // requirement, so they do not need to pre-convert any 00042 // pathname references. 00043 //////////////////////////////////////////////////////////////////// 00044 FltHeader:: 00045 FltHeader(PathReplace *path_replace) : FltBeadID(this) { 00046 if (path_replace == (PathReplace *)NULL) { 00047 _path_replace = new PathReplace; 00048 _path_replace->_path_store = PS_absolute; 00049 } else { 00050 _path_replace = path_replace; 00051 } 00052 00053 _format_revision_level = 1570; 00054 _edit_revision_level = 1570; 00055 _next_group_id = 1; 00056 _next_lod_id = 1; 00057 _next_object_id = 1; 00058 _next_face_id = 1; 00059 _unit_multiplier = 1; 00060 _vertex_units = U_feet; 00061 _texwhite_new = false; 00062 _flags = 0; 00063 _projection_type = PT_flat_earth; 00064 _next_dof_id = 1; 00065 _vertex_storage_type = VTS_double; 00066 _database_origin = DO_open_flight; 00067 _sw_x = 0.0; 00068 _sw_y = 0.0; 00069 _delta_x = 0.0; 00070 _delta_y = 0.0; 00071 _next_sound_id = 1; 00072 _next_path_id = 1; 00073 _next_clip_id = 1; 00074 _next_text_id = 1; 00075 _next_bsp_id = 1; 00076 _next_switch_id = 1; 00077 _sw_lat = 0.0; 00078 _sw_long = 0.0; 00079 _ne_lat = 0.0; 00080 _ne_long = 0.0; 00081 _origin_lat = 0.0; 00082 _origin_long = 0.0; 00083 _lambert_upper_lat = 0.0; 00084 _lambert_lower_lat = 0.0; 00085 _next_light_id = 1; 00086 _next_road_id = 1; 00087 _next_cat_id = 1; 00088 00089 // New with 15.2 00090 _earth_model = EM_wgs84; 00091 00092 // New with 15.6 00093 _next_adaptive_id = 0; 00094 _next_curve_id = 0; 00095 00096 // New with 15.7 00097 _delta_z = 0.0; 00098 _radius = 0.0; 00099 _next_mesh_id = 0; 00100 00101 _vertex_lookups_stale = false; 00102 _current_vertex_offset = 0; 00103 _next_material_index = 1; 00104 _next_pattern_index = 1; 00105 _got_color_palette = false; 00106 _got_14_material_palette = false; 00107 _got_eyepoint_trackplane_palette = false; 00108 00109 _auto_attr_update = AU_if_missing; 00110 } 00111 00112 //////////////////////////////////////////////////////////////////// 00113 // Function: FltHeader::apply_converted_filenames 00114 // Access: Public, Virtual 00115 // Description: Walks the hierarchy at this record and below and 00116 // copies the _converted_filename record into the 00117 // _orig_filename record, so the flt file will be 00118 // written out with the converted filename instead of 00119 // what was originally read in. 00120 //////////////////////////////////////////////////////////////////// 00121 void FltHeader:: 00122 apply_converted_filenames() { 00123 Textures::const_iterator ti; 00124 for (ti = _textures.begin(); ti != _textures.end(); ++ti) { 00125 FltTexture *texture = (*ti).second; 00126 texture->apply_converted_filenames(); 00127 } 00128 00129 FltBeadID::apply_converted_filenames(); 00130 } 00131 00132 //////////////////////////////////////////////////////////////////// 00133 // Function: FltHeader::set_path_replace 00134 // Access: Public 00135 // Description: Replaces the PathReplace object (which specifies how 00136 // to mangle paths from the source to the destination 00137 // file) with a new one. 00138 //////////////////////////////////////////////////////////////////// 00139 void FltHeader:: 00140 set_path_replace(PathReplace *path_replace) { 00141 _path_replace = path_replace; 00142 } 00143 00144 //////////////////////////////////////////////////////////////////// 00145 // Function: FltHeader::get_path_replace 00146 // Access: Public 00147 // Description: Returns a pointer to the PathReplace object 00148 // associated with this converter. If the converter is 00149 // non-const, this returns a non-const pointer, which 00150 // can be adjusted. 00151 //////////////////////////////////////////////////////////////////// 00152 PathReplace *FltHeader:: 00153 get_path_replace() { 00154 return _path_replace; 00155 } 00156 00157 //////////////////////////////////////////////////////////////////// 00158 // Function: FltHeader::get_path_replace 00159 // Access: Public 00160 // Description: Returns a pointer to the PathReplace object 00161 // associated with this converter. If the converter is 00162 // non-const, this returns a non-const pointer, which 00163 // can be adjusted. 00164 //////////////////////////////////////////////////////////////////// 00165 const PathReplace *FltHeader:: 00166 get_path_replace() const { 00167 return _path_replace; 00168 } 00169 00170 //////////////////////////////////////////////////////////////////// 00171 // Function: FltHeader::convert_path 00172 // Access: Public 00173 // Description: Uses the PathReplace object to convert the named 00174 // filename as read from the flt record to its actual 00175 // name. 00176 //////////////////////////////////////////////////////////////////// 00177 Filename FltHeader:: 00178 convert_path(const Filename &orig_filename, const DSearchPath &additional_path) { 00179 DSearchPath file_path; 00180 if (!_flt_filename.empty()) { 00181 file_path.append_directory(_flt_filename.get_dirname()); 00182 } 00183 file_path.append_path(additional_path); 00184 return _path_replace->convert_path(orig_filename, file_path); 00185 } 00186 00187 //////////////////////////////////////////////////////////////////// 00188 // Function: FltHeader::set_flt_filename 00189 // Access: Public 00190 // Description: Sets the filename--especially the directory part--in 00191 // which the flt file is considered to reside. This is 00192 // also implicitly set by read_flt(). 00193 //////////////////////////////////////////////////////////////////// 00194 void FltHeader:: 00195 set_flt_filename(const Filename &flt_filename) { 00196 _flt_filename = flt_filename; 00197 } 00198 00199 //////////////////////////////////////////////////////////////////// 00200 // Function: FltHeader::get_flt_filename 00201 // Access: Public 00202 // Description: Returns the directory in which the flt file is 00203 // considered to reside. 00204 //////////////////////////////////////////////////////////////////// 00205 const Filename &FltHeader:: 00206 get_flt_filename() const { 00207 return _flt_filename; 00208 } 00209 00210 //////////////////////////////////////////////////////////////////// 00211 // Function: FltHeader::read_flt 00212 // Access: Public 00213 // Description: Opens the indicated filename for reading and attempts 00214 // to read the complete Flt file. Returns FE_ok on 00215 // success, otherwise on failure. 00216 //////////////////////////////////////////////////////////////////// 00217 FltError FltHeader:: 00218 read_flt(Filename filename) { 00219 filename.set_binary(); 00220 _flt_filename = filename; 00221 00222 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); 00223 istream *in = vfs->open_read_file(filename, true); 00224 if (in == (istream *)NULL) { 00225 assert(!flt_error_abort); 00226 return FE_could_not_open; 00227 } 00228 FltError result = read_flt(*in); 00229 vfs->close_read_file(in); 00230 return result; 00231 } 00232 00233 //////////////////////////////////////////////////////////////////// 00234 // Function: FltHeader::read_flt 00235 // Access: Public 00236 // Description: Attempts to read a complete Flt file from the 00237 // already-opened stream. Returns FE_ok on success, 00238 // otherwise on failure. 00239 //////////////////////////////////////////////////////////////////// 00240 FltError FltHeader:: 00241 read_flt(istream &in) { 00242 FltRecordReader reader(in); 00243 FltError result = reader.advance(); 00244 if (result == FE_end_of_file) { 00245 assert(!flt_error_abort); 00246 return FE_empty_file; 00247 } else if (result != FE_ok) { 00248 return result; 00249 } 00250 00251 result = read_record_and_children(reader); 00252 if (result != FE_ok) { 00253 return result; 00254 } 00255 00256 if (!reader.eof()) { 00257 assert(!flt_error_abort); 00258 return FE_extra_data; 00259 } 00260 00261 return FE_ok; 00262 } 00263 00264 00265 //////////////////////////////////////////////////////////////////// 00266 // Function: FltHeader::write_flt 00267 // Access: Public 00268 // Description: Opens the indicated filename for writing and attempts 00269 // to write the complete Flt file. Returns FE_ok on 00270 // success, otherwise on failure. 00271 //////////////////////////////////////////////////////////////////// 00272 FltError FltHeader:: 00273 write_flt(Filename filename) { 00274 filename.set_binary(); 00275 00276 ofstream out; 00277 if (!filename.open_write(out)) { 00278 assert(!flt_error_abort); 00279 return FE_could_not_open; 00280 } 00281 00282 #ifdef HAVE_ZLIB 00283 if (filename.get_extension() == "pz") { 00284 // The filename ends in .pz, which means to automatically compress 00285 // the flt file that we write. 00286 OCompressStream compressor(&out, false); 00287 return write_flt(compressor); 00288 } 00289 #endif // HAVE_ZLIB 00290 00291 return write_flt(out); 00292 } 00293 00294 //////////////////////////////////////////////////////////////////// 00295 // Function: FltHeader::write_flt 00296 // Access: Public 00297 // Description: Attempts to write a complete Flt file to the 00298 // already-opened stream. Returns FE_ok on success, 00299 // otherwise on failure. 00300 //////////////////////////////////////////////////////////////////// 00301 FltError FltHeader:: 00302 write_flt(ostream &out) { 00303 FltRecordWriter writer(out); 00304 FltError result = write_record_and_children(writer); 00305 00306 if (out.fail()) { 00307 assert(!flt_error_abort); 00308 return FE_write_error; 00309 } 00310 return result; 00311 } 00312 00313 //////////////////////////////////////////////////////////////////// 00314 // Function: FltHeader::set_auto_attr_update 00315 // Access: Public 00316 // Description: Controls whether texture .attr files are written 00317 // automatically when write_flt() is called. There are 00318 // three possibilities: 00319 // 00320 // AU_none: the .attr files are not written 00321 // automatically; they must be written explicitly via a 00322 // call to FltTexture::write_attr_data() if you want 00323 // them to be written. 00324 // 00325 // AU_if_missing: the .attr files are written only if 00326 // they do not already exist. This will not update any 00327 // .attr files, even if the data is changed. 00328 // 00329 // AU_always: the .attr files are always rewritten, even 00330 // if they already exist and even if the data has not 00331 // changed. 00332 // 00333 // The default is AU_if_missing. 00334 //////////////////////////////////////////////////////////////////// 00335 void FltHeader:: 00336 set_auto_attr_update(FltHeader::AttrUpdate attr) { 00337 _auto_attr_update = attr; 00338 } 00339 00340 //////////////////////////////////////////////////////////////////// 00341 // Function: FltHeader::get_auto_attr_update 00342 // Access: Public 00343 // Description: Returns the current setting of the auto_attr_update 00344 // flag. See sett_auto_attr_update(). 00345 //////////////////////////////////////////////////////////////////// 00346 FltHeader::AttrUpdate FltHeader:: 00347 get_auto_attr_update() const { 00348 return _auto_attr_update; 00349 } 00350 00351 //////////////////////////////////////////////////////////////////// 00352 // Function: FltHeader::get_flt_version 00353 // Access: Public 00354 // Description: Returns the version number of the flt file as 00355 // reported in the header, times 100. Divide by 100 to 00356 // get the floating-point version number. 00357 //////////////////////////////////////////////////////////////////// 00358 int FltHeader:: 00359 get_flt_version() const { 00360 if (_format_revision_level < 1420) { 00361 return _format_revision_level * 100; 00362 } else { 00363 return _format_revision_level; 00364 } 00365 } 00366 00367 //////////////////////////////////////////////////////////////////// 00368 // Function: FltHeader::set_flt_version 00369 // Access: Public 00370 // Description: Changes the version number of the flt file that will 00371 // be reported in the header. Pass in the 00372 // floating-point version number times 100. 00373 //////////////////////////////////////////////////////////////////// 00374 void FltHeader:: 00375 set_flt_version(int version) { 00376 if (version < 14.2) { 00377 _format_revision_level = version / 100; 00378 } else { 00379 _format_revision_level = version; 00380 } 00381 } 00382 00383 //////////////////////////////////////////////////////////////////// 00384 // Function: FltHeader::min_flt_version 00385 // Access: Public, Static 00386 // Description: Returns the earliest flt version number that this 00387 // codebase supports (times 100). Earlier versions will 00388 // probably not work. 00389 //////////////////////////////////////////////////////////////////// 00390 int FltHeader:: 00391 min_flt_version() { 00392 return 1400; 00393 } 00394 00395 //////////////////////////////////////////////////////////////////// 00396 // Function: FltHeader::max_flt_version 00397 // Access: Public, Static 00398 // Description: Returns the latest flt version number that this 00399 // codebase is known to support (times 100). Later 00400 // versions might work, but then again they may not. 00401 //////////////////////////////////////////////////////////////////// 00402 int FltHeader:: 00403 max_flt_version() { 00404 return 1570; 00405 } 00406 00407 //////////////////////////////////////////////////////////////////// 00408 // Function: FltHeader::check_version 00409 // Access: Public 00410 // Description: Verifies that the version number read from the header 00411 // is an understood version number, and prints a warning 00412 // to the user if this is not so--the read may or may 00413 // not succeed. Returns true if the version number is 00414 // acceptable (and no warning is printed), or false if 00415 // it is questionable (and a warning is printed). 00416 //////////////////////////////////////////////////////////////////// 00417 bool FltHeader:: 00418 check_version() const { 00419 int version = get_flt_version(); 00420 00421 if (version < min_flt_version()) { 00422 nout << "Warning! The version number of this file appears to be " 00423 << version / 100.0 << ", which is older than " << min_flt_version() / 100.0 00424 << ", the oldest OpenFlight version understood by this program. " 00425 "It is unlikely that this program will be able to read the file " 00426 "correctly.\n"; 00427 return false; 00428 } 00429 00430 if (version > max_flt_version()) { 00431 nout << "Warning! The version number of this file appears to be " 00432 << version / 100.0 << ", which is newer than " << max_flt_version() / 100.0 00433 << ", the newest OpenFlight version understood by this program. " 00434 "Chances are good that the program will still be able to read it " 00435 "correctly, but any features in the file that are specific to " 00436 "the latest version of OpenFlight will not be understood.\n"; 00437 return false; 00438 } 00439 00440 return true; 00441 } 00442 00443 //////////////////////////////////////////////////////////////////// 00444 // Function: FltHeader::get_units 00445 // Access: Public 00446 // Description: Returns the units indicated by the flt header, or 00447 // DU_invalid if the units in the header are not 00448 // understood. 00449 //////////////////////////////////////////////////////////////////// 00450 DistanceUnit FltHeader:: 00451 get_units() const { 00452 switch (_vertex_units) { 00453 case FltHeader::U_meters: 00454 return DU_meters; 00455 00456 case FltHeader::U_kilometers: 00457 return DU_kilometers; 00458 00459 case FltHeader::U_feet: 00460 return DU_feet; 00461 00462 case FltHeader::U_inches: 00463 return DU_inches; 00464 00465 case FltHeader::U_nautical_miles: 00466 return DU_nautical_miles; 00467 } 00468 00469 // Unknown units. 00470 return DU_invalid; 00471 } 00472 00473 //////////////////////////////////////////////////////////////////// 00474 // Function: FltHeader::has_instance 00475 // Access: Public 00476 // Description: Returns true if a instance subtree with the given 00477 // index has been defined. 00478 //////////////////////////////////////////////////////////////////// 00479 bool FltHeader:: 00480 has_instance(int instance_index) const { 00481 return (_instances.count(instance_index) != 0); 00482 } 00483 00484 //////////////////////////////////////////////////////////////////// 00485 // Function: FltHeader::get_instance 00486 // Access: Public 00487 // Description: Returns the instance subtree associated with the 00488 // given index, or NULL if there is no such instance. 00489 //////////////////////////////////////////////////////////////////// 00490 FltInstanceDefinition *FltHeader:: 00491 get_instance(int instance_index) const { 00492 Instances::const_iterator mi; 00493 mi = _instances.find(instance_index); 00494 if (mi != _instances.end()) { 00495 return (*mi).second; 00496 } 00497 return (FltInstanceDefinition *)NULL; 00498 } 00499 00500 //////////////////////////////////////////////////////////////////// 00501 // Function: FltHeader::clear_instances 00502 // Access: Public 00503 // Description: Removes all instance subtrees from the instance pool. 00504 //////////////////////////////////////////////////////////////////// 00505 void FltHeader:: 00506 clear_instances() { 00507 _instances.clear(); 00508 } 00509 00510 //////////////////////////////////////////////////////////////////// 00511 // Function: FltHeader::add_instance 00512 // Access: Public 00513 // Description: Defines a new instance subtree. This subtree is not 00514 // itself part of the hierarchy; it marks geometry that 00515 // may be instanced to various beads elsewhere in the 00516 // hierarchy by creating a corresponding FltInstanceRef 00517 // bead. 00518 //////////////////////////////////////////////////////////////////// 00519 void FltHeader:: 00520 add_instance(FltInstanceDefinition *instance) { 00521 _instances[instance->_instance_index] = instance; 00522 } 00523 00524 //////////////////////////////////////////////////////////////////// 00525 // Function: FltHeader::remove_instance 00526 // Access: Public 00527 // Description: Removes a particular instance subtree from the pool, 00528 // if it exists. 00529 //////////////////////////////////////////////////////////////////// 00530 void FltHeader:: 00531 remove_instance(int instance_index) { 00532 _instances.erase(instance_index); 00533 } 00534 00535 //////////////////////////////////////////////////////////////////// 00536 // Function: FltHeader::get_num_vertices 00537 // Access: Public 00538 // Description: Returns the number of vertices in the vertex palette. 00539 //////////////////////////////////////////////////////////////////// 00540 int FltHeader:: 00541 get_num_vertices() const { 00542 return _vertices.size(); 00543 } 00544 00545 //////////////////////////////////////////////////////////////////// 00546 // Function: FltHeader::get_vertex 00547 // Access: Public 00548 // Description: Returns the nth vertex of the vertex palette. 00549 //////////////////////////////////////////////////////////////////// 00550 FltVertex *FltHeader:: 00551 get_vertex(int n) const { 00552 nassertr(n >= 0 && n < (int)_vertices.size(), 0); 00553 return _vertices[n]; 00554 } 00555 00556 //////////////////////////////////////////////////////////////////// 00557 // Function: FltHeader::clear_vertices 00558 // Access: Public 00559 // Description: Removes all vertices from the vertex palette. 00560 //////////////////////////////////////////////////////////////////// 00561 void FltHeader:: 00562 clear_vertices() { 00563 _vertices.clear(); 00564 _unique_vertices.clear(); 00565 _vertices_by_offset.clear(); 00566 _offsets_by_vertex.clear(); 00567 _vertex_lookups_stale = false; 00568 } 00569 00570 //////////////////////////////////////////////////////////////////// 00571 // Function: FltHeader::add_vertex 00572 // Access: Public 00573 // Description: Adds a new vertex to the end of the vertex palette. 00574 // If this particular vertex was already present in the 00575 // palette, does nothing. 00576 //////////////////////////////////////////////////////////////////// 00577 void FltHeader:: 00578 add_vertex(FltVertex *vertex) { 00579 bool inserted = _unique_vertices.insert(vertex).second; 00580 if (inserted) { 00581 _vertices.push_back(vertex); 00582 } 00583 _vertex_lookups_stale = true; 00584 nassertv(_unique_vertices.size() == _vertices.size()); 00585 } 00586 00587 //////////////////////////////////////////////////////////////////// 00588 // Function: FltHeader::get_vertex_by_offset 00589 // Access: Public 00590 // Description: Returns the particular vertex pointer associated with 00591 // the given byte offset into the vertex palette. If 00592 // there is no such vertex in the palette, this 00593 // generates an error message and returns NULL. 00594 //////////////////////////////////////////////////////////////////// 00595 FltVertex *FltHeader:: 00596 get_vertex_by_offset(int offset) { 00597 if (_vertex_lookups_stale) { 00598 update_vertex_lookups(); 00599 } 00600 00601 VerticesByOffset::const_iterator vi; 00602 vi = _vertices_by_offset.find(offset); 00603 if (vi == _vertices_by_offset.end()) { 00604 nout << "No vertex with offset " << offset << "\n"; 00605 return (FltVertex *)NULL; 00606 } 00607 return (*vi).second; 00608 } 00609 00610 //////////////////////////////////////////////////////////////////// 00611 // Function: FltHeader::get_offset_by_vertex 00612 // Access: Public 00613 // Description: Returns the byte offset into the vertex palette 00614 // associated with the given vertex pointer. If there 00615 // is no such vertex in the palette, this generates an 00616 // error message and returns 0. 00617 //////////////////////////////////////////////////////////////////// 00618 int FltHeader:: 00619 get_offset_by_vertex(FltVertex *vertex) { 00620 if (_vertex_lookups_stale) { 00621 update_vertex_lookups(); 00622 } 00623 00624 OffsetsByVertex::const_iterator vi; 00625 vi = _offsets_by_vertex.find(vertex); 00626 if (vi == _offsets_by_vertex.end()) { 00627 nout << "Vertex does not appear in palette.\n"; 00628 return 0; 00629 } 00630 return (*vi).second; 00631 } 00632 00633 //////////////////////////////////////////////////////////////////// 00634 // Function: FltHeader::get_num_colors 00635 // Access: Public 00636 // Description: Returns the total number of different colors in the 00637 // color palette. This includes all different colors, 00638 // and represents the complete range of alloable color 00639 // indices. This is different from the actual number of 00640 // color entries as read directly from the color 00641 // palette, since each color entry defines a number of 00642 // different intensity levels--the value returned by 00643 // get_num_colors() is equal to get_num_color_entries() 00644 // * get_num_color_shades(). 00645 //////////////////////////////////////////////////////////////////// 00646 int FltHeader:: 00647 get_num_colors() const { 00648 return _colors.size() * get_num_color_shades(); 00649 } 00650 00651 //////////////////////////////////////////////////////////////////// 00652 // Function: FltHeader::get_color 00653 // Access: Public 00654 // Description: Returns the four-component color corresponding to the 00655 // given color index. Each component will be in the 00656 // range [0, 1]. 00657 //////////////////////////////////////////////////////////////////// 00658 LColor FltHeader:: 00659 get_color(int color_index) const { 00660 nassertr(color_index >= 0 && color_index < get_num_colors(), 00661 LColor(0.0, 0.0, 0.0, 0.0)); 00662 int num_color_shades = get_num_color_shades(); 00663 00664 int index = (color_index / num_color_shades); 00665 int level = (color_index % num_color_shades); 00666 nassertr(index >= 0 && index < (int)_colors.size(), 00667 LColor(0.0, 0.0, 0.0, 0.0)); 00668 00669 LColor color = _colors[index].get_color(); 00670 return color * ((double)level / (double)(num_color_shades - 1)); 00671 } 00672 00673 //////////////////////////////////////////////////////////////////// 00674 // Function: FltHeader::get_rgb 00675 // Access: Public 00676 // Description: Returns the three-component color corresponding to 00677 // the given color index, ignoring the alpha component. 00678 // Each component will be in the range [0, 1]. 00679 //////////////////////////////////////////////////////////////////// 00680 LRGBColor FltHeader:: 00681 get_rgb(int color_index) const { 00682 nassertr(color_index >= 0 && color_index < get_num_colors(), 00683 LRGBColor(0.0, 0.0, 0.0)); 00684 int num_color_shades = get_num_color_shades(); 00685 00686 int index = (color_index / num_color_shades); 00687 int level = (color_index % num_color_shades); 00688 nassertr(index >= 0 && index < (int)_colors.size(), 00689 LRGBColor(0.0, 0.0, 0.0)); 00690 00691 LRGBColor color = _colors[index].get_rgb(); 00692 return color * ((double)level / (double)(num_color_shades - 1)); 00693 } 00694 00695 //////////////////////////////////////////////////////////////////// 00696 // Function: FltHeader::has_color_name 00697 // Access: Public 00698 // Description: Returns true if the given color is named, false 00699 // otherwise. 00700 //////////////////////////////////////////////////////////////////// 00701 bool FltHeader:: 00702 has_color_name(int color_index) const { 00703 return (_color_names.count(color_index) != 0); 00704 } 00705 00706 //////////////////////////////////////////////////////////////////// 00707 // Function: FltHeader::get_color_name 00708 // Access: Public 00709 // Description: Returns the name associated with the given color, if 00710 // any. 00711 //////////////////////////////////////////////////////////////////// 00712 string FltHeader:: 00713 get_color_name(int color_index) const { 00714 ColorNames::const_iterator ni; 00715 ni = _color_names.find(color_index); 00716 if (ni != _color_names.end()) { 00717 return (*ni).second; 00718 } 00719 return string(); 00720 } 00721 00722 //////////////////////////////////////////////////////////////////// 00723 // Function: FltHeader::get_closest_color 00724 // Access: Public 00725 // Description: Returns the color index of the nearest color in the 00726 // palette that matches the given four-component color, 00727 // including alpha. 00728 //////////////////////////////////////////////////////////////////// 00729 int FltHeader:: 00730 get_closest_color(const LColor &color0) const { 00731 // Since the colortable stores the brightest colors, with 00732 // num_color_shades scaled versions of each color implicitly 00733 // available, we really only care about the relative brightnesses of 00734 // the various components. Normalize the color in terms of the 00735 // largest of these. 00736 LColor color = color0; 00737 00738 double scale = 1.0; 00739 00740 if (color[0] == 0.0 && color[1] == 0.0 && color[2] == 0.0 && color[3] == 0.0) { 00741 // Oh, this is invisible black. 00742 scale = 0.0; 00743 color.set(1.0, 1.0, 1.0, 1.0); 00744 00745 } else { 00746 if (color[0] >= color[1] && color[0] >= color[2] && color[0] >= color[3]) { 00747 // color[0] is largest. 00748 scale = color[0]; 00749 00750 } else if (color[1] >= color[2] && color[1] >= color[3]) { 00751 // color[1] is largest. 00752 scale = color[1]; 00753 00754 } else if (color[2] >= color[3]) { 00755 // color[2] is largest. 00756 scale = color[2]; 00757 00758 } else { 00759 // color[3] is largest. 00760 scale = color[3]; 00761 } 00762 color /= scale; 00763 } 00764 00765 // Now search for the best match. 00766 PN_stdfloat best_dist = 5.0; // Greater than 4. 00767 int best_i = -1; 00768 00769 int num_color_entries = get_num_color_entries(); 00770 for (int i = 0; i < num_color_entries; i++) { 00771 LColor consider = _colors[i].get_color(); 00772 PN_stdfloat dist2 = dot(consider - color, consider - color); 00773 nassertr(dist2 < 5.0, 0); 00774 00775 if (dist2 < best_dist) { 00776 best_dist = dist2; 00777 best_i = i; 00778 } 00779 } 00780 nassertr(best_i >= 0, 0); 00781 00782 int num_color_shades = get_num_color_shades(); 00783 int shade_index = (int)floor((num_color_shades-1) * scale + 0.5); 00784 00785 return (best_i * num_color_shades) + shade_index; 00786 } 00787 00788 //////////////////////////////////////////////////////////////////// 00789 // Function: FltHeader::get_closest_rgb 00790 // Access: Public 00791 // Description: Returns the color index of the nearest color in the 00792 // palette that matches the given three-component color, 00793 // ignoring alpha. 00794 //////////////////////////////////////////////////////////////////// 00795 int FltHeader:: 00796 get_closest_rgb(const LRGBColor &color0) const { 00797 // Since the colortable stores the brightest colors, with 00798 // num_color_shades scaled versions of each color implicitly 00799 // available, we really only care about the relative brightnesses of 00800 // the various components. Normalize the color in terms of the 00801 // largest of these. 00802 00803 LRGBColor color = color0; 00804 double scale = 1.0; 00805 00806 if (color[0] == 0.0 && color[1] == 0.0 && color[2] == 0.0) { 00807 // Oh, this is black. 00808 scale = 0.0; 00809 color.set(1.0, 1.0, 1.0); 00810 00811 } else { 00812 if (color[0] >= color[1] && color[0] >= color[2]) { 00813 // color[0] is largest. 00814 scale = color[0]; 00815 00816 } else if (color[1] >= color[2]) { 00817 // color[1] is largest. 00818 scale = color[1]; 00819 00820 } else { 00821 // color[2] is largest. 00822 scale = color[2]; 00823 } 00824 color /= scale; 00825 } 00826 00827 // Now search for the best match. 00828 PN_stdfloat best_dist = 5.0; // Greater than 4. 00829 int best_i = -1; 00830 00831 int num_color_entries = get_num_color_entries(); 00832 for (int i = 0; i < num_color_entries; i++) { 00833 LRGBColor consider = _colors[i].get_rgb(); 00834 PN_stdfloat dist2 = dot(consider - color, consider - color); 00835 nassertr(dist2 < 5.0, 0); 00836 00837 if (dist2 < best_dist) { 00838 best_dist = dist2; 00839 best_i = i; 00840 } 00841 } 00842 nassertr(best_i >= 0, 0); 00843 00844 int num_color_shades = get_num_color_shades(); 00845 int shade_index = (int)floor((num_color_shades-1) * scale + 0.5); 00846 00847 return (best_i * num_color_shades) + shade_index; 00848 } 00849 00850 //////////////////////////////////////////////////////////////////// 00851 // Function: FltHeader::get_num_color_entries 00852 // Access: Public 00853 // Description: Returns the number of actual entries in the color 00854 // palette. This is based on the version of the flt 00855 // file, and is usually either 512 or 1024. 00856 //////////////////////////////////////////////////////////////////// 00857 int FltHeader:: 00858 get_num_color_entries() const { 00859 return _colors.size(); 00860 } 00861 00862 //////////////////////////////////////////////////////////////////// 00863 // Function: FltHeader::get_num_color_shades 00864 // Access: Public 00865 // Description: Returns the number of shades of brightness of each 00866 // entry in the color palette. This is a fixed property 00867 // of MultiGen files: each entry in the palette actually 00868 // represents a range of this many colors. 00869 //////////////////////////////////////////////////////////////////// 00870 int FltHeader:: 00871 get_num_color_shades() const { 00872 return 128; 00873 } 00874 00875 //////////////////////////////////////////////////////////////////// 00876 // Function: FltHeader::get_color 00877 // Access: Public 00878 // Description: Decodes a MultiGen color, as stored on a face or 00879 // vertex, into an actual four-component LColor. 00880 // Normally you need not call this directly; there are 00881 // color accessors defined on faces and vertices that do 00882 // this. 00883 //////////////////////////////////////////////////////////////////// 00884 LColor FltHeader:: 00885 get_color(int color_index, bool use_packed_color, 00886 const FltPackedColor &packed_color, 00887 int transparency) { 00888 if (!use_packed_color) { 00889 return get_color(color_index); 00890 } 00891 00892 LColor color; 00893 color[0] = packed_color._r / 255.0; 00894 color[1] = packed_color._g / 255.0; 00895 color[2] = packed_color._b / 255.0; 00896 // MultiGen doesn't yet use the A component of RGBA. 00897 //color[3] = packed_color._a / 255.0; 00898 color[3] = 1.0 - (transparency / 65535.0); 00899 return color; 00900 } 00901 00902 //////////////////////////////////////////////////////////////////// 00903 // Function: FltHeader::get_color 00904 // Access: Public 00905 // Description: Decodes a MultiGen color, as stored on a face or 00906 // vertex, into an actual three-component LRGBColor. 00907 // Normally you need not call this directly; there are 00908 // color accessors defined on faces and vertices that do 00909 // this. 00910 //////////////////////////////////////////////////////////////////// 00911 LRGBColor FltHeader:: 00912 get_rgb(int color_index, bool use_packed_color, 00913 const FltPackedColor &packed_color) { 00914 if (!use_packed_color) { 00915 return get_rgb(color_index); 00916 } 00917 00918 LRGBColor color; 00919 color[0] = packed_color._r / 255.0; 00920 color[1] = packed_color._g / 255.0; 00921 color[2] = packed_color._b / 255.0; 00922 return color; 00923 } 00924 00925 //////////////////////////////////////////////////////////////////// 00926 // Function: FltHeader::has_material 00927 // Access: Public 00928 // Description: Returns true if a material with the given index has 00929 // been defined. 00930 //////////////////////////////////////////////////////////////////// 00931 bool FltHeader:: 00932 has_material(int material_index) const { 00933 return (_materials.count(material_index) != 0); 00934 } 00935 00936 //////////////////////////////////////////////////////////////////// 00937 // Function: FltHeader::get_material 00938 // Access: Public 00939 // Description: Returns the material associated with the given index, 00940 // or NULL if there is no such material. 00941 //////////////////////////////////////////////////////////////////// 00942 FltMaterial *FltHeader:: 00943 get_material(int material_index) const { 00944 Materials::const_iterator mi; 00945 mi = _materials.find(material_index); 00946 if (mi != _materials.end()) { 00947 return (*mi).second; 00948 } 00949 return (FltMaterial *)NULL; 00950 } 00951 00952 //////////////////////////////////////////////////////////////////// 00953 // Function: FltHeader::clear_materials 00954 // Access: Public 00955 // Description: Removes all materials from the palette. 00956 //////////////////////////////////////////////////////////////////// 00957 void FltHeader:: 00958 clear_materials() { 00959 _materials.clear(); 00960 } 00961 00962 //////////////////////////////////////////////////////////////////// 00963 // Function: FltHeader::add_material 00964 // Access: Public 00965 // Description: Defines a new material. The material is added in the 00966 // position indicated by the material's index number. 00967 // If there is already a material defined for that index 00968 // number, it is replaced. 00969 //////////////////////////////////////////////////////////////////// 00970 void FltHeader:: 00971 add_material(FltMaterial *material) { 00972 if (material->_material_index < 0) { 00973 // We need to make up a new material index for the material. 00974 material->_material_index = _next_material_index; 00975 _next_material_index++; 00976 00977 } else { 00978 // Make sure our next generated material index will be different 00979 // from any existing material indices. 00980 _next_material_index = max(_next_material_index, material->_material_index + 1); 00981 } 00982 00983 _materials[material->_material_index] = material; 00984 } 00985 00986 //////////////////////////////////////////////////////////////////// 00987 // Function: FltHeader::remove_material 00988 // Access: Public 00989 // Description: Removes a particular material from the material 00990 // palette, if it exists. 00991 //////////////////////////////////////////////////////////////////// 00992 void FltHeader:: 00993 remove_material(int material_index) { 00994 _materials.erase(material_index); 00995 } 00996 00997 //////////////////////////////////////////////////////////////////// 00998 // Function: FltHeader::has_texture 00999 // Access: Public 01000 // Description: Returns true if a texture with the given index has 01001 // been defined. 01002 //////////////////////////////////////////////////////////////////// 01003 bool FltHeader:: 01004 has_texture(int texture_index) const { 01005 return (_textures.count(texture_index) != 0); 01006 } 01007 01008 //////////////////////////////////////////////////////////////////// 01009 // Function: FltHeader::get_texture 01010 // Access: Public 01011 // Description: Returns the texture associated with the given index, 01012 // or NULL if there is no such texture. 01013 //////////////////////////////////////////////////////////////////// 01014 FltTexture *FltHeader:: 01015 get_texture(int texture_index) const { 01016 Textures::const_iterator mi; 01017 mi = _textures.find(texture_index); 01018 if (mi != _textures.end()) { 01019 return (*mi).second; 01020 } 01021 return (FltTexture *)NULL; 01022 } 01023 01024 //////////////////////////////////////////////////////////////////// 01025 // Function: FltHeader::clear_textures 01026 // Access: Public 01027 // Description: Removes all textures from the palette. 01028 //////////////////////////////////////////////////////////////////// 01029 void FltHeader:: 01030 clear_textures() { 01031 _textures.clear(); 01032 } 01033 01034 //////////////////////////////////////////////////////////////////// 01035 // Function: FltHeader::add_texture 01036 // Access: Public 01037 // Description: Defines a new texture. The texture is added in the 01038 // position indicated by the texture's index number. 01039 // If there is already a texture defined for that index 01040 // number, it is replaced. 01041 //////////////////////////////////////////////////////////////////// 01042 void FltHeader:: 01043 add_texture(FltTexture *texture) { 01044 if (texture->_pattern_index < 0) { 01045 // We need to make up a new pattern index for the texture. 01046 texture->_pattern_index = _next_pattern_index; 01047 _next_pattern_index++; 01048 01049 } else { 01050 // Make sure our next generated pattern index will be different 01051 // from any existing texture indices. 01052 _next_pattern_index = max(_next_pattern_index, texture->_pattern_index + 1); 01053 } 01054 01055 _textures[texture->_pattern_index] = texture; 01056 } 01057 01058 //////////////////////////////////////////////////////////////////// 01059 // Function: FltHeader::remove_texture 01060 // Access: Public 01061 // Description: Removes a particular texture from the texture 01062 // palette, if it exists. 01063 //////////////////////////////////////////////////////////////////// 01064 void FltHeader:: 01065 remove_texture(int texture_index) { 01066 _textures.erase(texture_index); 01067 } 01068 01069 //////////////////////////////////////////////////////////////////// 01070 // Function: FltHeader::has_light_source 01071 // Access: Public 01072 // Description: Returns true if a light source with the given index 01073 // has been defined. 01074 //////////////////////////////////////////////////////////////////// 01075 bool FltHeader:: 01076 has_light_source(int light_index) const { 01077 return (_light_sources.count(light_index) != 0); 01078 } 01079 01080 //////////////////////////////////////////////////////////////////// 01081 // Function: FltHeader::get_light_source 01082 // Access: Public 01083 // Description: Returns the light source associated with the given 01084 // index, or NULL if there is no such light source. 01085 //////////////////////////////////////////////////////////////////// 01086 FltLightSourceDefinition *FltHeader:: 01087 get_light_source(int light_index) const { 01088 LightSources::const_iterator li; 01089 li = _light_sources.find(light_index); 01090 if (li != _light_sources.end()) { 01091 return (*li).second; 01092 } 01093 return (FltLightSourceDefinition *)NULL; 01094 } 01095 01096 //////////////////////////////////////////////////////////////////// 01097 // Function: FltHeader::clear_light_sources 01098 // Access: Public 01099 // Description: Removes all light sources from the palette. 01100 //////////////////////////////////////////////////////////////////// 01101 void FltHeader:: 01102 clear_light_sources() { 01103 _light_sources.clear(); 01104 } 01105 01106 //////////////////////////////////////////////////////////////////// 01107 // Function: FltHeader::add_light_source 01108 // Access: Public 01109 // Description: Defines a new light source. The light source is 01110 // added in the position indicated by its light index 01111 // number. If there is already a light source defined 01112 // for that index number, it is replaced. 01113 //////////////////////////////////////////////////////////////////// 01114 void FltHeader:: 01115 add_light_source(FltLightSourceDefinition *light_source) { 01116 _light_sources[light_source->_light_index] = light_source; 01117 } 01118 01119 //////////////////////////////////////////////////////////////////// 01120 // Function: FltHeader::remove_light_source 01121 // Access: Public 01122 // Description: Removes a particular light source from the light 01123 // source palette, if it exists. 01124 //////////////////////////////////////////////////////////////////// 01125 void FltHeader:: 01126 remove_light_source(int light_index) { 01127 _light_sources.erase(light_index); 01128 } 01129 01130 //////////////////////////////////////////////////////////////////// 01131 // Function: FltHeader::got_eyepoint_trackplane_palette 01132 // Access: Public 01133 // Description: Returns true if we have read an eyepoint/trackplane 01134 // palette, and at least some of the eyepoints and 01135 // trackplanes are therefore expected to be meaningful. 01136 //////////////////////////////////////////////////////////////////// 01137 bool FltHeader:: 01138 got_eyepoint_trackplane_palette() const { 01139 return _got_eyepoint_trackplane_palette; 01140 } 01141 01142 //////////////////////////////////////////////////////////////////// 01143 // Function: FltHeader::set_eyepoint_trackplane_palette 01144 // Access: Public 01145 // Description: Sets the state of the eyepoint/trackplane palette 01146 // flag. When this is false, the palette is believed to 01147 // be meaningless, and will not be written; when it is 01148 // true, the palette is believed to contain at least 01149 // some meaningful data, and will be written. 01150 //////////////////////////////////////////////////////////////////// 01151 void FltHeader:: 01152 set_eyepoint_trackplane_palette(bool flag) { 01153 _got_eyepoint_trackplane_palette = flag; 01154 } 01155 01156 //////////////////////////////////////////////////////////////////// 01157 // Function: FltHeader::get_num_eyepoints 01158 // Access: Public 01159 // Description: Returns the number of eyepoints in the 01160 // eyepoint/trackplane palette. This is presently fixed 01161 // at 10, according to the MultiGen specs. 01162 //////////////////////////////////////////////////////////////////// 01163 int FltHeader:: 01164 get_num_eyepoints() const { 01165 return 10; 01166 } 01167 01168 //////////////////////////////////////////////////////////////////// 01169 // Function: FltHeader::get_eyepoint 01170 // Access: Public 01171 // Description: Returns the nth eyepoint in the eyepoint/trackplane 01172 // palette. 01173 //////////////////////////////////////////////////////////////////// 01174 FltEyepoint *FltHeader:: 01175 get_eyepoint(int n) { 01176 nassertr(n >= 0 && n < get_num_eyepoints(), (FltEyepoint *)NULL); 01177 return &_eyepoints[n]; 01178 } 01179 01180 //////////////////////////////////////////////////////////////////// 01181 // Function: FltHeader::get_num_trackplanes 01182 // Access: Public 01183 // Description: Returns the number of trackplanes in the 01184 // eyepoint/trackplane palette. This is presently fixed 01185 // at 10, according to the MultiGen specs. 01186 //////////////////////////////////////////////////////////////////// 01187 int FltHeader:: 01188 get_num_trackplanes() const { 01189 return 10; 01190 } 01191 01192 //////////////////////////////////////////////////////////////////// 01193 // Function: FltHeader::get_trackplane 01194 // Access: Public 01195 // Description: Returns the nth trackplane in the eyepoint/trackplane 01196 // palette. 01197 //////////////////////////////////////////////////////////////////// 01198 FltTrackplane *FltHeader:: 01199 get_trackplane(int n) { 01200 nassertr(n >= 0 && n < get_num_trackplanes(), (FltTrackplane *)NULL); 01201 return &_trackplanes[n]; 01202 } 01203 01204 //////////////////////////////////////////////////////////////////// 01205 // Function: FltHeader::update_vertex_lookups 01206 // Access: Public 01207 // Description: Recomputes the offsets_by_vertex and 01208 // vertices_by_offset tables. This reflects the flt 01209 // file as it will be written out, but not necessarily 01210 // as it was read in. 01211 // 01212 // The return value is the total length of the vertex 01213 // palette, including the header record. 01214 //////////////////////////////////////////////////////////////////// 01215 int FltHeader:: 01216 update_vertex_lookups() { 01217 // We start with the length of the vertex palette record itself. 01218 int offset = 8; 01219 01220 Vertices::const_iterator vi; 01221 for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) { 01222 FltVertex *vertex = (*vi); 01223 01224 _offsets_by_vertex[vertex] = offset; 01225 _vertices_by_offset[offset] = vertex; 01226 offset += vertex->get_record_length(); 01227 } 01228 01229 _vertex_lookups_stale = false; 01230 01231 return offset; 01232 } 01233 01234 //////////////////////////////////////////////////////////////////// 01235 // Function: FltHeader::extract_record 01236 // Access: Protected, Virtual 01237 // Description: Fills in the information in this bead based on the 01238 // information given in the indicated datagram, whose 01239 // opcode has already been read. Returns true on 01240 // success, false if the datagram is invalid. 01241 //////////////////////////////////////////////////////////////////// 01242 bool FltHeader:: 01243 extract_record(FltRecordReader &reader) { 01244 if (!FltBeadID::extract_record(reader)) { 01245 return false; 01246 } 01247 01248 nassertr(reader.get_opcode() == FO_header, false); 01249 DatagramIterator &iterator = reader.get_iterator(); 01250 01251 _format_revision_level = iterator.get_be_int32(); 01252 _edit_revision_level = iterator.get_be_int32(); 01253 _last_revision = iterator.get_fixed_string(32); 01254 _next_group_id = iterator.get_be_int16(); 01255 _next_lod_id = iterator.get_be_int16(); 01256 _next_object_id = iterator.get_be_int16(); 01257 _next_face_id = iterator.get_be_int16(); 01258 _unit_multiplier = iterator.get_be_int16(); 01259 _vertex_units = (Units)iterator.get_int8(); 01260 _texwhite_new = (iterator.get_int8() != 0); 01261 _flags = iterator.get_be_uint32(); 01262 iterator.skip_bytes(24); 01263 _projection_type = (ProjectionType)iterator.get_be_int32(); 01264 iterator.skip_bytes(28); 01265 _next_dof_id = iterator.get_be_int16(); 01266 _vertex_storage_type = (VertexStorageType)iterator.get_be_int16(); 01267 _database_origin = (DatabaseOrigin)iterator.get_be_int32(); 01268 _sw_x = iterator.get_be_float64(); 01269 _sw_y = iterator.get_be_float64(); 01270 _delta_x = iterator.get_be_float64(); 01271 _delta_y = iterator.get_be_float64(); 01272 _next_sound_id = iterator.get_be_int16(); 01273 _next_path_id = iterator.get_be_int16(); 01274 iterator.skip_bytes(8); 01275 _next_clip_id = iterator.get_be_int16(); 01276 _next_text_id = iterator.get_be_int16(); 01277 _next_bsp_id = iterator.get_be_int16(); 01278 _next_switch_id = iterator.get_be_int16(); 01279 iterator.skip_bytes(4); 01280 _sw_lat = iterator.get_be_float64(); 01281 _sw_long = iterator.get_be_float64(); 01282 _ne_lat = iterator.get_be_float64(); 01283 _ne_long = iterator.get_be_float64(); 01284 _origin_lat = iterator.get_be_float64(); 01285 _origin_long = iterator.get_be_float64(); 01286 _lambert_upper_lat = iterator.get_be_float64(); 01287 _lambert_lower_lat = iterator.get_be_float64(); 01288 _next_light_id = iterator.get_be_int16(); 01289 iterator.skip_bytes(2); 01290 if (get_flt_version() >= 1420 && iterator.get_remaining_size() > 0) { 01291 _next_road_id = iterator.get_be_int16(); 01292 _next_cat_id = iterator.get_be_int16(); 01293 01294 if (get_flt_version() >= 1520 && iterator.get_remaining_size() > 0) { 01295 iterator.skip_bytes(2 + 2 + 2 + 2); 01296 _earth_model = (EarthModel)iterator.get_be_int32(); 01297 01298 // Undocumented padding. 01299 iterator.skip_bytes(4); 01300 01301 if (get_flt_version() >= 1560 && iterator.get_remaining_size() > 0) { 01302 _next_adaptive_id = iterator.get_be_int16(); 01303 _next_curve_id = iterator.get_be_int16(); 01304 iterator.skip_bytes(4); 01305 01306 if (get_flt_version() >= 1570 && iterator.get_remaining_size() > 0) { 01307 _delta_z = iterator.get_be_float64(); 01308 _radius = iterator.get_be_float64(); 01309 _next_mesh_id = iterator.get_be_int16(); 01310 iterator.skip_bytes(2); 01311 01312 // Undocumented padding. 01313 iterator.skip_bytes(4); 01314 } 01315 } 01316 } 01317 } 01318 01319 check_remaining_size(iterator); 01320 return true; 01321 } 01322 01323 //////////////////////////////////////////////////////////////////// 01324 // Function: FltHeader::extract_ancillary 01325 // Access: Protected, Virtual 01326 // Description: Checks whether the given bead, which follows this 01327 // bead sequentially in the file, is an ancillary record 01328 // of this bead. If it is, extracts the relevant 01329 // information and returns true; otherwise, leaves it 01330 // alone and returns false. 01331 //////////////////////////////////////////////////////////////////// 01332 bool FltHeader:: 01333 extract_ancillary(FltRecordReader &reader) { 01334 switch (reader.get_opcode()) { 01335 case FO_vertex_palette: 01336 // We're about to begin the vertex palette! 01337 clear_vertices(); 01338 _current_vertex_offset = reader.get_record_length(); 01339 return true; 01340 01341 case FO_vertex_c: 01342 case FO_vertex_cn: 01343 case FO_vertex_cnu: 01344 case FO_vertex_cu: 01345 // Here's a new vertex for the palette. 01346 return extract_vertex(reader); 01347 01348 case FO_color_palette: 01349 return extract_color_palette(reader); 01350 01351 case FO_15_material: 01352 return extract_material(reader); 01353 01354 case FO_14_material_palette: 01355 return extract_14_material_palette(reader); 01356 01357 case FO_texture: 01358 return extract_texture(reader); 01359 01360 case FO_texture_map_palette: 01361 return extract_texture_map(reader); 01362 01363 case FO_light_definition: 01364 return extract_light_source(reader); 01365 01366 case FO_eyepoint_palette: 01367 return extract_eyepoint_palette(reader); 01368 01369 default: 01370 return FltBeadID::extract_ancillary(reader); 01371 } 01372 } 01373 01374 //////////////////////////////////////////////////////////////////// 01375 // Function: FltHeader::build_record 01376 // Access: Protected, Virtual 01377 // Description: Fills up the current record on the FltRecordWriter with 01378 // data for this record, but does not advance the 01379 // writer. Returns true on success, false if there is 01380 // some error. 01381 //////////////////////////////////////////////////////////////////// 01382 bool FltHeader:: 01383 build_record(FltRecordWriter &writer) const { 01384 if (!FltBeadID::build_record(writer)) { 01385 return false; 01386 } 01387 01388 writer.set_opcode(FO_header); 01389 Datagram &datagram = writer.update_datagram(); 01390 01391 datagram.add_be_int32(_format_revision_level); 01392 datagram.add_be_int32(_edit_revision_level); 01393 datagram.add_fixed_string(_last_revision, 32); 01394 datagram.add_be_int16(_next_group_id); 01395 datagram.add_be_int16(_next_lod_id); 01396 datagram.add_be_int16(_next_object_id); 01397 datagram.add_be_int16(_next_face_id); 01398 datagram.add_be_int16(_unit_multiplier); 01399 datagram.add_int8(_vertex_units); 01400 datagram.add_int8(_texwhite_new); 01401 datagram.add_be_uint32(_flags); 01402 datagram.pad_bytes(24); 01403 datagram.add_be_int32(_projection_type); 01404 datagram.pad_bytes(28); 01405 datagram.add_be_int16(_next_dof_id); 01406 datagram.add_be_int16(_vertex_storage_type); 01407 datagram.add_be_int32(_database_origin); 01408 datagram.add_be_float64(_sw_x); 01409 datagram.add_be_float64(_sw_y); 01410 datagram.add_be_float64(_delta_x); 01411 datagram.add_be_float64(_delta_y); 01412 datagram.add_be_int16(_next_sound_id); 01413 datagram.add_be_int16(_next_path_id); 01414 datagram.pad_bytes(8); 01415 datagram.add_be_int16(_next_clip_id); 01416 datagram.add_be_int16(_next_text_id); 01417 datagram.add_be_int16(_next_bsp_id); 01418 datagram.add_be_int16(_next_switch_id); 01419 datagram.pad_bytes(4); 01420 datagram.add_be_float64(_sw_lat); 01421 datagram.add_be_float64(_sw_long); 01422 datagram.add_be_float64(_ne_lat); 01423 datagram.add_be_float64(_ne_long); 01424 datagram.add_be_float64(_origin_lat); 01425 datagram.add_be_float64(_origin_long); 01426 datagram.add_be_float64(_lambert_upper_lat); 01427 datagram.add_be_float64(_lambert_lower_lat); 01428 datagram.add_be_int16(_next_light_id); 01429 datagram.pad_bytes(2); 01430 datagram.add_be_int16(_next_road_id); 01431 datagram.add_be_int16(_next_cat_id); 01432 01433 if (get_flt_version() >= 1520) { 01434 // New with 15.2 01435 datagram.pad_bytes(2 + 2 + 2 + 2); 01436 datagram.add_be_int32(_earth_model); 01437 01438 datagram.pad_bytes(4); 01439 01440 if (get_flt_version() >= 1560) { 01441 // New with 15.6 01442 datagram.add_be_int16(_next_adaptive_id); 01443 datagram.add_be_int16(_next_curve_id); 01444 datagram.pad_bytes(4); 01445 01446 if (get_flt_version() >= 1570) { 01447 // New with 15.7 01448 datagram.add_be_float64(_delta_z); 01449 datagram.add_be_float64(_radius); 01450 datagram.add_be_int16(_next_mesh_id); 01451 datagram.pad_bytes(2); 01452 datagram.pad_bytes(4); 01453 } 01454 } 01455 } 01456 01457 return true; 01458 } 01459 01460 //////////////////////////////////////////////////////////////////// 01461 // Function: FltHeader::write_ancillary 01462 // Access: Protected, Virtual 01463 // Description: Writes whatever ancillary records are required for 01464 // this bead. Returns FE_ok on success, or something 01465 // else on error. 01466 //////////////////////////////////////////////////////////////////// 01467 FltError FltHeader:: 01468 write_ancillary(FltRecordWriter &writer) const { 01469 FltError result; 01470 01471 result = write_color_palette(writer); 01472 if (result != FE_ok) { 01473 return result; 01474 } 01475 01476 result = write_material_palette(writer); 01477 if (result != FE_ok) { 01478 return result; 01479 } 01480 01481 result = write_texture_palette(writer); 01482 if (result != FE_ok) { 01483 return result; 01484 } 01485 01486 result = write_light_source_palette(writer); 01487 if (result != FE_ok) { 01488 return result; 01489 } 01490 01491 result = write_eyepoint_palette(writer); 01492 if (result != FE_ok) { 01493 return result; 01494 } 01495 01496 result = write_vertex_palette(writer); 01497 if (result != FE_ok) { 01498 return result; 01499 } 01500 01501 return FltBeadID::write_ancillary(writer); 01502 } 01503 01504 //////////////////////////////////////////////////////////////////// 01505 // Function: FltHeader::extract_vertex 01506 // Access: Private 01507 // Description: Reads a single vertex ancillary record. It is 01508 // assumed that all the vertex records will immediately 01509 // follow the vertex palette record. 01510 //////////////////////////////////////////////////////////////////// 01511 bool FltHeader:: 01512 extract_vertex(FltRecordReader &reader) { 01513 FltVertex *vertex = new FltVertex(this); 01514 if (!vertex->extract_record(reader)) { 01515 return false; 01516 } 01517 _vertices.push_back(vertex); 01518 _unique_vertices.insert(vertex); 01519 _offsets_by_vertex[vertex] = _current_vertex_offset; 01520 _vertices_by_offset[_current_vertex_offset] = vertex; 01521 _current_vertex_offset += reader.get_record_length(); 01522 01523 // _vertex_lookups_stale remains false. 01524 01525 return true; 01526 } 01527 01528 //////////////////////////////////////////////////////////////////// 01529 // Function: FltHeader::extract_color_palette 01530 // Access: Private 01531 // Description: Reads the color palette. 01532 //////////////////////////////////////////////////////////////////// 01533 bool FltHeader:: 01534 extract_color_palette(FltRecordReader &reader) { 01535 nassertr(reader.get_opcode() == FO_color_palette, false); 01536 DatagramIterator &iterator = reader.get_iterator(); 01537 01538 if (_got_color_palette) { 01539 nout << "Warning: multiple color palettes found.\n"; 01540 } 01541 _got_color_palette = true; 01542 01543 static const int expected_color_entries = 1024; 01544 01545 iterator.skip_bytes(128); 01546 _colors.clear(); 01547 for (int i = 0; i < expected_color_entries; i++) { 01548 if (iterator.get_remaining_size() == 0) { 01549 // An early end to the palette is acceptable. 01550 return true; 01551 } 01552 FltPackedColor color; 01553 if (!color.extract_record(reader)) { 01554 return false; 01555 } 01556 _colors.push_back(color); 01557 } 01558 01559 // Now pull out the color names. 01560 while (iterator.get_remaining_size() > 0) { 01561 int entry_length = iterator.get_be_uint16(); 01562 iterator.skip_bytes(2); 01563 if (iterator.get_remaining_size() > 0) { 01564 int color_index = iterator.get_be_int16(); 01565 iterator.skip_bytes(2); 01566 01567 int name_length = entry_length - 8; 01568 nassertr(color_index >= 0 && color_index < (int)_colors.size(), false); 01569 _color_names[color_index] = iterator.get_fixed_string(name_length); 01570 } 01571 } 01572 01573 check_remaining_size(iterator, "color palette"); 01574 return true; 01575 } 01576 01577 //////////////////////////////////////////////////////////////////// 01578 // Function: FltHeader::extract_material 01579 // Access: Private 01580 // Description: Reads a single material ancillary record. 01581 //////////////////////////////////////////////////////////////////// 01582 bool FltHeader:: 01583 extract_material(FltRecordReader &reader) { 01584 PT(FltMaterial) material = new FltMaterial(this); 01585 if (!material->extract_record(reader)) { 01586 return false; 01587 } 01588 add_material(material); 01589 01590 return true; 01591 } 01592 01593 //////////////////////////////////////////////////////////////////// 01594 // Function: FltHeader::extract_14_material_palette 01595 // Access: Private 01596 // Description: Reads the v14.2 material palette. 01597 //////////////////////////////////////////////////////////////////// 01598 bool FltHeader:: 01599 extract_14_material_palette(FltRecordReader &reader) { 01600 nassertr(reader.get_opcode() == FO_14_material_palette, false); 01601 DatagramIterator &iterator = reader.get_iterator(); 01602 01603 if (_got_14_material_palette) { 01604 nout << "Warning: multiple material palettes found.\n"; 01605 } 01606 _got_14_material_palette = true; 01607 01608 static const int expected_material_entries = 64; 01609 01610 _materials.clear(); 01611 for (int i = 0; i < expected_material_entries; i++) { 01612 if (iterator.get_remaining_size() == 0) { 01613 // An early end to the palette is acceptable. 01614 return true; 01615 } 01616 PT(FltMaterial) material = new FltMaterial(this); 01617 if (!material->extract_14_record(i, iterator)) { 01618 return false; 01619 } 01620 add_material(material); 01621 } 01622 01623 check_remaining_size(iterator, "material palette"); 01624 return true; 01625 } 01626 01627 //////////////////////////////////////////////////////////////////// 01628 // Function: FltHeader::extract_texture 01629 // Access: Private 01630 // Description: Reads a single texture ancillary record. 01631 //////////////////////////////////////////////////////////////////// 01632 bool FltHeader:: 01633 extract_texture(FltRecordReader &reader) { 01634 FltTexture *texture = new FltTexture(this); 01635 if (!texture->extract_record(reader)) { 01636 return false; 01637 } 01638 add_texture(texture); 01639 01640 return true; 01641 } 01642 01643 //////////////////////////////////////////////////////////////////// 01644 // Function: FltHeader::extract_texture_map 01645 // Access: Private 01646 // Description: Reads the a single texture mapping ancillary record. 01647 // This describes a kind of texture mapping in the 01648 // texture mapping palette. 01649 //////////////////////////////////////////////////////////////////// 01650 bool FltHeader:: 01651 extract_texture_map(FltRecordReader &reader) { 01652 // At the moment, we ignore this, since it's not needed for 01653 // meaningful extraction of data: we can get this information from 01654 // the UV's for a particular model. We just add an 01655 // UnsupportedRecord for it. 01656 FltUnsupportedRecord *rec = new FltUnsupportedRecord(this); 01657 if (!rec->extract_record(reader)) { 01658 return false; 01659 } 01660 add_ancillary(rec); 01661 01662 return true; 01663 } 01664 01665 //////////////////////////////////////////////////////////////////// 01666 // Function: FltHeader::extract_light_source 01667 // Access: Private 01668 // Description: Reads a single light source ancillary record. 01669 //////////////////////////////////////////////////////////////////// 01670 bool FltHeader:: 01671 extract_light_source(FltRecordReader &reader) { 01672 FltLightSourceDefinition *light_source = new FltLightSourceDefinition(this); 01673 if (!light_source->extract_record(reader)) { 01674 return false; 01675 } 01676 add_light_source(light_source); 01677 01678 return true; 01679 } 01680 01681 //////////////////////////////////////////////////////////////////// 01682 // Function: FltHeader::extract_eyepoint_palette 01683 // Access: Private 01684 // Description: Reads the eyepoint/trackplane palette. 01685 //////////////////////////////////////////////////////////////////// 01686 bool FltHeader:: 01687 extract_eyepoint_palette(FltRecordReader &reader) { 01688 nassertr(reader.get_opcode() == FO_eyepoint_palette, false); 01689 DatagramIterator &iterator = reader.get_iterator(); 01690 01691 iterator.skip_bytes(4); 01692 01693 int i; 01694 int num_eyepoints = get_num_eyepoints(); 01695 for (i = 0; i < num_eyepoints; i++) { 01696 if (!_eyepoints[i].extract_record(reader)) { 01697 return false; 01698 } 01699 } 01700 01701 int num_trackplanes = get_num_trackplanes(); 01702 for (i = 0; i < num_trackplanes; i++) { 01703 if (!_trackplanes[i].extract_record(reader)) { 01704 return false; 01705 } 01706 } 01707 01708 _got_eyepoint_trackplane_palette = true; 01709 01710 if (get_flt_version() >= 1420) { 01711 // I have no idea what bytes are supposed to be here in earlier 01712 // versions that 14.2, but who really cares? Don't bother 01713 // reporting it if there are too many bytes in old versions. 01714 check_remaining_size(iterator, "eyepoint palette"); 01715 } 01716 return true; 01717 } 01718 01719 //////////////////////////////////////////////////////////////////// 01720 // Function: FltHeader::write_vertex_palette 01721 // Access: Private 01722 // Description: Writes out the vertex palette with all of its 01723 // vertices. 01724 //////////////////////////////////////////////////////////////////// 01725 FltError FltHeader:: 01726 write_vertex_palette(FltRecordWriter &writer) const { 01727 FltError result; 01728 01729 int vertex_palette_length = 01730 ((FltHeader *)this)->update_vertex_lookups(); 01731 Datagram vertex_palette; 01732 vertex_palette.add_be_int32(vertex_palette_length); 01733 result = writer.write_record(FO_vertex_palette, vertex_palette); 01734 if (result != FE_ok) { 01735 return result; 01736 } 01737 // Now write out each vertex in the palette. 01738 Vertices::const_iterator vi; 01739 for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) { 01740 FltVertex *vertex = (*vi); 01741 vertex->build_record(writer); 01742 result = writer.advance(); 01743 if (result != FE_ok) { 01744 return result; 01745 } 01746 } 01747 01748 return FE_ok; 01749 } 01750 01751 01752 //////////////////////////////////////////////////////////////////// 01753 // Function: FltHeader::write_color_palette 01754 // Access: Private 01755 // Description: Writes out the color palette. 01756 //////////////////////////////////////////////////////////////////// 01757 FltError FltHeader:: 01758 write_color_palette(FltRecordWriter &writer) const { 01759 writer.set_opcode(FO_color_palette); 01760 Datagram &datagram = writer.update_datagram(); 01761 01762 datagram.pad_bytes(128); 01763 01764 // How many colors should we write? 01765 int num_colors = 1024; 01766 01767 Colors::const_iterator ci; 01768 for (ci = _colors.begin(); num_colors > 0 && ci != _colors.end(); ++ci) { 01769 if (!(*ci).build_record(writer)) { 01770 assert(!flt_error_abort); 01771 return FE_invalid_record; 01772 } 01773 num_colors--; 01774 } 01775 01776 // Now we might need to pad the record to fill up the required 01777 // number of colors. 01778 if (num_colors > 0) { 01779 FltPackedColor empty; 01780 while (num_colors > 0) { 01781 if (!empty.build_record(writer)) { 01782 assert(!flt_error_abort); 01783 return FE_invalid_record; 01784 } 01785 num_colors--; 01786 } 01787 } 01788 01789 // Now append all the names at the end. 01790 ColorNames::const_iterator ni; 01791 for (ni = _color_names.begin(); ni != _color_names.end(); ++ni) { 01792 string name = (*ni).second.substr(0, 80); 01793 int entry_length = name.length() + 8; 01794 datagram.add_be_uint16(entry_length); 01795 datagram.pad_bytes(2); 01796 datagram.add_be_uint16((*ni).first); 01797 datagram.pad_bytes(2); 01798 datagram.add_fixed_string(name, name.length()); 01799 } 01800 01801 return writer.advance(); 01802 } 01803 01804 //////////////////////////////////////////////////////////////////// 01805 // Function: FltHeader::write_material_palette 01806 // Access: Private 01807 // Description: Writes out the material palette. 01808 //////////////////////////////////////////////////////////////////// 01809 FltError FltHeader:: 01810 write_material_palette(FltRecordWriter &writer) const { 01811 FltError result; 01812 01813 if (get_flt_version() >= 1520) { 01814 // Write a version 15 material palette. 01815 Materials::const_iterator mi; 01816 for (mi = _materials.begin(); mi != _materials.end(); ++mi) { 01817 FltMaterial *material = (*mi).second; 01818 material->build_record(writer); 01819 01820 result = writer.advance(); 01821 if (result != FE_ok) { 01822 return result; 01823 } 01824 } 01825 01826 } else { 01827 // Write a version 14 material palette. 01828 if (_materials.empty()) { 01829 // No palette is OK. 01830 return FE_ok; 01831 } 01832 writer.set_opcode(FO_14_material_palette); 01833 Datagram &datagram = writer.update_datagram(); 01834 01835 PT(FltMaterial) dummy_material = new FltMaterial(_header); 01836 01837 Materials::const_iterator mi = _materials.lower_bound(0); 01838 int index; 01839 static const int expected_material_entries = 64; 01840 for (index = 0; index < expected_material_entries; index++) { 01841 if (mi == _materials.end() || index < (*mi).first) { 01842 dummy_material->build_14_record(datagram); 01843 } else { 01844 nassertr(index == (*mi).first, FE_internal); 01845 FltMaterial *material = (*mi).second; 01846 material->build_14_record(datagram); 01847 ++mi; 01848 } 01849 } 01850 01851 result = writer.advance(); 01852 if (result != FE_ok) { 01853 return result; 01854 } 01855 } 01856 01857 return FE_ok; 01858 } 01859 01860 //////////////////////////////////////////////////////////////////// 01861 // Function: FltHeader::write_texture_palette 01862 // Access: Private 01863 // Description: Writes out the texture palette. 01864 //////////////////////////////////////////////////////////////////// 01865 FltError FltHeader:: 01866 write_texture_palette(FltRecordWriter &writer) const { 01867 FltError result; 01868 01869 Textures::const_iterator ti; 01870 for (ti = _textures.begin(); ti != _textures.end(); ++ti) { 01871 FltTexture *texture = (*ti).second; 01872 texture->build_record(writer); 01873 result = writer.advance(); 01874 if (result != FE_ok) { 01875 return result; 01876 } 01877 } 01878 01879 return FE_ok; 01880 } 01881 01882 //////////////////////////////////////////////////////////////////// 01883 // Function: FltHeader::write_light_source_palette 01884 // Access: Private 01885 // Description: Writes out the light source palette. 01886 //////////////////////////////////////////////////////////////////// 01887 FltError FltHeader:: 01888 write_light_source_palette(FltRecordWriter &writer) const { 01889 FltError result; 01890 01891 LightSources::const_iterator li; 01892 for (li = _light_sources.begin(); li != _light_sources.end(); ++li) { 01893 FltLightSourceDefinition *light_source = (*li).second; 01894 light_source->build_record(writer); 01895 result = writer.advance(); 01896 if (result != FE_ok) { 01897 return result; 01898 } 01899 } 01900 01901 return FE_ok; 01902 } 01903 01904 //////////////////////////////////////////////////////////////////// 01905 // Function: FltHeader::write_eyepoint_palette 01906 // Access: Private 01907 // Description: Writes out the eyepoint/trackplane palette, if we 01908 // have one. 01909 //////////////////////////////////////////////////////////////////// 01910 FltError FltHeader:: 01911 write_eyepoint_palette(FltRecordWriter &writer) const { 01912 if (!_got_eyepoint_trackplane_palette) { 01913 return FE_ok; 01914 } 01915 01916 writer.set_opcode(FO_eyepoint_palette); 01917 Datagram &datagram = writer.update_datagram(); 01918 datagram.pad_bytes(4); 01919 01920 int i; 01921 int num_eyepoints = get_num_eyepoints(); 01922 for (i = 0; i < num_eyepoints; i++) { 01923 if (!_eyepoints[i].build_record(writer)) { 01924 assert(!flt_error_abort); 01925 return FE_bad_data; 01926 } 01927 } 01928 01929 int num_trackplanes = get_num_trackplanes(); 01930 for (i = 0; i < num_trackplanes; i++) { 01931 if (!_trackplanes[i].build_record(writer)) { 01932 assert(!flt_error_abort); 01933 return FE_bad_data; 01934 } 01935 } 01936 01937 return writer.advance(); 01938 }