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