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