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

pandatool/src/fltegg/fltToEggConverter.cxx

Go to the documentation of this file.
00001 // Filename: fltToEggConverter.cxx
00002 // Created by:  drose (17Apr01)
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 "fltToEggConverter.h"
00020 
00021 #include "fltRecord.h"
00022 #include "fltLOD.h"
00023 #include "fltGroup.h"
00024 #include "fltObject.h"
00025 #include "fltBeadID.h"
00026 #include "fltBead.h"
00027 #include "fltFace.h"
00028 #include "fltVertex.h"
00029 #include "fltVertexList.h"
00030 #include "fltExternalReference.h"
00031 #include "dcast.h"
00032 #include "eggData.h"
00033 #include "eggGroup.h"
00034 #include "eggSwitchCondition.h"
00035 #include "eggPrimitive.h"
00036 #include "eggPolygon.h"
00037 #include "eggPoint.h"
00038 #include "eggVertex.h"
00039 #include "eggVertexPool.h"
00040 #include "eggExternalReference.h"
00041 #include "string_utils.h"
00042 
00043 
00044 ////////////////////////////////////////////////////////////////////
00045 //     Function: FltToEggConverter::Constructor
00046 //       Access: Public
00047 //  Description:
00048 ////////////////////////////////////////////////////////////////////
00049 FltToEggConverter::
00050 FltToEggConverter() {
00051   _compose_transforms = false;
00052 }
00053 
00054 ////////////////////////////////////////////////////////////////////
00055 //     Function: FltToEggConverter::Copy Constructor
00056 //       Access: Public
00057 //  Description:
00058 ////////////////////////////////////////////////////////////////////
00059 FltToEggConverter::
00060 FltToEggConverter(const FltToEggConverter &copy) :
00061   SomethingToEggConverter(copy),
00062   _compose_transforms(copy._compose_transforms)
00063 {
00064 }
00065 
00066 ////////////////////////////////////////////////////////////////////
00067 //     Function: FltToEggConverter::Destructor
00068 //       Access: Public
00069 //  Description:
00070 ////////////////////////////////////////////////////////////////////
00071 FltToEggConverter::
00072 ~FltToEggConverter() {
00073   cleanup();
00074 }
00075 
00076 ////////////////////////////////////////////////////////////////////
00077 //     Function: FltToEggConverter::make_copy
00078 //       Access: Public, Virtual
00079 //  Description: Allocates and returns a new copy of the converter.
00080 ////////////////////////////////////////////////////////////////////
00081 SomethingToEggConverter *FltToEggConverter::
00082 make_copy() {
00083   return new FltToEggConverter(*this);
00084 }
00085 
00086 
00087 ////////////////////////////////////////////////////////////////////
00088 //     Function: FltToEggConverter::get_name
00089 //       Access: Public, Virtual
00090 //  Description: Returns the English name of the file type this
00091 //               converter supports.
00092 ////////////////////////////////////////////////////////////////////
00093 string FltToEggConverter::
00094 get_name() const {
00095   return "MultiGen";
00096 }
00097 
00098 ////////////////////////////////////////////////////////////////////
00099 //     Function: FltToEggConverter::get_extension
00100 //       Access: Public, Virtual
00101 //  Description: Returns the common extension of the file type this
00102 //               converter supports.
00103 ////////////////////////////////////////////////////////////////////
00104 string FltToEggConverter::
00105 get_extension() const {
00106   return "flt";
00107 }
00108 
00109 ////////////////////////////////////////////////////////////////////
00110 //     Function: FltToEggConverter::convert_file
00111 //       Access: Public, Virtual
00112 //  Description: Handles the reading of the input file and converting
00113 //               it to egg.  Returns true if successful, false
00114 //               otherwise.
00115 //
00116 //               This is designed to be as generic as possible,
00117 //               generally in support of run-time loading.
00118 //               Command-line converters may choose to use
00119 //               convert_flt() instead, as it provides more control.
00120 ////////////////////////////////////////////////////////////////////
00121 bool FltToEggConverter::
00122 convert_file(const Filename &filename) {
00123   PT(FltHeader) header = new FltHeader(_path_replace);
00124 
00125   nout << "Reading " << filename << "\n";
00126   FltError result = header->read_flt(filename);
00127   if (result != FE_ok) {
00128     nout << "Unable to read: " << result << "\n";
00129     return false;
00130   }
00131 
00132   header->check_version();
00133   return convert_flt(header);
00134 }
00135 
00136 ////////////////////////////////////////////////////////////////////
00137 //     Function: FltToEggConverter::convert_flt
00138 //       Access: Public
00139 //  Description: Fills up the egg_data structure according to the
00140 //               indicated lwo structure.
00141 ////////////////////////////////////////////////////////////////////
00142 bool FltToEggConverter::
00143 convert_flt(const FltHeader *flt_header) {
00144   if (_egg_data->get_coordinate_system() == CS_default) {
00145     _egg_data->set_coordinate_system(CS_zup_right);
00146   }
00147 
00148   _error = false;
00149   _flt_header = flt_header;
00150 
00151   // Generate a default vertex pool.
00152   _main_egg_vpool = new EggVertexPool("vpool");
00153   _egg_data->add_child(_main_egg_vpool.p());
00154 
00155   // We could populate the vertex pool right away, but it's better to
00156   // defer each vertex until we encounter it, since some of the
00157   // vertices may need to be adjusted to match the particular polygon
00158   // they're assigned to (for instance, to apply a transparency or
00159   // something).
00160 
00161   FltToEggLevelState state(this);
00162   state._egg_parent = _egg_data;
00163   convert_record(_flt_header, state);
00164 
00165   if (_main_egg_vpool->empty()) {
00166     // If we didn't get any global vertices, remove the vertex pool
00167     // just for cleanliness.
00168     _egg_data->remove_child(_main_egg_vpool.p());
00169   }
00170 
00171   cleanup();
00172 
00173   return !_error;
00174 }
00175 
00176 ////////////////////////////////////////////////////////////////////
00177 //     Function: FltToEggConverter::cleanup
00178 //       Access: Private
00179 //  Description: Frees all the internal data structures after we're
00180 //               done converting, and resets the converter to its
00181 //               initial state.
00182 ////////////////////////////////////////////////////////////////////
00183 void FltToEggConverter::
00184 cleanup() {
00185   _flt_header.clear();
00186   _main_egg_vpool.clear();
00187   _textures.clear();
00188 }
00189 
00190 ////////////////////////////////////////////////////////////////////
00191 //     Function: FltToEggConverter::convert_record
00192 //       Access: Private
00193 //  Description: Converts the record and all of its children.
00194 ////////////////////////////////////////////////////////////////////
00195 void FltToEggConverter::
00196 convert_record(const FltRecord *flt_record, FltToEggLevelState &state) {
00197   int num_children = flt_record->get_num_children();
00198 
00199   for (int i = 0; i < num_children; i++) {
00200     const FltRecord *child = flt_record->get_child(i);
00201     dispatch_record(child, state);
00202   }
00203 }
00204 
00205 ////////////////////////////////////////////////////////////////////
00206 //     Function: FltToEggConverter::dispatch_record
00207 //       Access: Private
00208 //  Description: Determines what kind of record this is and calls the
00209 //               appropriate convert function.
00210 ////////////////////////////////////////////////////////////////////
00211 void FltToEggConverter::
00212 dispatch_record(const FltRecord *flt_record, FltToEggLevelState &state) {
00213   if (flt_record->is_of_type(FltLOD::get_class_type())) {
00214     convert_lod(DCAST(FltLOD, flt_record), state);
00215 
00216   } else if (flt_record->is_of_type(FltGroup::get_class_type())) {
00217     convert_group(DCAST(FltGroup, flt_record), state);
00218 
00219   } else if (flt_record->is_of_type(FltObject::get_class_type())) {
00220     convert_object(DCAST(FltObject, flt_record), state);
00221 
00222   } else if (flt_record->is_of_type(FltFace::get_class_type())) {
00223     convert_face(DCAST(FltFace, flt_record), state);
00224 
00225   } else if (flt_record->is_of_type(FltExternalReference::get_class_type())) {
00226     convert_ext_ref(DCAST(FltExternalReference, flt_record), state);
00227 
00228     // Fallbacks.
00229   } else if (flt_record->is_of_type(FltBeadID::get_class_type())) {
00230     convert_bead_id(DCAST(FltBeadID, flt_record), state);
00231 
00232   } else if (flt_record->is_of_type(FltBead::get_class_type())) {
00233     convert_bead(DCAST(FltBead, flt_record), state);
00234 
00235   } else {
00236     convert_record(flt_record, state);
00237   }
00238 }
00239 
00240 ////////////////////////////////////////////////////////////////////
00241 //     Function: FltToEggConverter::convert_lod
00242 //       Access: Private
00243 //  Description: Converts the LOD bead and all of its children.
00244 ////////////////////////////////////////////////////////////////////
00245 void FltToEggConverter::
00246 convert_lod(const FltLOD *flt_lod, FltToEggLevelState &state) {
00247   EggGroup *egg_group = new EggGroup(flt_lod->get_id());
00248   state._egg_parent->add_child(egg_group);
00249 
00250   EggSwitchConditionDistance lod
00251     (flt_lod->_switch_in, flt_lod->_switch_out,
00252      LPoint3d(flt_lod->_center_x, flt_lod->_center_y, flt_lod->_center_z),
00253      flt_lod->_transition_range);
00254   egg_group->set_lod(lod);
00255 
00256   state.set_transform(flt_lod, egg_group);
00257   parse_comment(flt_lod, egg_group);
00258 
00259   FltToEggLevelState next_state(state);
00260   next_state._egg_parent = egg_group;
00261   convert_record(flt_lod, next_state);
00262 }
00263 
00264 ////////////////////////////////////////////////////////////////////
00265 //     Function: FltToEggConverter::convert_group
00266 //       Access: Private
00267 //  Description: Converts the group and all of its children.
00268 ////////////////////////////////////////////////////////////////////
00269 void FltToEggConverter::
00270 convert_group(const FltGroup *flt_group, FltToEggLevelState &state) {
00271   EggGroup *egg_group = new EggGroup(flt_group->get_id());
00272   state._egg_parent->add_child(egg_group);
00273 
00274   if ((flt_group->_flags & FltGroup::F_forward_animation) != 0) {
00275     // It's a sequence animation.
00276     egg_group->set_switch_flag(true);
00277     egg_group->set_switch_fps(24.0);
00278   }
00279 
00280   state.set_transform(flt_group, egg_group);
00281   parse_comment(flt_group, egg_group);
00282 
00283   ///*** replicate count.
00284 
00285   FltToEggLevelState next_state(state);
00286   next_state._egg_parent = egg_group;
00287   convert_record(flt_group, next_state);
00288 }
00289 
00290 ////////////////////////////////////////////////////////////////////
00291 //     Function: FltToEggConverter::convert_object
00292 //       Access: Private
00293 //  Description: Converts the object and all of its children.
00294 ////////////////////////////////////////////////////////////////////
00295 void FltToEggConverter::
00296 convert_object(const FltObject *flt_object, FltToEggLevelState &state) {
00297   EggGroup *egg_group = new EggGroup(flt_object->get_id());
00298   state._egg_parent->add_child(egg_group);
00299 
00300   state.set_transform(flt_object, egg_group);
00301   parse_comment(flt_object, egg_group);
00302 
00303   FltToEggLevelState next_state(state);
00304   next_state._flt_object = flt_object;
00305   next_state._egg_parent = egg_group;
00306   convert_record(flt_object, next_state);
00307 }
00308 
00309 ////////////////////////////////////////////////////////////////////
00310 //     Function: FltToEggConverter::convert_bead_id
00311 //       Access: Private
00312 //  Description: Converts the generic bead (with ID) and all of its
00313 //               children.
00314 ////////////////////////////////////////////////////////////////////
00315 void FltToEggConverter::
00316 convert_bead_id(const FltBeadID *flt_bead, FltToEggLevelState &state) {
00317   nout << "Don't know how to convert beads of type " << flt_bead->get_type()
00318        << "\n";
00319   EggGroup *egg_group = new EggGroup(flt_bead->get_id());
00320   state._egg_parent->add_child(egg_group);
00321 
00322   state.set_transform(flt_bead, egg_group);
00323   parse_comment(flt_bead, egg_group);
00324 
00325   FltToEggLevelState next_state(state);
00326   next_state._egg_parent = egg_group;
00327   convert_record(flt_bead, next_state);
00328 }
00329 
00330 ////////////////////////////////////////////////////////////////////
00331 //     Function: FltToEggConverter::convert_bead
00332 //       Access: Private
00333 //  Description: Converts the generic bead (without ID) and all of its
00334 //               children.
00335 ////////////////////////////////////////////////////////////////////
00336 void FltToEggConverter::
00337 convert_bead(const FltBead *flt_bead, FltToEggLevelState &state) {
00338   nout << "Don't know how to convert beads of type " << flt_bead->get_type()
00339        << "\n";
00340   EggGroup *egg_group = new EggGroup;
00341   state._egg_parent->add_child(egg_group);
00342 
00343   state.set_transform(flt_bead, egg_group);
00344   parse_comment(flt_bead, egg_group);
00345 
00346   FltToEggLevelState next_state(state);
00347   next_state._egg_parent = egg_group;
00348   convert_record(flt_bead, next_state);
00349 }
00350 
00351 ////////////////////////////////////////////////////////////////////
00352 //     Function: FltToEggConverter::convert_face
00353 //       Access: Private
00354 //  Description: Converts the face and all of its children.
00355 ////////////////////////////////////////////////////////////////////
00356 void FltToEggConverter::
00357 convert_face(const FltFace *flt_face, FltToEggLevelState &state) {
00358   bool is_light;
00359   switch (flt_face->_draw_type) {
00360   case FltGeometry::DT_omni_light:
00361   case FltGeometry::DT_uni_light:
00362   case FltGeometry::DT_bi_light:
00363     is_light = true;
00364     break;
00365 
00366   default:
00367     is_light = false;
00368   }
00369 
00370   PT(EggPrimitive) egg_prim;
00371   if (is_light) {
00372     egg_prim = new EggPoint;
00373   } else {
00374     egg_prim = new EggPolygon;
00375   }
00376 
00377   // Collect the vertices for this primitive.
00378   pvector< PT_EggVertex > vertices;
00379 
00380   const FltVertexList *vlist = (FltVertexList *)NULL;
00381   int num_children = flt_face->get_num_children();
00382   for (int i = 0; i < num_children && vlist == (FltVertexList *)NULL; i++) {
00383     const FltRecord *child = flt_face->get_child(i);
00384     if (child->is_of_type(FltVertexList::get_class_type())) {
00385       vlist = DCAST(FltVertexList, child);
00386     }
00387   }
00388 
00389   if (vlist != (FltVertexList *)NULL) {
00390     int num_vertices = vlist->get_num_vertices();
00391     for (int i = 0; i < num_vertices; i++) {
00392       FltVertex *flt_vertex = vlist->get_vertex(i);
00393       vertices.push_back(make_egg_vertex(flt_vertex));
00394     }
00395   }
00396 
00397   setup_geometry(flt_face, state, egg_prim, _main_egg_vpool, vertices);
00398 }
00399 
00400 ////////////////////////////////////////////////////////////////////
00401 //     Function: FltToEggConverter::convert_ext_ref
00402 //       Access: Private
00403 //  Description: Converts the external reference node.
00404 ////////////////////////////////////////////////////////////////////
00405 void FltToEggConverter::
00406 convert_ext_ref(const FltExternalReference *flt_ext, FltToEggLevelState &state) {
00407   // Get a group node to put the reference into.
00408   EggGroupNode *egg_parent =
00409     state.get_synthetic_group("", flt_ext);
00410 
00411   handle_external_reference(egg_parent, flt_ext->get_ref_filename());
00412 }
00413 
00414 ////////////////////////////////////////////////////////////////////
00415 //     Function: FltToEggConverter::setup_geometry
00416 //       Access: Private
00417 //  Description: Applies the state indicated in the FltGeometry record
00418 //               to the indicated EggPrimitive and all of its
00419 //               indicated vertices, and then officially adds the
00420 //               vertices to the vertex pool and to the primitive, and
00421 //               adds the primitive to its appropriate parent.
00422 ////////////////////////////////////////////////////////////////////
00423 void FltToEggConverter::
00424 setup_geometry(const FltGeometry *flt_geom, FltToEggLevelState &state,
00425                EggPrimitive *egg_prim, EggVertexPool *egg_vpool,
00426                const FltToEggConverter::EggVertices &vertices) {
00427 
00428   // Determine what the appropriate parent will be.
00429   EggGroupNode *egg_parent =
00430     state.get_synthetic_group(flt_geom->get_id(), flt_geom,
00431                               flt_geom->_billboard_type);
00432 
00433   // Create a new state to reflect the new parent.
00434   FltToEggLevelState next_state(state);
00435   next_state._egg_parent = egg_parent;
00436 
00437   // Check for decals onto the primitive.
00438   convert_subfaces(flt_geom, next_state);
00439 
00440   // Add the primitive to its new home.
00441   next_state._egg_parent->add_child(egg_prim);
00442 
00443   // Now examine the vertices.
00444   EggVertices::const_iterator vi;
00445 
00446   bool use_vertex_color = true;
00447   bool keep_normals = true;
00448   switch (flt_geom->_light_mode) {
00449   case FltGeometry::LM_face_no_normal:
00450     use_vertex_color = false;
00451     keep_normals = false;
00452     break;
00453 
00454   case FltGeometry::LM_vertex_no_normal:
00455     use_vertex_color = true;
00456     keep_normals = false;
00457     break;
00458 
00459   case FltGeometry::LM_face_with_normal:
00460     use_vertex_color = false;
00461     keep_normals = true;
00462     break;
00463 
00464   case FltGeometry::LM_vertex_with_normal:
00465     use_vertex_color = true;
00466     keep_normals = true;
00467     break;
00468   }
00469 
00470   Colorf face_color = flt_geom->get_color();
00471 
00472   if (state._flt_object != (FltObject *)NULL) {
00473     // If we have a FltObject above us, it might also specify a
00474     // transparency.  This combines with our existing transparency.
00475     float alpha = 1.0 - (state._flt_object->_transparency / 65535.0);
00476     face_color[3] *= alpha;
00477   }
00478 
00479   egg_prim->set_color(face_color);
00480 
00481   if (flt_geom->has_texture()) {
00482     // If the geometry has a texture, apply it.
00483     egg_prim->set_texture(make_egg_texture(flt_geom->get_texture()));
00484 
00485     if (flt_geom->_texwhite) {
00486       // If the geometry should be colored white under the texture,
00487       // then eliminate vertex colors.
00488       use_vertex_color = false;
00489     }
00490   }
00491 
00492   if (use_vertex_color) {
00493     // If we're to use vertex color instead of the face color, remove
00494     // the face color to eliminate any ambiguity.
00495     egg_prim->clear_color();
00496 
00497     // Also, make sure the transparency is set correctly across all
00498     // vertices.
00499     for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
00500       EggVertex *vertex = (*vi);
00501       if (vertex->has_color()) {
00502         Colorf vertex_color = vertex->get_color();
00503         vertex_color[3] = face_color[3];
00504         vertex->set_color(vertex_color);
00505       } else {
00506         if (flt_geom->has_color()) {
00507           // If a vertex doesn't have a color but the face does, set
00508           // the vertex to use the face color.
00509           vertex->set_color(face_color);
00510         }
00511       }
00512     }
00513 
00514   } else {
00515     // If we're to use face color instead of vertex color, remove the
00516     // vertex color to eliminate any ambiguity.
00517     for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
00518       (*vi)->clear_color();
00519     }
00520   }
00521 
00522   if (!keep_normals) {
00523     // If we're not to use the normals, then eliminate them.
00524     for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
00525       (*vi)->clear_normal();
00526     }
00527   }
00528 
00529   if (flt_geom->_draw_type == FltGeometry::DT_solid_no_backface) {
00530     // A double-sided polygon.
00531     egg_prim->set_bface_flag(true);
00532   }
00533 
00534   for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
00535     EggVertex *egg_vertex = egg_vpool->create_unique_vertex(*(*vi));
00536     egg_prim->add_vertex(egg_vertex);
00537   }
00538 
00539   parse_comment(flt_geom, egg_prim);
00540 }
00541 
00542 ////////////////////////////////////////////////////////////////////
00543 //     Function: FltToEggConverter::convert_subfaces
00544 //       Access: Public
00545 //  Description: Records all of the subfaces of the indicated group as
00546 //               coplanar polygons (i.e. decals) of the group.
00547 //
00548 //               If coplanar polygons exist, the state is modified so
00549 //               that _egg_parent is the new group to which the base
00550 //               polygons should be added.  Therefore, subfaces should
00551 //               be defined before the ordinary children are
00552 //               processed.
00553 ////////////////////////////////////////////////////////////////////
00554 void FltToEggConverter::
00555 convert_subfaces(const FltRecord *flt_record, FltToEggLevelState &state) {
00556   int num_subfaces = flt_record->get_num_subfaces();
00557   if (num_subfaces == 0) {
00558     // No subfaces.
00559     return;
00560   }
00561 
00562   // Create a new group to contain the base polygons.
00563   EggGroup *egg_group = new EggGroup("decal_base");
00564   state._egg_parent->add_child(egg_group);
00565   state._egg_parent = egg_group;
00566 
00567   egg_group->set_decal_flag(true);
00568 
00569   // Now create a nested group to hold the decals.
00570   EggGroup *decal_group = new EggGroup("decals");
00571   egg_group->add_child(decal_group);
00572   egg_group = decal_group;
00573 
00574   FltToEggLevelState next_state(state);
00575   next_state._egg_parent = decal_group;
00576 
00577   for (int i = 0; i < num_subfaces; i++) {
00578     const FltRecord *subface = flt_record->get_subface(i);
00579     dispatch_record(subface, next_state);
00580   }
00581 }
00582 
00583 ////////////////////////////////////////////////////////////////////
00584 //     Function: FltToEggConverter::parse_comment
00585 //       Access: Private
00586 //  Description: Scans the comment on this record for "<egg> { ... }"
00587 //               and parses the enclosed string as if it appeared in
00588 //               the egg file.  Returns true on success, false on
00589 //               syntax error (in which case _error is also set to
00590 //               true).
00591 ////////////////////////////////////////////////////////////////////
00592 bool FltToEggConverter::
00593 parse_comment(const FltBeadID *flt_bead, EggNode *egg_node) {
00594   return parse_comment(flt_bead->get_comment(), flt_bead->get_id(), egg_node);
00595 }
00596 
00597 ////////////////////////////////////////////////////////////////////
00598 //     Function: FltToEggConverter::parse_comment
00599 //       Access: Private
00600 //  Description: Scans the comment on this record for "<egg> { ... }"
00601 //               and parses the enclosed string as if it appeared in
00602 //               the egg file.  Returns true on success, false on
00603 //               syntax error (in which case _error is also set to
00604 //               true).
00605 ////////////////////////////////////////////////////////////////////
00606 bool FltToEggConverter::
00607 parse_comment(const FltBead *flt_bead, EggNode *egg_node) {
00608   return parse_comment(flt_bead->get_comment(), "anonymous", egg_node);
00609 }
00610 
00611 ////////////////////////////////////////////////////////////////////
00612 //     Function: FltToEggConverter::parse_comment
00613 //       Access: Private
00614 //  Description: Scans the comment on this record for "<egg> { ... }"
00615 //               and parses the enclosed string as if it appeared in
00616 //               the egg file.  Returns true on success, false on
00617 //               syntax error (in which case _error is also set to
00618 //               true).
00619 ////////////////////////////////////////////////////////////////////
00620 bool FltToEggConverter::
00621 parse_comment(const FltTexture *flt_texture, EggNode *egg_node) {
00622   return parse_comment(flt_texture->get_comment(), 
00623                flt_texture->get_texture_filename(), egg_node);
00624 }
00625 
00626 ////////////////////////////////////////////////////////////////////
00627 //     Function: FltToEggConverter::parse_comment
00628 //       Access: Private
00629 //  Description: Scans the comment on this record for "<egg> { ... }"
00630 //               and parses the enclosed string as if it appeared in
00631 //               the egg file.  Returns true on success, false on
00632 //               syntax error (in which case _error is also set to
00633 //               true).
00634 ////////////////////////////////////////////////////////////////////
00635 bool FltToEggConverter::
00636 parse_comment(const string &comment, const string &name,
00637               EggNode *egg_node) {
00638   if (comment.empty()) {
00639     // No comment.
00640     return true;
00641   }
00642 
00643   // Scan for <egg>.
00644   static const string egg_str = "<egg>";
00645 
00646   size_t p;
00647   p = 0;
00648   while (p < comment.length() &&
00649          cmp_nocase(comment.substr(p, 5), egg_str) != 0) {
00650     p++;
00651   }
00652 
00653   if (p >= comment.length()) {
00654     // No "<egg>" in the comment.
00655     return true;
00656   }
00657 
00658   p += 5;
00659   // Now scan past whitespace for the open curly brace.
00660   while (p < comment.length() && isspace(comment[p])) {
00661     ++p;
00662   }
00663   if (p >= comment.length() || comment[p] != '{') {
00664     nout << "No opening brace in comment for "
00665          << name << "\n\n";
00666     if (!_allow_errors) {
00667       _error = true;
00668     }
00669     return false;
00670   }
00671 
00672   // Here's the beginning of the string after "<egg> {".  Now lop off
00673   // the closing brace at the end.
00674   ++p;
00675   size_t q = comment.length() - 1;
00676   while (q > p && comment[q] != '}') {
00677     --q;
00678   }
00679   if (q == p) {
00680     nout << "No closing brace in comment for "
00681          << name << "\n\n";
00682     if (!_allow_errors) {
00683       _error = true;
00684     }
00685     return false;
00686   }
00687 
00688   string egg_syntax = comment.substr(p, q - p);
00689 
00690   if (!egg_node->parse_egg(egg_syntax)) {
00691     nout << "Syntax error in comment for "
00692          << name << "\n\n";
00693     if (!_allow_errors) {
00694       _error = true;
00695     }
00696     return false;
00697   }
00698 
00699   // Correctly parsed!
00700   return true;
00701 }
00702 
00703 ////////////////////////////////////////////////////////////////////
00704 //     Function: FltToEggConverter::make_egg_vertex
00705 //       Access: Private
00706 //  Description: Makes a new EggVertex for the indicated FltVertex.
00707 //               The vertex is not automatically added to the vertex
00708 //               pool.
00709 ////////////////////////////////////////////////////////////////////
00710 PT_EggVertex FltToEggConverter::
00711 make_egg_vertex(const FltVertex *flt_vertex) {
00712   PT_EggVertex egg_vertex = new EggVertex;
00713   egg_vertex->set_pos(flt_vertex->_pos);
00714 
00715   if (flt_vertex->_has_normal) {
00716     egg_vertex->set_normal(LCAST(double, flt_vertex->_normal));
00717   }
00718 
00719   if (flt_vertex->_has_uv) {
00720     egg_vertex->set_uv(LCAST(double, flt_vertex->_uv));
00721   }
00722 
00723   if (flt_vertex->has_color()) {
00724     egg_vertex->set_color(flt_vertex->get_color());
00725   }
00726 
00727   return egg_vertex;
00728 }
00729 
00730 ////////////////////////////////////////////////////////////////////
00731 //     Function: FltToEggConverter::make_egg_texture
00732 //       Access: Private
00733 //  Description: Makes a new EggTexture for the indicated FltTexture,
00734 //               or returns a pointer to one previously made for the
00735 //               same FltTexture.
00736 ////////////////////////////////////////////////////////////////////
00737 PT_EggTexture FltToEggConverter::
00738 make_egg_texture(const FltTexture *flt_texture) {
00739   Textures::const_iterator ti;
00740   ti = _textures.find(flt_texture);
00741   if (ti != _textures.end()) {
00742     // There's one previously created.
00743     return (*ti).second;
00744   }
00745 
00746   // Create a new one.
00747   string tref_name = format_string(flt_texture->_pattern_index);
00748   Filename filename = flt_texture->get_texture_filename();
00749 
00750   PT_EggTexture egg_texture = new EggTexture(tref_name, filename);
00751 
00752   _textures.insert(Textures::value_type(flt_texture, egg_texture));
00753 
00754   // Set up the texture properties.
00755 
00756   switch (flt_texture->_min_filter) {
00757   case FltTexture::MN_point:
00758     egg_texture->set_minfilter(EggTexture::FT_nearest);
00759     break;
00760 
00761   case FltTexture::MN_bilinear:
00762     egg_texture->set_minfilter(EggTexture::FT_linear);
00763     break;
00764 
00765   case FltTexture::MN_mipmap_point:
00766     egg_texture->set_minfilter(EggTexture::FT_nearest_mipmap_nearest);
00767     break;
00768 
00769   case FltTexture::MN_mipmap_linear:
00770     egg_texture->set_minfilter(EggTexture::FT_nearest_mipmap_linear);
00771     break;
00772 
00773   case FltTexture::MN_mipmap_bilinear:
00774     egg_texture->set_minfilter(EggTexture::FT_linear_mipmap_nearest);
00775     break;
00776 
00777   case FltTexture::MN_mipmap_trilinear:
00778   case FltTexture::MN_OB_mipmap:
00779     egg_texture->set_minfilter(EggTexture::FT_linear_mipmap_linear);
00780     break;
00781 
00782   case FltTexture::MN_bicubic:
00783   case FltTexture::MN_bilinear_gequal:
00784   case FltTexture::MN_bilinear_lequal:
00785   case FltTexture::MN_bicubic_gequal:
00786   case FltTexture::MN_bicubic_lequal:
00787     // Not supported.
00788     break;
00789   }
00790 
00791   switch (flt_texture->_mag_filter) {
00792   case FltTexture::MG_point:
00793     egg_texture->set_magfilter(EggTexture::FT_nearest);
00794     break;
00795 
00796   case FltTexture::MG_bilinear:
00797     egg_texture->set_magfilter(EggTexture::FT_linear);
00798     break;
00799 
00800   case FltTexture::MG_bicubic:
00801   case FltTexture::MG_sharpen:
00802   case FltTexture::MG_add_detail:
00803   case FltTexture::MG_modulate_detail:
00804   case FltTexture::MG_bilinear_gequal:
00805   case FltTexture::MG_bilinear_lequal:
00806   case FltTexture::MG_bicubic_gequal:
00807   case FltTexture::MG_bicubic_lequal:
00808     // Not supported.
00809     break;
00810   }
00811 
00812   switch (flt_texture->_repeat) {
00813   case FltTexture::RT_repeat:
00814     egg_texture->set_wrap_mode(EggTexture::WM_repeat);
00815     break;
00816 
00817   case FltTexture::RT_clamp:
00818     egg_texture->set_wrap_mode(EggTexture::WM_clamp);
00819     break;
00820   }
00821 
00822   switch (flt_texture->_repeat_u) {
00823   case FltTexture::RT_repeat:
00824     egg_texture->set_wrap_u(EggTexture::WM_repeat);
00825     break;
00826 
00827   case FltTexture::RT_clamp:
00828     egg_texture->set_wrap_u(EggTexture::WM_clamp);
00829     break;
00830   }
00831 
00832   switch (flt_texture->_repeat_v) {
00833   case FltTexture::RT_repeat:
00834     egg_texture->set_wrap_v(EggTexture::WM_repeat);
00835     break;
00836 
00837   case FltTexture::RT_clamp:
00838     egg_texture->set_wrap_v(EggTexture::WM_clamp);
00839     break;
00840   }
00841 
00842   switch (flt_texture->_env_type) {
00843   case FltTexture::ET_modulate:
00844     egg_texture->set_env_type(EggTexture::ET_modulate);
00845     break;
00846 
00847   case FltTexture::ET_decal:
00848     egg_texture->set_env_type(EggTexture::ET_decal);
00849     break;
00850 
00851   case FltTexture::ET_blend:
00852   case FltTexture::ET_color:
00853     // Not supported.
00854     break;
00855   }
00856 
00857   switch (flt_texture->_internal_format) {
00858   case FltTexture::IF_default:
00859     break;
00860 
00861   case FltTexture::IF_i_12a_4:
00862   case FltTexture::IF_ia_12:
00863   case FltTexture::IF_ia_8:
00864     egg_texture->set_format(EggTexture::F_luminance_alpha);
00865     break;
00866 
00867   case FltTexture::IF_rgb_5:
00868     egg_texture->set_format(EggTexture::F_rgb5);
00869     break;
00870 
00871   case FltTexture::IF_rgba_4:
00872     egg_texture->set_format(EggTexture::F_rgba4);
00873     break;
00874 
00875 
00876   case FltTexture::IF_rgba_8:
00877     egg_texture->set_format(EggTexture::F_rgba8);
00878     break;
00879 
00880   case FltTexture::IF_rgba_12:
00881     egg_texture->set_format(EggTexture::F_rgba12);
00882     break;
00883 
00884   case FltTexture::IF_i_16:
00885     if (flt_texture->_intensity_is_alpha) {
00886       egg_texture->set_format(EggTexture::F_alpha);
00887     } else {
00888       egg_texture->set_format(EggTexture::F_luminance);
00889     }
00890     break;
00891 
00892   case FltTexture::IF_rgb_12:
00893     egg_texture->set_format(EggTexture::F_rgb12);
00894     break;
00895   }
00896 
00897   parse_comment(flt_texture, egg_texture);
00898   return egg_texture;
00899 }

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