40 if (path_replace ==
nullptr) {
42 _path_replace->_path_store = PS_absolute;
44 _path_replace = path_replace;
47 _format_revision_level = 1570;
48 _edit_revision_level = 1570;
54 _vertex_units = U_feet;
55 _texwhite_new =
false;
57 _projection_type = PT_flat_earth;
59 _vertex_storage_type = VTS_double;
60 _database_origin = DO_open_flight;
77 _lambert_upper_lat = 0.0;
78 _lambert_lower_lat = 0.0;
84 _earth_model = EM_wgs84;
87 _next_adaptive_id = 0;
95 _vertex_lookups_stale =
false;
96 _current_vertex_offset = 0;
97 _next_material_index = 1;
98 _next_pattern_index = 1;
99 _got_color_palette =
false;
100 _got_14_material_palette =
false;
101 _got_eyepoint_trackplane_palette =
false;
103 _auto_attr_update = AU_if_missing;
114 Textures::const_iterator ti;
115 for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
129 _path_replace = path_replace;
139 return _path_replace;
149 return _path_replace;
159 if (!_flt_filename.empty()) {
163 return _path_replace->convert_path(orig_filename, file_path);
172 _flt_filename = flt_filename;
180 return _flt_filename;
190 _flt_filename = filename;
195 assert(!flt_error_abort);
196 return FE_could_not_open;
210 FltError result = reader.
advance();
211 if (result == FE_end_of_file) {
212 assert(!flt_error_abort);
213 return FE_empty_file;
214 }
else if (result != FE_ok) {
218 result = read_record_and_children(reader);
219 if (result != FE_ok) {
224 assert(!flt_error_abort);
225 return FE_extra_data;
242 assert(!flt_error_abort);
243 return FE_could_not_open;
250 OCompressStream compressor(&out,
false);
265 FltError result = write_record_and_children(writer);
268 assert(!flt_error_abort);
269 return FE_write_error;
292 _auto_attr_update = attr;
301 return _auto_attr_update;
310 if (_format_revision_level < 1420) {
311 return _format_revision_level * 100;
313 return _format_revision_level;
323 if (version < 14.2) {
324 _format_revision_level = version / 100;
326 _format_revision_level = version;
361 nout <<
"Warning! The version number of this file appears to be "
362 << version / 100.0 <<
", which is older than " <<
min_flt_version() / 100.0
363 <<
", the oldest OpenFlight version understood by this program. "
364 "It is unlikely that this program will be able to read the file "
370 nout <<
"Warning! The version number of this file appears to be "
371 << version / 100.0 <<
", which is newer than " <<
max_flt_version() / 100.0
372 <<
", the newest OpenFlight version understood by this program. "
373 "Chances are good that the program will still be able to read it "
374 "correctly, but any features in the file that are specific to "
375 "the latest version of OpenFlight will not be understood.\n";
388 switch (_vertex_units) {
389 case FltHeader::U_meters:
392 case FltHeader::U_kilometers:
393 return DU_kilometers;
395 case FltHeader::U_feet:
398 case FltHeader::U_inches:
401 case FltHeader::U_nautical_miles:
402 return DU_nautical_miles;
414 return (_instances.count(instance_index) != 0);
423 Instances::const_iterator mi;
424 mi = _instances.find(instance_index);
425 if (mi != _instances.end()) {
446 _instances[instance->_instance_index] = instance;
454 _instances.erase(instance_index);
462 return _vertices.size();
470 nassertr(n >= 0 && n < (
int)_vertices.size(),
nullptr);
480 _unique_vertices.clear();
481 _vertices_by_offset.clear();
482 _offsets_by_vertex.clear();
483 _vertex_lookups_stale =
false;
492 bool inserted = _unique_vertices.insert(vertex).second;
494 _vertices.push_back(vertex);
496 _vertex_lookups_stale =
true;
497 nassertv(_unique_vertices.size() == _vertices.size());
507 if (_vertex_lookups_stale) {
508 update_vertex_lookups();
511 VerticesByOffset::const_iterator vi;
512 vi = _vertices_by_offset.find(offset);
513 if (vi == _vertices_by_offset.end()) {
514 nout <<
"No vertex with offset " << offset <<
"\n";
527 if (_vertex_lookups_stale) {
528 update_vertex_lookups();
531 OffsetsByVertex::const_iterator vi;
532 vi = _offsets_by_vertex.find(vertex);
533 if (vi == _offsets_by_vertex.end()) {
534 nout <<
"Vertex does not appear in palette.\n";
561 LColor(0.0, 0.0, 0.0, 0.0));
564 int index = (color_index / num_color_shades);
565 int level = (color_index % num_color_shades);
566 nassertr(index >= 0 && index < (
int)_colors.size(),
567 LColor(0.0, 0.0, 0.0, 0.0));
569 LColor color = _colors[index].get_color();
570 return color * ((double)level / (
double)(num_color_shades - 1));
578 get_rgb(
int color_index)
const {
580 LRGBColor(0.0, 0.0, 0.0));
583 int index = (color_index / num_color_shades);
584 int level = (color_index % num_color_shades);
585 nassertr(index >= 0 && index < (
int)_colors.size(),
586 LRGBColor(0.0, 0.0, 0.0));
588 LRGBColor color = _colors[index].get_rgb();
589 return color * ((double)level / (
double)(num_color_shades - 1));
597 return (_color_names.count(color_index) != 0);
605 ColorNames::const_iterator ni;
606 ni = _color_names.find(color_index);
607 if (ni != _color_names.end()) {
610 return std::string();
623 LColor color = color0;
627 if (color[0] == 0.0 && color[1] == 0.0 && color[2] == 0.0 && color[3] == 0.0) {
630 color.set(1.0, 1.0, 1.0, 1.0);
633 if (color[0] >= color[1] && color[0] >= color[2] && color[0] >= color[3]) {
637 }
else if (color[1] >= color[2] && color[1] >= color[3]) {
641 }
else if (color[2] >= color[3]) {
653 PN_stdfloat best_dist = 5.0;
657 for (
int i = 0; i < num_color_entries; i++) {
658 LColor consider = _colors[i].get_color();
659 PN_stdfloat dist2 = dot(consider - color, consider - color);
660 nassertr(dist2 < 5.0, 0);
662 if (dist2 < best_dist) {
667 nassertr(best_i >= 0, 0);
670 int shade_index = (int)floor((num_color_shades-1) * scale + 0.5);
672 return (best_i * num_color_shades) + shade_index;
686 LRGBColor color = color0;
689 if (color[0] == 0.0 && color[1] == 0.0 && color[2] == 0.0) {
692 color.set(1.0, 1.0, 1.0);
695 if (color[0] >= color[1] && color[0] >= color[2]) {
699 }
else if (color[1] >= color[2]) {
711 PN_stdfloat best_dist = 5.0;
715 for (
int i = 0; i < num_color_entries; i++) {
716 LRGBColor consider = _colors[i].get_rgb();
717 PN_stdfloat dist2 = dot(consider - color, consider - color);
718 nassertr(dist2 < 5.0, 0);
720 if (dist2 < best_dist) {
725 nassertr(best_i >= 0, 0);
728 int shade_index = (int)floor((num_color_shades-1) * scale + 0.5);
730 return (best_i * num_color_shades) + shade_index;
739 return _colors.size();
758 get_color(
int color_index,
bool use_packed_color,
761 if (!use_packed_color) {
766 color[0] = packed_color._r / 255.0;
767 color[1] = packed_color._g / 255.0;
768 color[2] = packed_color._b / 255.0;
771 color[3] = 1.0 - (transparency / 65535.0);
781 get_rgb(
int color_index,
bool use_packed_color,
783 if (!use_packed_color) {
788 color[0] = packed_color._r / 255.0;
789 color[1] = packed_color._g / 255.0;
790 color[2] = packed_color._b / 255.0;
799 return (_materials.count(material_index) != 0);
808 Materials::const_iterator mi;
809 mi = _materials.find(material_index);
810 if (mi != _materials.end()) {
831 if (material->_material_index < 0) {
833 material->_material_index = _next_material_index;
834 _next_material_index++;
839 _next_material_index = std::max(_next_material_index, material->_material_index + 1);
842 _materials[material->_material_index] = material;
850 _materials.erase(material_index);
858 return (_textures.count(texture_index) != 0);
867 Textures::const_iterator mi;
868 mi = _textures.find(texture_index);
869 if (mi != _textures.end()) {
890 if (texture->_pattern_index < 0) {
892 texture->_pattern_index = _next_pattern_index;
893 _next_pattern_index++;
898 _next_pattern_index = std::max(_next_pattern_index, texture->_pattern_index + 1);
901 _textures[texture->_pattern_index] = texture;
909 _textures.erase(texture_index);
917 return (_light_sources.count(light_index) != 0);
926 LightSources::const_iterator li;
927 li = _light_sources.find(light_index);
928 if (li != _light_sources.end()) {
939 _light_sources.clear();
949 _light_sources[light_source->_light_index] = light_source;
958 _light_sources.erase(light_index);
968 return _got_eyepoint_trackplane_palette;
979 _got_eyepoint_trackplane_palette = flag;
997 return &_eyepoints[n];
1015 return &_trackplanes[n];
1027 update_vertex_lookups() {
1031 Vertices::const_iterator vi;
1032 for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) {
1035 _offsets_by_vertex[vertex] = offset;
1036 _vertices_by_offset[offset] = vertex;
1040 _vertex_lookups_stale =
false;
1052 if (!FltBeadID::extract_record(reader)) {
1056 nassertr(reader.
get_opcode() == FO_header,
false);
1067 _vertex_units = (Units)iterator.
get_int8();
1068 _texwhite_new = (iterator.
get_int8() != 0);
1071 _projection_type = (ProjectionType)iterator.
get_be_int32();
1074 _vertex_storage_type = (VertexStorageType)iterator.
get_be_int16();
1075 _database_origin = (DatabaseOrigin)iterator.
get_be_int32();
1139 case FO_vertex_palette:
1150 return extract_vertex(reader);
1152 case FO_color_palette:
1153 return extract_color_palette(reader);
1155 case FO_15_material:
1156 return extract_material(reader);
1158 case FO_14_material_palette:
1159 return extract_14_material_palette(reader);
1162 return extract_texture(reader);
1164 case FO_texture_map_palette:
1165 return extract_texture_map(reader);
1167 case FO_light_definition:
1168 return extract_light_source(reader);
1170 case FO_eyepoint_palette:
1171 return extract_eyepoint_palette(reader);
1174 return FltBeadID::extract_ancillary(reader);
1185 if (!FltBeadID::build_record(writer)) {
1265 FltError FltHeader::
1269 result = write_color_palette(writer);
1270 if (result != FE_ok) {
1274 result = write_material_palette(writer);
1275 if (result != FE_ok) {
1279 result = write_texture_palette(writer);
1280 if (result != FE_ok) {
1284 result = write_light_source_palette(writer);
1285 if (result != FE_ok) {
1289 result = write_eyepoint_palette(writer);
1290 if (result != FE_ok) {
1294 result = write_vertex_palette(writer);
1295 if (result != FE_ok) {
1299 return FltBeadID::write_ancillary(writer);
1309 if (!vertex->extract_record(reader)) {
1312 _vertices.push_back(vertex);
1313 _unique_vertices.insert(vertex);
1314 _offsets_by_vertex[vertex] = _current_vertex_offset;
1315 _vertices_by_offset[_current_vertex_offset] = vertex;
1328 nassertr(reader.
get_opcode() == FO_color_palette,
false);
1331 if (_got_color_palette) {
1332 nout <<
"Warning: multiple color palettes found.\n";
1334 _got_color_palette =
true;
1336 static const int expected_color_entries = 1024;
1340 for (
int i = 0; i < expected_color_entries; i++) {
1346 if (!color.extract_record(reader)) {
1349 _colors.push_back(color);
1360 int name_length = entry_length - 8;
1361 nassertr(color_index >= 0 && color_index < (
int)_colors.size(),
false);
1376 if (!material->extract_record(reader)) {
1389 nassertr(reader.
get_opcode() == FO_14_material_palette,
false);
1392 if (_got_14_material_palette) {
1393 nout <<
"Warning: multiple material palettes found.\n";
1395 _got_14_material_palette =
true;
1397 static const int expected_material_entries = 64;
1400 for (
int i = 0; i < expected_material_entries; i++) {
1406 if (!material->extract_14_record(i, iterator)) {
1422 if (!texture->extract_record(reader)) {
1440 if (!rec->extract_record(reader)) {
1454 if (!light_source->extract_record(reader)) {
1467 nassertr(reader.
get_opcode() == FO_eyepoint_palette,
false);
1474 for (i = 0; i < num_eyepoints; i++) {
1475 if (!_eyepoints[i].extract_record(reader)) {
1481 for (i = 0; i < num_trackplanes; i++) {
1482 if (!_trackplanes[i].extract_record(reader)) {
1487 _got_eyepoint_trackplane_palette =
true;
1501 FltError FltHeader::
1505 int vertex_palette_length =
1506 ((
FltHeader *)
this)->update_vertex_lookups();
1509 result = writer.
write_record(FO_vertex_palette, vertex_palette);
1510 if (result != FE_ok) {
1514 Vertices::const_iterator vi;
1515 for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) {
1517 vertex->build_record(writer);
1519 if (result != FE_ok) {
1531 FltError FltHeader::
1539 int num_colors = 1024;
1541 Colors::const_iterator ci;
1542 for (ci = _colors.begin(); num_colors > 0 && ci != _colors.end(); ++ci) {
1543 if (!(*ci).build_record(writer)) {
1544 assert(!flt_error_abort);
1545 return FE_invalid_record;
1552 if (num_colors > 0) {
1554 while (num_colors > 0) {
1555 if (!empty.build_record(writer)) {
1556 assert(!flt_error_abort);
1557 return FE_invalid_record;
1564 ColorNames::const_iterator ni;
1565 for (ni = _color_names.begin(); ni != _color_names.end(); ++ni) {
1566 std::string name = (*ni).second.substr(0, 80);
1567 int entry_length = name.length() + 8;
1581 FltError FltHeader::
1587 Materials::const_iterator mi;
1588 for (mi = _materials.begin(); mi != _materials.end(); ++mi) {
1590 material->build_record(writer);
1593 if (result != FE_ok) {
1600 if (_materials.empty()) {
1609 Materials::const_iterator mi = _materials.lower_bound(0);
1611 static const int expected_material_entries = 64;
1612 for (index = 0; index < expected_material_entries; index++) {
1613 if (mi == _materials.end() || index < (*mi).first) {
1614 dummy_material->build_14_record(datagram);
1616 nassertr(index == (*mi).first, FE_internal);
1624 if (result != FE_ok) {
1635 FltError FltHeader::
1639 Textures::const_iterator ti;
1640 for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
1642 texture->build_record(writer);
1644 if (result != FE_ok) {
1655 FltError FltHeader::
1659 LightSources::const_iterator li;
1660 for (li = _light_sources.begin(); li != _light_sources.end(); ++li) {
1662 light_source->build_record(writer);
1664 if (result != FE_ok) {
1675 FltError FltHeader::
1677 if (!_got_eyepoint_trackplane_palette) {
1687 for (i = 0; i < num_eyepoints; i++) {
1688 if (!_eyepoints[i].build_record(writer)) {
1689 assert(!flt_error_abort);
1695 for (i = 0; i < num_trackplanes; i++) {
1696 if (!_trackplanes[i].build_record(writer)) {
1697 assert(!flt_error_abort);