00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
00046
00047
00048
00049 FltToEggConverter::
00050 FltToEggConverter() {
00051 _compose_transforms = false;
00052 }
00053
00054
00055
00056
00057
00058
00059 FltToEggConverter::
00060 FltToEggConverter(const FltToEggConverter ©) :
00061 SomethingToEggConverter(copy),
00062 _compose_transforms(copy._compose_transforms)
00063 {
00064 }
00065
00066
00067
00068
00069
00070
00071 FltToEggConverter::
00072 ~FltToEggConverter() {
00073 cleanup();
00074 }
00075
00076
00077
00078
00079
00080
00081 SomethingToEggConverter *FltToEggConverter::
00082 make_copy() {
00083 return new FltToEggConverter(*this);
00084 }
00085
00086
00087
00088
00089
00090
00091
00092
00093 string FltToEggConverter::
00094 get_name() const {
00095 return "MultiGen";
00096 }
00097
00098
00099
00100
00101
00102
00103
00104 string FltToEggConverter::
00105 get_extension() const {
00106 return "flt";
00107 }
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
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
00138
00139
00140
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
00152 _main_egg_vpool = new EggVertexPool("vpool");
00153 _egg_data->add_child(_main_egg_vpool.p());
00154
00155
00156
00157
00158
00159
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
00167
00168 _egg_data->remove_child(_main_egg_vpool.p());
00169 }
00170
00171 cleanup();
00172
00173 return !_error;
00174 }
00175
00176
00177
00178
00179
00180
00181
00182
00183 void FltToEggConverter::
00184 cleanup() {
00185 _flt_header.clear();
00186 _main_egg_vpool.clear();
00187 _textures.clear();
00188 }
00189
00190
00191
00192
00193
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
00207
00208
00209
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
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
00242
00243
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
00266
00267
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
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
00284
00285 FltToEggLevelState next_state(state);
00286 next_state._egg_parent = egg_group;
00287 convert_record(flt_group, next_state);
00288 }
00289
00290
00291
00292
00293
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
00311
00312
00313
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
00332
00333
00334
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
00353
00354
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
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
00402
00403
00404
00405 void FltToEggConverter::
00406 convert_ext_ref(const FltExternalReference *flt_ext, FltToEggLevelState &state) {
00407
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
00416
00417
00418
00419
00420
00421
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
00429 EggGroupNode *egg_parent =
00430 state.get_synthetic_group(flt_geom->get_id(), flt_geom,
00431 flt_geom->_billboard_type);
00432
00433
00434 FltToEggLevelState next_state(state);
00435 next_state._egg_parent = egg_parent;
00436
00437
00438 convert_subfaces(flt_geom, next_state);
00439
00440
00441 next_state._egg_parent->add_child(egg_prim);
00442
00443
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
00474
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
00483 egg_prim->set_texture(make_egg_texture(flt_geom->get_texture()));
00484
00485 if (flt_geom->_texwhite) {
00486
00487
00488 use_vertex_color = false;
00489 }
00490 }
00491
00492 if (use_vertex_color) {
00493
00494
00495 egg_prim->clear_color();
00496
00497
00498
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
00508
00509 vertex->set_color(face_color);
00510 }
00511 }
00512 }
00513
00514 } else {
00515
00516
00517 for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
00518 (*vi)->clear_color();
00519 }
00520 }
00521
00522 if (!keep_normals) {
00523
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
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
00544
00545
00546
00547
00548
00549
00550
00551
00552
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
00559 return;
00560 }
00561
00562
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
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
00585
00586
00587
00588
00589
00590
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
00599
00600
00601
00602
00603
00604
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
00613
00614
00615
00616
00617
00618
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
00628
00629
00630
00631
00632
00633
00634
00635 bool FltToEggConverter::
00636 parse_comment(const string &comment, const string &name,
00637 EggNode *egg_node) {
00638 if (comment.empty()) {
00639
00640 return true;
00641 }
00642
00643
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
00655 return true;
00656 }
00657
00658 p += 5;
00659
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
00673
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
00700 return true;
00701 }
00702
00703
00704
00705
00706
00707
00708
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
00732
00733
00734
00735
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
00743 return (*ti).second;
00744 }
00745
00746
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
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
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
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
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 }