Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

pandatool/src/flt/fltHeader.cxx

Go to the documentation of this file.
00001 // Filename: fltHeader.cxx
00002 // Created by:  drose (24Aug00)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
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 //     Function: FltHeader::Constructor
00034 //       Access: Public
00035 //  Description: The FltHeader constructor accepts a PathReplace
00036 //               pointer; it uses this object to automatically convert
00037 //               all external filename and texture references.  (This
00038 //               is necessary because the FltHeader has to look in the
00039 //               same directory as the texture to find the .attr file,
00040 //               so it must pre-convert at least the texture
00041 //               references.)
00042 //
00043 //               Most of the other file converters do not have this
00044 //               requirement, so they do not need to pre-convert any
00045 //               pathname references.
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   // New with 15.2
00093   _earth_model = EM_wgs84;
00094 
00095   // New with 15.6
00096   _next_adaptive_id = 0;
00097   _next_curve_id = 0;
00098 
00099   // New with 15.7
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 //     Function: FltHeader::apply_converted_filenames
00115 //       Access: Public, Virtual
00116 //  Description: Walks the hierarchy at this record and below and
00117 //               copies the _converted_filename record into the
00118 //               _orig_filename record, so the flt file will be
00119 //               written out with the converted filename instead of
00120 //               what was originally read in.
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 //     Function: FltHeader::set_path_replace
00135 //       Access: Public
00136 //  Description: Replaces the PathReplace object (which specifies how
00137 //               to mangle paths from the source to the destination
00138 //               file) with a new one.
00139 ////////////////////////////////////////////////////////////////////
00140 void FltHeader::
00141 set_path_replace(PathReplace *path_replace) {
00142   _path_replace = path_replace;
00143 }
00144 
00145 ////////////////////////////////////////////////////////////////////
00146 //     Function: FltHeader::get_path_replace
00147 //       Access: Public
00148 //  Description: Returns a pointer to the PathReplace object
00149 //               associated with this converter.  If the converter is
00150 //               non-const, this returns a non-const pointer, which
00151 //               can be adjusted.
00152 ////////////////////////////////////////////////////////////////////
00153 PathReplace *FltHeader::
00154 get_path_replace() {
00155   return _path_replace;
00156 }
00157 
00158 ////////////////////////////////////////////////////////////////////
00159 //     Function: FltHeader::get_path_replace
00160 //       Access: Public
00161 //  Description: Returns a pointer to the PathReplace object
00162 //               associated with this converter.  If the converter is
00163 //               non-const, this returns a non-const pointer, which
00164 //               can be adjusted.
00165 ////////////////////////////////////////////////////////////////////
00166 const PathReplace *FltHeader::
00167 get_path_replace() const {
00168   return _path_replace;
00169 }
00170 
00171 ////////////////////////////////////////////////////////////////////
00172 //     Function: FltHeader::convert_path
00173 //       Access: Public
00174 //  Description: Uses the PathReplace object to convert the named
00175 //               filename as read from the flt record to its actual
00176 //               name.
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 //     Function: FltHeader::set_flt_filename
00190 //       Access: Public
00191 //  Description: Sets the filename--especially the directory part--in
00192 //               which the flt file is considered to reside.  This is
00193 //               also implicitly set by read_flt().
00194 ////////////////////////////////////////////////////////////////////
00195 void FltHeader::
00196 set_flt_filename(const Filename &flt_filename) {
00197   _flt_filename = flt_filename;
00198 }
00199 
00200 ////////////////////////////////////////////////////////////////////
00201 //     Function: FltHeader::get_flt_filename
00202 //       Access: Public
00203 //  Description: Returns the directory in which the flt file is
00204 //               considered to reside.
00205 ////////////////////////////////////////////////////////////////////
00206 const Filename &FltHeader::
00207 get_flt_filename() const {
00208   return _flt_filename;
00209 }
00210 
00211 ////////////////////////////////////////////////////////////////////
00212 //     Function: FltHeader::read_flt
00213 //       Access: Public
00214 //  Description: Opens the indicated filename for reading and attempts
00215 //               to read the complete Flt file.  Returns FE_ok on
00216 //               success, otherwise on failure.
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 //     Function: FltHeader::read_flt
00234 //       Access: Public
00235 //  Description: Attempts to read a complete Flt file from the
00236 //               already-opened stream.  Returns FE_ok on success,
00237 //               otherwise on failure.
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 //     Function: FltHeader::write_flt
00266 //       Access: Public
00267 //  Description: Opens the indicated filename for writing and attempts
00268 //               to write the complete Flt file.  Returns FE_ok on
00269 //               success, otherwise on failure.
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 //     Function: FltHeader::write_flt
00286 //       Access: Public
00287 //  Description: Attempts to write a complete Flt file to the
00288 //               already-opened stream.  Returns FE_ok on success,
00289 //               otherwise on failure.
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 //     Function: FltHeader::set_auto_attr_update
00305 //       Access: Public
00306 //  Description: Controls whether texture .attr files are written
00307 //               automatically when write_flt() is called.  There are
00308 //               three possibilities:
00309 //
00310 //               AU_none: the .attr files are not written
00311 //               automatically; they must be written explicitly via a
00312 //               call to FltTexture::write_attr_data() if you want
00313 //               them to be written.
00314 //
00315 //               AU_if_missing: the .attr files are written only if
00316 //               they do not already exist.  This will not update any
00317 //               .attr files, even if the data is changed.
00318 //
00319 //               AU_always: the .attr files are always rewritten, even
00320 //               if they already exist and even if the data has not
00321 //               changed.
00322 //
00323 //               The default is AU_if_missing.
00324 ////////////////////////////////////////////////////////////////////
00325 void FltHeader::
00326 set_auto_attr_update(FltHeader::AttrUpdate attr) {
00327   _auto_attr_update = attr;
00328 }
00329 
00330 ////////////////////////////////////////////////////////////////////
00331 //     Function: FltHeader::get_auto_attr_update
00332 //       Access: Public
00333 //  Description: Returns the current setting of the auto_attr_update
00334 //               flag.  See sett_auto_attr_update().
00335 ////////////////////////////////////////////////////////////////////
00336 FltHeader::AttrUpdate FltHeader::
00337 get_auto_attr_update() const {
00338   return _auto_attr_update;
00339 }
00340 
00341 ////////////////////////////////////////////////////////////////////
00342 //     Function: FltHeader::get_flt_version
00343 //       Access: Public
00344 //  Description: Returns the version number of the flt file as
00345 //               reported in the header, times 100.  Divide by 100 to
00346 //               get the floating-point version number.
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 //     Function: FltHeader::set_flt_version
00359 //       Access: Public
00360 //  Description: Changes the version number of the flt file that will
00361 //               be reported in the header.  Pass in the
00362 //               floating-point version number times 100.
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 //     Function: FltHeader::min_flt_version
00375 //       Access: Public, Static
00376 //  Description: Returns the earliest flt version number that this
00377 //               codebase supports (times 100).  Earlier versions will
00378 //               probably not work.
00379 ////////////////////////////////////////////////////////////////////
00380 int FltHeader::
00381 min_flt_version() {
00382   return 1400;
00383 }
00384 
00385 ////////////////////////////////////////////////////////////////////
00386 //     Function: FltHeader::max_flt_version
00387 //       Access: Public, Static
00388 //  Description: Returns the latest flt version number that this
00389 //               codebase is known to support (times 100).  Later
00390 //               versions might work, but then again they may not.
00391 ////////////////////////////////////////////////////////////////////
00392 int FltHeader::
00393 max_flt_version() {
00394   return 1570;
00395 }
00396 
00397 ////////////////////////////////////////////////////////////////////
00398 //     Function: FltHeader::check_version
00399 //       Access: Public
00400 //  Description: Verifies that the version number read from the header
00401 //               is an understood version number, and prints a warning
00402 //               to the user if this is not so--the read may or may
00403 //               not succeed.  Returns true if the version number is
00404 //               acceptable (and no warning is printed), or false if
00405 //               it is questionable (and a warning is printed).
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 //     Function: FltHeader::get_units
00435 //       Access: Public
00436 //  Description: Returns the units indicated by the flt header, or
00437 //               DU_invalid if the units in the header are not
00438 //               understood.
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   // Unknown units.
00460   return DU_invalid;
00461 }
00462 
00463 ////////////////////////////////////////////////////////////////////
00464 //     Function: FltHeader::has_instance
00465 //       Access: Public
00466 //  Description: Returns true if a instance subtree with the given
00467 //               index has been defined.
00468 ////////////////////////////////////////////////////////////////////
00469 bool FltHeader::
00470 has_instance(int instance_index) const {
00471   return (_instances.count(instance_index) != 0);
00472 }
00473 
00474 ////////////////////////////////////////////////////////////////////
00475 //     Function: FltHeader::get_instance
00476 //       Access: Public
00477 //  Description: Returns the instance subtree associated with the
00478 //               given index, or NULL if there is no such instance.
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 //     Function: FltHeader::clear_instances
00492 //       Access: Public
00493 //  Description: Removes all instance subtrees from the instance pool.
00494 ////////////////////////////////////////////////////////////////////
00495 void FltHeader::
00496 clear_instances() {
00497   _instances.clear();
00498 }
00499 
00500 ////////////////////////////////////////////////////////////////////
00501 //     Function: FltHeader::add_instance
00502 //       Access: Public
00503 //  Description: Defines a new instance subtree.  This subtree is not
00504 //               itself part of the hierarchy; it marks geometry that
00505 //               may be instanced to various beads elsewhere in the
00506 //               hierarchy by creating a corresponding FltInstanceRef
00507 //               bead.
00508 ////////////////////////////////////////////////////////////////////
00509 void FltHeader::
00510 add_instance(FltInstanceDefinition *instance) {
00511   _instances[instance->_instance_index] = instance;
00512 }
00513 
00514 ////////////////////////////////////////////////////////////////////
00515 //     Function: FltHeader::remove_instance
00516 //       Access: Public
00517 //  Description: Removes a particular instance subtree from the pool,
00518 //               if it exists.
00519 ////////////////////////////////////////////////////////////////////
00520 void FltHeader::
00521 remove_instance(int instance_index) {
00522   _instances.erase(instance_index);
00523 }
00524 
00525 ////////////////////////////////////////////////////////////////////
00526 //     Function: FltHeader::get_num_vertices
00527 //       Access: Public
00528 //  Description: Returns the number of vertices in the vertex palette.
00529 ////////////////////////////////////////////////////////////////////
00530 int FltHeader::
00531 get_num_vertices() const {
00532   return _vertices.size();
00533 }
00534 
00535 ////////////////////////////////////////////////////////////////////
00536 //     Function: FltHeader::get_vertex
00537 //       Access: Public
00538 //  Description: Returns the nth vertex of the vertex palette.
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 //     Function: FltHeader::clear_vertices
00548 //       Access: Public
00549 //  Description: Removes all vertices from the vertex palette.
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 //     Function: FltHeader::add_vertex
00562 //       Access: Public
00563 //  Description: Adds a new vertex to the end of the vertex palette.
00564 //               If this particular vertex was already present in the
00565 //               palette, does nothing.
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 //     Function: FltHeader::get_vertex_by_offset
00579 //       Access: Public
00580 //  Description: Returns the particular vertex pointer associated with
00581 //               the given byte offset into the vertex palette.  If
00582 //               there is no such vertex in the palette, this
00583 //               generates an error message and returns NULL.
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 //     Function: FltHeader::get_offset_by_vertex
00602 //       Access: Public
00603 //  Description: Returns the byte offset into the vertex palette
00604 //               associated with the given vertex pointer.  If there
00605 //               is no such vertex in the palette, this generates an
00606 //               error message and returns 0.
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 //     Function: FltHeader::get_num_colors
00625 //       Access: Public
00626 //  Description: Returns the total number of different colors in the
00627 //               color palette.  This includes all different colors,
00628 //               and represents the complete range of alloable color
00629 //               indices.  This is different from the actual number of
00630 //               color entries as read directly from the color
00631 //               palette, since each color entry defines a number of
00632 //               different intensity levels--the value returned by
00633 //               get_num_colors() is equal to get_num_color_entries()
00634 //               * get_num_color_shades().
00635 ////////////////////////////////////////////////////////////////////
00636 int FltHeader::
00637 get_num_colors() const {
00638   return _colors.size() * get_num_color_shades();
00639 }
00640 
00641 ////////////////////////////////////////////////////////////////////
00642 //     Function: FltHeader::get_color
00643 //       Access: Public
00644 //  Description: Returns the four-component color corresponding to the
00645 //               given color index.  Each component will be in the
00646 //               range [0, 1].
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 //     Function: FltHeader::get_rgb
00665 //       Access: Public
00666 //  Description: Returns the three-component color corresponding to
00667 //               the given color index, ignoring the alpha component.
00668 //               Each component will be in the range [0, 1].
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 //     Function: FltHeader::has_color_name
00687 //       Access: Public
00688 //  Description: Returns true if the given color is named, false
00689 //               otherwise.
00690 ////////////////////////////////////////////////////////////////////
00691 bool FltHeader::
00692 has_color_name(int color_index) const {
00693   return (_color_names.count(color_index) != 0);
00694 }
00695 
00696 ////////////////////////////////////////////////////////////////////
00697 //     Function: FltHeader::get_color_name
00698 //       Access: Public
00699 //  Description: Returns the name associated with the given color, if
00700 //               any.
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 //     Function: FltHeader::get_closest_color
00714 //       Access: Public
00715 //  Description: Returns the color index of the nearest color in the
00716 //               palette that matches the given four-component color,
00717 //               including alpha.
00718 ////////////////////////////////////////////////////////////////////
00719 int FltHeader::
00720 get_closest_color(Colorf color) const {
00721   // Since the colortable stores the brightest colors, with
00722   // num_color_shades scaled versions of each color implicitly
00723   // available, we really only care about the relative brightnesses of
00724   // the various components.  Normalize the color in terms of the
00725   // largest of these.
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     // Oh, this is invisible black.
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       // color[0] is largest.
00737       scale = color[0];
00738 
00739     } else if (color[1] >= color[2] && color[1] >= color[3]) {
00740       // color[1] is largest.
00741       scale = color[1];
00742 
00743     } else if (color[2] >= color[3]) {
00744       // color[2] is largest.
00745       scale = color[2];
00746 
00747     } else {
00748       // color[3] is largest.
00749       scale = color[3];
00750     }
00751     color /= scale;
00752   }
00753 
00754   // Now search for the best match.
00755   float best_dist = 5.0;  // Greater than 4.
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 //     Function: FltHeader::get_closest_rgb
00779 //       Access: Public
00780 //  Description: Returns the color index of the nearest color in the
00781 //               palette that matches the given three-component color,
00782 //               ignoring alpha.
00783 ////////////////////////////////////////////////////////////////////
00784 int FltHeader::
00785 get_closest_rgb(RGBColorf color) const {
00786   // Since the colortable stores the brightest colors, with
00787   // num_color_shades scaled versions of each color implicitly
00788   // available, we really only care about the relative brightnesses of
00789   // the various components.  Normalize the color in terms of the
00790   // largest of these.
00791 
00792   double scale = 1.0;
00793 
00794   if (color[0] == 0.0 && color[1] == 0.0 && color[2] == 0.0) {
00795     // Oh, this is black.
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       // color[0] is largest.
00802       scale = color[0];
00803 
00804     } else if (color[1] >= color[2]) {
00805       // color[1] is largest.
00806       scale = color[1];
00807 
00808     } else {
00809       // color[2] is largest.
00810       scale = color[2];
00811     }
00812     color /= scale;
00813   }
00814 
00815   // Now search for the best match.
00816   float best_dist = 5.0;  // Greater than 4.
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 //     Function: FltHeader::get_num_color_entries
00840 //       Access: Public
00841 //  Description: Returns the number of actual entries in the color
00842 //               palette.  This is based on the version of the flt
00843 //               file, and is usually either 512 or 1024.
00844 ////////////////////////////////////////////////////////////////////
00845 int FltHeader::
00846 get_num_color_entries() const {
00847   return _colors.size();
00848 }
00849 
00850 ////////////////////////////////////////////////////////////////////
00851 //     Function: FltHeader::get_num_color_shades
00852 //       Access: Public
00853 //  Description: Returns the number of shades of brightness of each
00854 //               entry in the color palette.  This is a fixed property
00855 //               of MultiGen files: each entry in the palette actually
00856 //               represents a range of this many colors.
00857 ////////////////////////////////////////////////////////////////////
00858 int FltHeader::
00859 get_num_color_shades() const {
00860   return 128;
00861 }
00862 
00863 ////////////////////////////////////////////////////////////////////
00864 //     Function: FltHeader::get_color
00865 //       Access: Public
00866 //  Description: Decodes a MultiGen color, as stored on a face or
00867 //               vertex, into an actual four-component Colorf.
00868 //               Normally you need not call this directly; there are
00869 //               color accessors defined on faces and vertices that do
00870 //               this.
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   // MultiGen doesn't yet use the A component of RGBA.
00885   //color[3] = packed_color._a / 255.0;
00886   color[3] = 1.0 - (transparency / 65535.0);
00887   return color;
00888 }
00889 
00890 ////////////////////////////////////////////////////////////////////
00891 //     Function: FltHeader::get_color
00892 //       Access: Public
00893 //  Description: Decodes a MultiGen color, as stored on a face or
00894 //               vertex, into an actual three-component RGBColorf.
00895 //               Normally you need not call this directly; there are
00896 //               color accessors defined on faces and vertices that do
00897 //               this.
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 //     Function: FltHeader::has_material
00915 //       Access: Public
00916 //  Description: Returns true if a material with the given index has
00917 //               been defined.
00918 ////////////////////////////////////////////////////////////////////
00919 bool FltHeader::
00920 has_material(int material_index) const {
00921   return (_materials.count(material_index) != 0);
00922 }
00923 
00924 ////////////////////////////////////////////////////////////////////
00925 //     Function: FltHeader::get_material
00926 //       Access: Public
00927 //  Description: Returns the material associated with the given index,
00928 //               or NULL if there is no such material.
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 //     Function: FltHeader::clear_materials
00942 //       Access: Public
00943 //  Description: Removes all materials from the palette.
00944 ////////////////////////////////////////////////////////////////////
00945 void FltHeader::
00946 clear_materials() {
00947   _materials.clear();
00948 }
00949 
00950 ////////////////////////////////////////////////////////////////////
00951 //     Function: FltHeader::add_material
00952 //       Access: Public
00953 //  Description: Defines a new material.  The material is added in the
00954 //               position indicated by the material's index number.
00955 //               If there is already a material defined for that index
00956 //               number, it is replaced.
00957 ////////////////////////////////////////////////////////////////////
00958 void FltHeader::
00959 add_material(FltMaterial *material) {
00960   _materials[material->_material_index] = material;
00961 }
00962 
00963 ////////////////////////////////////////////////////////////////////
00964 //     Function: FltHeader::remove_material
00965 //       Access: Public
00966 //  Description: Removes a particular material from the material
00967 //               palette, if it exists.
00968 ////////////////////////////////////////////////////////////////////
00969 void FltHeader::
00970 remove_material(int material_index) {
00971   _materials.erase(material_index);
00972 }
00973 
00974 ////////////////////////////////////////////////////////////////////
00975 //     Function: FltHeader::has_texture
00976 //       Access: Public
00977 //  Description: Returns true if a texture with the given index has
00978 //               been defined.
00979 ////////////////////////////////////////////////////////////////////
00980 bool FltHeader::
00981 has_texture(int texture_index) const {
00982   return (_textures.count(texture_index) != 0);
00983 }
00984 
00985 ////////////////////////////////////////////////////////////////////
00986 //     Function: FltHeader::get_texture
00987 //       Access: Public
00988 //  Description: Returns the texture associated with the given index,
00989 //               or NULL if there is no such texture.
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 //     Function: FltHeader::clear_textures
01003 //       Access: Public
01004 //  Description: Removes all textures from the palette.
01005 ////////////////////////////////////////////////////////////////////
01006 void FltHeader::
01007 clear_textures() {
01008   _textures.clear();
01009 }
01010 
01011 ////////////////////////////////////////////////////////////////////
01012 //     Function: FltHeader::add_texture
01013 //       Access: Public
01014 //  Description: Defines a new texture.  The texture is added in the
01015 //               position indicated by the texture's index number.
01016 //               If there is already a texture defined for that index
01017 //               number, it is replaced.
01018 ////////////////////////////////////////////////////////////////////
01019 void FltHeader::
01020 add_texture(FltTexture *texture) {
01021   _textures[texture->_pattern_index] = texture;
01022 }
01023 
01024 ////////////////////////////////////////////////////////////////////
01025 //     Function: FltHeader::remove_texture
01026 //       Access: Public
01027 //  Description: Removes a particular texture from the texture
01028 //               palette, if it exists.
01029 ////////////////////////////////////////////////////////////////////
01030 void FltHeader::
01031 remove_texture(int texture_index) {
01032   _textures.erase(texture_index);
01033 }
01034 
01035 ////////////////////////////////////////////////////////////////////
01036 //     Function: FltHeader::has_light_source
01037 //       Access: Public
01038 //  Description: Returns true if a light source with the given index
01039 //               has been defined.
01040 ////////////////////////////////////////////////////////////////////
01041 bool FltHeader::
01042 has_light_source(int light_index) const {
01043   return (_light_sources.count(light_index) != 0);
01044 }
01045 
01046 ////////////////////////////////////////////////////////////////////
01047 //     Function: FltHeader::get_light_source
01048 //       Access: Public
01049 //  Description: Returns the light source associated with the given
01050 //               index, or NULL if there is no such light source.
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 //     Function: FltHeader::clear_light_sources
01064 //       Access: Public
01065 //  Description: Removes all light sources from the palette.
01066 ////////////////////////////////////////////////////////////////////
01067 void FltHeader::
01068 clear_light_sources() {
01069   _light_sources.clear();
01070 }
01071 
01072 ////////////////////////////////////////////////////////////////////
01073 //     Function: FltHeader::add_light_source
01074 //       Access: Public
01075 //  Description: Defines a new light source.  The light source is
01076 //               added in the position indicated by its light index
01077 //               number.  If there is already a light source defined
01078 //               for that index number, it is replaced.
01079 ////////////////////////////////////////////////////////////////////
01080 void FltHeader::
01081 add_light_source(FltLightSourceDefinition *light_source) {
01082   _light_sources[light_source->_light_index] = light_source;
01083 }
01084 
01085 ////////////////////////////////////////////////////////////////////
01086 //     Function: FltHeader::remove_light_source
01087 //       Access: Public
01088 //  Description: Removes a particular light source from the light
01089 //               source palette, if it exists.
01090 ////////////////////////////////////////////////////////////////////
01091 void FltHeader::
01092 remove_light_source(int light_index) {
01093   _light_sources.erase(light_index);
01094 }
01095 
01096 ////////////////////////////////////////////////////////////////////
01097 //     Function: FltHeader::got_eyepoint_trackplane_palette
01098 //       Access: Public
01099 //  Description: Returns true if we have read an eyepoint/trackplane
01100 //               palette, and at least some of the eyepoints and
01101 //               trackplanes are therefore expected to be meaningful.
01102 ////////////////////////////////////////////////////////////////////
01103 bool FltHeader::
01104 got_eyepoint_trackplane_palette() const {
01105   return _got_eyepoint_trackplane_palette;
01106 }
01107 
01108 ////////////////////////////////////////////////////////////////////
01109 //     Function: FltHeader::set_eyepoint_trackplane_palette
01110 //       Access: Public
01111 //  Description: Sets the state of the eyepoint/trackplane palette
01112 //               flag.  When this is false, the palette is believed to
01113 //               be meaningless, and will not be written; when it is
01114 //               true, the palette is believed to contain at least
01115 //               some meaningful data, and will be written.
01116 ////////////////////////////////////////////////////////////////////
01117 void FltHeader::
01118 set_eyepoint_trackplane_palette(bool flag) {
01119   _got_eyepoint_trackplane_palette = flag;
01120 }
01121 
01122 ////////////////////////////////////////////////////////////////////
01123 //     Function: FltHeader::get_num_eyepoints
01124 //       Access: Public
01125 //  Description: Returns the number of eyepoints in the
01126 //               eyepoint/trackplane palette.  This is presently fixed
01127 //               at 10, according to the MultiGen specs.
01128 ////////////////////////////////////////////////////////////////////
01129 int FltHeader::
01130 get_num_eyepoints() const {
01131   return 10;
01132 }
01133 
01134 ////////////////////////////////////////////////////////////////////
01135 //     Function: FltHeader::get_eyepoint
01136 //       Access: Public
01137 //  Description: Returns the nth eyepoint in the eyepoint/trackplane
01138 //               palette.
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 //     Function: FltHeader::get_num_trackplanes
01148 //       Access: Public
01149 //  Description: Returns the number of trackplanes in the
01150 //               eyepoint/trackplane palette.  This is presently fixed
01151 //               at 10, according to the MultiGen specs.
01152 ////////////////////////////////////////////////////////////////////
01153 int FltHeader::
01154 get_num_trackplanes() const {
01155   return 10;
01156 }
01157 
01158 ////////////////////////////////////////////////////////////////////
01159 //     Function: FltHeader::get_trackplane
01160 //       Access: Public
01161 //  Description: Returns the nth trackplane in the eyepoint/trackplane
01162 //               palette.
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 //     Function: FltHeader::update_vertex_lookups
01172 //       Access: Public
01173 //  Description: Recomputes the offsets_by_vertex and
01174 //               vertices_by_offset tables.  This reflects the flt
01175 //               file as it will be written out, but not necessarily
01176 //               as it was read in.
01177 //
01178 //               The return value is the total length of the vertex
01179 //               palette, including the header record.
01180 ////////////////////////////////////////////////////////////////////
01181 int FltHeader::
01182 update_vertex_lookups() {
01183   // We start with the length of the vertex palette record itself.
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 //     Function: FltHeader::extract_record
01202 //       Access: Protected, Virtual
01203 //  Description: Fills in the information in this bead based on the
01204 //               information given in the indicated datagram, whose
01205 //               opcode has already been read.  Returns true on
01206 //               success, false if the datagram is invalid.
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       // Undocumented padding.
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           // Undocumented padding.
01279           iterator.skip_bytes(4);
01280         }
01281       }
01282     }
01283   }
01284 
01285   check_remaining_size(iterator);
01286   return true;
01287 }
01288 
01289 ////////////////////////////////////////////////////////////////////
01290 //     Function: FltHeader::extract_ancillary
01291 //       Access: Protected, Virtual
01292 //  Description: Checks whether the given bead, which follows this
01293 //               bead sequentially in the file, is an ancillary record
01294 //               of this bead.  If it is, extracts the relevant
01295 //               information and returns true; otherwise, leaves it
01296 //               alone and returns false.
01297 ////////////////////////////////////////////////////////////////////
01298 bool FltHeader::
01299 extract_ancillary(FltRecordReader &reader) {
01300   switch (reader.get_opcode()) {
01301   case FO_vertex_palette:
01302     // We're about to begin the vertex palette!
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     // Here's a new vertex for the palette.
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 //     Function: FltHeader::build_record
01342 //       Access: Protected, Virtual
01343 //  Description: Fills up the current record on the FltRecordWriter with
01344 //               data for this record, but does not advance the
01345 //               writer.  Returns true on success, false if there is
01346 //               some error.
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     // New with 15.2
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       // New with 15.6
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         // New with 15.7
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 //     Function: FltHeader::write_ancillary
01428 //       Access: Protected, Virtual
01429 //  Description: Writes whatever ancillary records are required for
01430 //               this bead.  Returns FE_ok on success, or something
01431 //               else on error.
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 //     Function: FltHeader::extract_vertex
01472 //       Access: Private
01473 //  Description: Reads a single vertex ancillary record.  It is
01474 //               assumed that all the vertex records will immediately
01475 //               follow the vertex palette record.
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   // _vertex_lookups_stale remains false.
01490 
01491   return true;
01492 }
01493 
01494 ////////////////////////////////////////////////////////////////////
01495 //     Function: FltHeader::extract_color_palette
01496 //       Access: Private
01497 //  Description: Reads the color palette.
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       // An early end to the palette is acceptable.
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   // Now pull out the color names.
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 //     Function: FltHeader::extract_material
01545 //       Access: Private
01546 //  Description: Reads a single material ancillary record.
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 //     Function: FltHeader::extract_14_material_palette
01561 //       Access: Private
01562 //  Description: Reads the v14.2 material palette.
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       // An early end to the palette is acceptable.
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 //     Function: FltHeader::extract_texture
01595 //       Access: Private
01596 //  Description: Reads a single texture ancillary record.
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 //     Function: FltHeader::extract_texture_map
01611 //       Access: Private
01612 //  Description: Reads the a single texture mapping ancillary record.
01613 //               This describes a kind of texture mapping in the
01614 //               texture mapping palette.
01615 ////////////////////////////////////////////////////////////////////
01616 bool FltHeader::
01617 extract_texture_map(FltRecordReader &reader) {
01618   // At the moment, we ignore this, since it's not needed for
01619   // meaningful extraction of data: we can get this information from
01620   // the UV's for a particular model.  We just add an
01621   // UnsupportedRecord for it.
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 //     Function: FltHeader::extract_light_source
01633 //       Access: Private
01634 //  Description: Reads a single light source ancillary record.
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 //     Function: FltHeader::extract_eyepoint_palette
01649 //       Access: Private
01650 //  Description: Reads the eyepoint/trackplane palette.
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     // I have no idea what bytes are supposed to be here in earlier
01678     // versions that 14.2, but who really cares?  Don't bother
01679     // reporting it if there are too many bytes in old versions.
01680     check_remaining_size(iterator, "eyepoint palette");
01681   }
01682   return true;
01683 }
01684 
01685 ////////////////////////////////////////////////////////////////////
01686 //     Function: FltHeader::write_vertex_palette
01687 //       Access: Private
01688 //  Description: Writes out the vertex palette with all of its
01689 //               vertices.
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   // Now write out each vertex in the palette.
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 //     Function: FltHeader::write_color_palette
01720 //       Access: Private
01721 //  Description: Writes out the color palette.
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   // How many colors should we write?
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   // Now we might need to pad the record to fill up the required
01743   // number of colors.
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   // Now append all the names at the end.
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 //     Function: FltHeader::write_material_palette
01772 //       Access: Private
01773 //  Description: Writes out the material palette.
01774 ////////////////////////////////////////////////////////////////////
01775 FltError FltHeader::
01776 write_material_palette(FltRecordWriter &writer) const {
01777   FltError result;
01778 
01779   if (get_flt_version() >= 1520) {
01780     // Write a version 15 material palette.
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     // Write a version 14 material palette.
01794     if (_materials.empty()) {
01795       // No palette is OK.
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 //     Function: FltHeader::write_texture_palette
01828 //       Access: Private
01829 //  Description: Writes out the texture palette.
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 //     Function: FltHeader::write_light_source_palette
01850 //       Access: Private
01851 //  Description: Writes out the light source palette.
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 //     Function: FltHeader::write_eyepoint_palette
01872 //       Access: Private
01873 //  Description: Writes out the eyepoint/trackplane palette, if we
01874 //               have one.
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 }

Generated on Fri May 2 03:19:16 2003 for Panda-Tool by doxygen1.3