00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "xFileToEggConverter.h"
00020 #include "xFileMesh.h"
00021 #include "xFileMaterial.h"
00022 #include "xFileTemplates.h"
00023 #include "config_xfile.h"
00024
00025 #include "eggData.h"
00026 #include "eggGroup.h"
00027 #include "datagram.h"
00028 #include "eggMaterialCollection.h"
00029 #include "eggTextureCollection.h"
00030 #include "dcast.h"
00031
00032
00033
00034
00035
00036
00037 XFileToEggConverter::
00038 XFileToEggConverter() {
00039 _dx_file = NULL;
00040 _dx_file_enum = NULL;
00041 }
00042
00043
00044
00045
00046
00047
00048 XFileToEggConverter::
00049 XFileToEggConverter(const XFileToEggConverter ©) :
00050 SomethingToEggConverter(copy)
00051 {
00052 _dx_file = NULL;
00053 _dx_file_enum = NULL;
00054 }
00055
00056
00057
00058
00059
00060
00061 XFileToEggConverter::
00062 ~XFileToEggConverter() {
00063 close();
00064 }
00065
00066
00067
00068
00069
00070
00071 SomethingToEggConverter *XFileToEggConverter::
00072 make_copy() {
00073 return new XFileToEggConverter(*this);
00074 }
00075
00076
00077
00078
00079
00080
00081
00082
00083 string XFileToEggConverter::
00084 get_name() const {
00085 return "DirectX";
00086 }
00087
00088
00089
00090
00091
00092
00093
00094 string XFileToEggConverter::
00095 get_extension() const {
00096 return "x";
00097 }
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 bool XFileToEggConverter::
00112 convert_file(const Filename &filename) {
00113 HRESULT hr;
00114
00115 close();
00116 hr = DirectXFileCreate(&_dx_file);
00117 if (hr != DXFILE_OK) {
00118 nout << "Unable to create X interface.\n";
00119 return false;
00120 }
00121
00122
00123 hr = _dx_file->RegisterTemplates(D3DRM_XTEMPLATES, d3drm_xtemplates_length);
00124 if (hr != DXFILE_OK) {
00125 nout << "Unable to register templates.\n";
00126 return false;
00127 }
00128
00129 string os_file = filename.to_os_specific();
00130 hr = _dx_file->CreateEnumObject
00131 ((void *)os_file.c_str(), DXFILELOAD_FROMFILE, &_dx_file_enum);
00132 if (hr != DXFILE_OK) {
00133 nout << "Unable to open X file: " << os_file << "\n";
00134 return false;
00135 }
00136
00137 if (_egg_data->get_coordinate_system() == CS_default) {
00138 _egg_data->set_coordinate_system(CS_yup_left);
00139 }
00140
00141 return get_toplevel();
00142 }
00143
00144
00145
00146
00147
00148
00149
00150 void XFileToEggConverter::
00151 close() {
00152 if (_dx_file != NULL) {
00153 if (_dx_file_enum != NULL) {
00154 _dx_file_enum->Release();
00155 _dx_file_enum = NULL;
00156 }
00157 _dx_file->Release();
00158 _dx_file = NULL;
00159 }
00160 }
00161
00162
00163
00164
00165
00166
00167
00168
00169 EggTexture *XFileToEggConverter::
00170 create_unique_texture(const EggTexture ©) {
00171 return _textures.create_unique_texture(copy, ~EggTexture::E_tref_name);
00172 }
00173
00174
00175
00176
00177
00178
00179
00180
00181 EggMaterial *XFileToEggConverter::
00182 create_unique_material(const EggMaterial ©) {
00183 return _materials.create_unique_material(copy, ~EggMaterial::E_mref_name);
00184 }
00185
00186
00187
00188
00189
00190
00191
00192
00193 bool XFileToEggConverter::
00194 get_toplevel() {
00195 HRESULT hr;
00196 LPDIRECTXFILEDATA obj;
00197
00198 hr = _dx_file_enum->GetNextDataObject(&obj);
00199 while (hr == DXFILE_OK) {
00200 if (!convert_data_object(obj, _egg_data)) {
00201 return false;
00202 }
00203 hr = _dx_file_enum->GetNextDataObject(&obj);
00204 }
00205
00206 if (hr != DXFILEERR_NOMOREOBJECTS) {
00207 xfile_cat.error()
00208 << "Error extracting top-level objects.\n";
00209 return false;
00210 }
00211
00212 return true;
00213 }
00214
00215
00216
00217
00218
00219
00220
00221 bool XFileToEggConverter::
00222 convert_object(LPDIRECTXFILEOBJECT obj, EggGroupNode *egg_parent) {
00223 HRESULT hr;
00224 LPDIRECTXFILEDATA data_obj;
00225
00226
00227 hr = obj->QueryInterface(IID_IDirectXFileData, (void **)&data_obj);
00228 if (hr == DD_OK) {
00229
00230 return convert_data_object(data_obj, egg_parent);
00231 }
00232
00233
00234 xfile_cat.error()
00235 << "Ignoring object of unknown type: " << get_object_name(obj)
00236 << "\n";
00237 return true;
00238 }
00239
00240
00241
00242
00243
00244
00245
00246
00247 bool XFileToEggConverter::
00248 convert_data_object(LPDIRECTXFILEDATA obj, EggGroupNode *egg_parent) {
00249 HRESULT hr;
00250
00251
00252 const GUID *type;
00253 hr = obj->GetType(&type);
00254 if (hr != DXFILE_OK) {
00255 xfile_cat.error()
00256 << "Unable to get type of template\n";
00257 return false;
00258 }
00259
00260 if (*type == mydef_TID_D3DRMHeader) {
00261
00262
00263 } else if (*type == TID_D3DRMFrame) {
00264 if (!convert_frame(obj, egg_parent)) {
00265 return false;
00266 }
00267
00268 } else if (*type == TID_D3DRMFrameTransformMatrix) {
00269 if (!convert_transform(obj, egg_parent)) {
00270 return false;
00271 }
00272
00273 } else if (*type == TID_D3DRMMesh) {
00274 if (!convert_mesh(obj, egg_parent)) {
00275 return false;
00276 }
00277
00278 } else {
00279 xfile_cat.error()
00280 << "Ignoring data object of unknown type: " << get_object_name(obj)
00281 << "\n";
00282 }
00283
00284 return true;
00285 }
00286
00287
00288
00289
00290
00291
00292
00293 bool XFileToEggConverter::
00294 convert_frame(LPDIRECTXFILEDATA obj, EggGroupNode *egg_parent) {
00295 HRESULT hr;
00296
00297 string name = get_object_name(obj);
00298 EggGroup *group = new EggGroup(name);
00299 egg_parent->add_child(group);
00300
00301
00302 LPDIRECTXFILEOBJECT child_obj;
00303
00304 hr = obj->GetNextObject(&child_obj);
00305 while (hr == DXFILE_OK) {
00306 if (!convert_object(child_obj, group)) {
00307 return false;
00308 }
00309 hr = obj->GetNextObject(&child_obj);
00310 }
00311
00312 if (hr != DXFILEERR_NOMOREOBJECTS) {
00313 xfile_cat.error()
00314 << "Error extracting children of frame " << name << ".\n";
00315 return false;
00316 }
00317
00318 return true;
00319 }
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330 bool XFileToEggConverter::
00331 convert_transform(LPDIRECTXFILEDATA obj, EggGroupNode *egg_parent) {
00332 Datagram raw_data;
00333 if (!get_data(obj, raw_data)) {
00334 return false;
00335 }
00336
00337 DatagramIterator di(raw_data);
00338 LMatrix4f mat;
00339 mat.read_datagram(di);
00340
00341 if (egg_parent->is_of_type(EggGroup::get_class_type())) {
00342 EggGroup *egg_group = DCAST(EggGroup, egg_parent);
00343 egg_group->set_transform(LCAST(double, mat));
00344 egg_group->set_group_type(EggGroup::GT_instance);
00345 } else {
00346 xfile_cat.error()
00347 << "Transform " << get_object_name(obj)
00348 << " encountered without frame!\n";
00349 }
00350
00351 return true;
00352 }
00353
00354
00355
00356
00357
00358
00359
00360 bool XFileToEggConverter::
00361 convert_mesh(LPDIRECTXFILEDATA obj, EggGroupNode *egg_parent) {
00362 HRESULT hr;
00363
00364 Datagram raw_data;
00365 if (!get_data(obj, raw_data)) {
00366 return false;
00367 }
00368
00369 XFileMesh mesh;
00370 mesh.set_name(get_object_name(obj));
00371 if (!mesh.read_mesh_data(raw_data)) {
00372 return false;
00373 }
00374
00375
00376 LPDIRECTXFILEOBJECT child_obj;
00377
00378 hr = obj->GetNextObject(&child_obj);
00379 while (hr == DXFILE_OK) {
00380 if (!convert_mesh_object(child_obj, mesh)) {
00381 return false;
00382 }
00383 hr = obj->GetNextObject(&child_obj);
00384 }
00385
00386 if (hr != DXFILEERR_NOMOREOBJECTS) {
00387 xfile_cat.error()
00388 << "Error extracting children of mesh " << get_object_name(obj)
00389 << ".\n";
00390 return false;
00391 }
00392
00393 if (!mesh.create_polygons(egg_parent, this)) {
00394 return false;
00395 }
00396
00397 return true;
00398 }
00399
00400
00401
00402
00403
00404
00405
00406 bool XFileToEggConverter::
00407 convert_mesh_object(LPDIRECTXFILEOBJECT obj, XFileMesh &mesh) {
00408 HRESULT hr;
00409 LPDIRECTXFILEDATA data_obj;
00410
00411
00412 hr = obj->QueryInterface(IID_IDirectXFileData, (void **)&data_obj);
00413 if (hr == DD_OK) {
00414
00415 return convert_mesh_data_object(data_obj, mesh);
00416 }
00417
00418
00419 xfile_cat.error()
00420 << "Ignoring object of unknown type: " << get_object_name(obj)
00421 << "\n";
00422 return true;
00423 }
00424
00425
00426
00427
00428
00429
00430
00431 bool XFileToEggConverter::
00432 convert_mesh_data_object(LPDIRECTXFILEDATA obj, XFileMesh &mesh) {
00433 HRESULT hr;
00434
00435
00436 const GUID *type;
00437 hr = obj->GetType(&type);
00438 if (hr != DXFILE_OK) {
00439 xfile_cat.error()
00440 << "Unable to get type of template\n";
00441 return false;
00442 }
00443
00444 if (*type == TID_D3DRMMeshNormals) {
00445 if (!convert_mesh_normals(obj, mesh)) {
00446 return false;
00447 }
00448
00449 } else if (*type == TID_D3DRMMeshVertexColors) {
00450 if (!convert_mesh_colors(obj, mesh)) {
00451 return false;
00452 }
00453
00454 } else if (*type == TID_D3DRMMeshTextureCoords) {
00455 if (!convert_mesh_uvs(obj, mesh)) {
00456 return false;
00457 }
00458
00459 } else if (*type == TID_D3DRMMeshMaterialList) {
00460 if (!convert_mesh_material_list(obj, mesh)) {
00461 return false;
00462 }
00463
00464 } else {
00465 xfile_cat.error()
00466 << "Ignoring data object of unknown type: " << get_object_name(obj)
00467 << "\n";
00468 }
00469
00470 return true;
00471 }
00472
00473
00474
00475
00476
00477
00478
00479 bool XFileToEggConverter::
00480 convert_mesh_normals(LPDIRECTXFILEDATA obj, XFileMesh &mesh) {
00481 Datagram raw_data;
00482 if (!get_data(obj, raw_data)) {
00483 return false;
00484 }
00485
00486 if (!mesh.read_normal_data(raw_data)) {
00487 return false;
00488 }
00489
00490 return true;
00491 }
00492
00493
00494
00495
00496
00497
00498
00499 bool XFileToEggConverter::
00500 convert_mesh_colors(LPDIRECTXFILEDATA obj, XFileMesh &mesh) {
00501 Datagram raw_data;
00502 if (!get_data(obj, raw_data)) {
00503 return false;
00504 }
00505
00506 if (!mesh.read_color_data(raw_data)) {
00507 return false;
00508 }
00509
00510 return true;
00511 }
00512
00513
00514
00515
00516
00517
00518
00519 bool XFileToEggConverter::
00520 convert_mesh_uvs(LPDIRECTXFILEDATA obj, XFileMesh &mesh) {
00521 Datagram raw_data;
00522 if (!get_data(obj, raw_data)) {
00523 return false;
00524 }
00525
00526 if (!mesh.read_uv_data(raw_data)) {
00527 return false;
00528 }
00529
00530 return true;
00531 }
00532
00533
00534
00535
00536
00537
00538
00539 bool XFileToEggConverter::
00540 convert_mesh_material_list(LPDIRECTXFILEDATA obj, XFileMesh &mesh) {
00541 HRESULT hr;
00542
00543 Datagram raw_data;
00544 if (!get_data(obj, raw_data)) {
00545 return false;
00546 }
00547
00548 if (!mesh.read_material_list_data(raw_data)) {
00549 return false;
00550 }
00551
00552
00553
00554 LPDIRECTXFILEOBJECT child_obj;
00555
00556 hr = obj->GetNextObject(&child_obj);
00557 while (hr == DXFILE_OK) {
00558 if (!convert_material_list_object(child_obj, mesh)) {
00559 return false;
00560 }
00561 hr = obj->GetNextObject(&child_obj);
00562 }
00563
00564 if (hr != DXFILEERR_NOMOREOBJECTS) {
00565 xfile_cat.error()
00566 << "Error extracting children of MeshMaterialList "
00567 << get_object_name(obj) << ".\n";
00568 return false;
00569 }
00570
00571 return true;
00572 }
00573
00574
00575
00576
00577
00578
00579
00580 bool XFileToEggConverter::
00581 convert_material_list_object(LPDIRECTXFILEOBJECT obj, XFileMesh &mesh) {
00582 HRESULT hr;
00583 LPDIRECTXFILEDATA data_obj;
00584
00585
00586 hr = obj->QueryInterface(IID_IDirectXFileData, (void **)&data_obj);
00587 if (hr == DD_OK) {
00588
00589 return convert_material_list_data_object(data_obj, mesh);
00590 }
00591
00592
00593 xfile_cat.error()
00594 << "Ignoring object of unknown type: " << get_object_name(obj)
00595 << "\n";
00596 return true;
00597 }
00598
00599
00600
00601
00602
00603
00604
00605 bool XFileToEggConverter::
00606 convert_material_list_data_object(LPDIRECTXFILEDATA obj, XFileMesh &mesh) {
00607 HRESULT hr;
00608
00609
00610 const GUID *type;
00611 hr = obj->GetType(&type);
00612 if (hr != DXFILE_OK) {
00613 xfile_cat.error()
00614 << "Unable to get type of template\n";
00615 return false;
00616 }
00617
00618 if (*type == TID_D3DRMMaterial) {
00619 if (!convert_material(obj, mesh)) {
00620 return false;
00621 }
00622 } else {
00623 xfile_cat.error()
00624 << "Ignoring data object of unknown type: " << get_object_name(obj)
00625 << "\n";
00626 }
00627
00628 return true;
00629 }
00630
00631
00632
00633
00634
00635
00636 bool XFileToEggConverter::
00637 convert_material(LPDIRECTXFILEDATA obj, XFileMesh &mesh) {
00638 HRESULT hr;
00639
00640 Datagram raw_data;
00641 if (!get_data(obj, raw_data)) {
00642 return false;
00643 }
00644
00645 XFileMaterial *material = new XFileMaterial;
00646
00647 if (!material->read_material_data(raw_data)) {
00648 delete material;
00649 return false;
00650 }
00651
00652 mesh.add_material(material);
00653
00654
00655
00656 LPDIRECTXFILEOBJECT child_obj;
00657
00658 hr = obj->GetNextObject(&child_obj);
00659 while (hr == DXFILE_OK) {
00660 if (!convert_material_object(child_obj, *material)) {
00661 return false;
00662 }
00663 hr = obj->GetNextObject(&child_obj);
00664 }
00665
00666 if (hr != DXFILEERR_NOMOREOBJECTS) {
00667 xfile_cat.error()
00668 << "Error extracting children of Material "
00669 << get_object_name(obj) << ".\n";
00670 return false;
00671 }
00672
00673 return true;
00674 }
00675
00676
00677
00678
00679
00680
00681
00682 bool XFileToEggConverter::
00683 convert_material_object(LPDIRECTXFILEOBJECT obj, XFileMaterial &material) {
00684 HRESULT hr;
00685 LPDIRECTXFILEDATA data_obj;
00686
00687
00688 hr = obj->QueryInterface(IID_IDirectXFileData, (void **)&data_obj);
00689 if (hr == DD_OK) {
00690
00691 return convert_material_data_object(data_obj, material);
00692 }
00693
00694
00695 xfile_cat.error()
00696 << "Ignoring object of unknown type: " << get_object_name(obj)
00697 << "\n";
00698 return true;
00699 }
00700
00701
00702
00703
00704
00705
00706
00707 bool XFileToEggConverter::
00708 convert_material_data_object(LPDIRECTXFILEDATA obj, XFileMaterial &material) {
00709 HRESULT hr;
00710
00711
00712 const GUID *type;
00713 hr = obj->GetType(&type);
00714 if (hr != DXFILE_OK) {
00715 xfile_cat.error()
00716 << "Unable to get type of template\n";
00717 return false;
00718 }
00719
00720 if (*type == TID_D3DRMTextureFilename) {
00721 if (!convert_texture(obj, material)) {
00722 return false;
00723 }
00724 } else {
00725 xfile_cat.error()
00726 << "Ignoring data object of unknown type: " << get_object_name(obj)
00727 << "\n";
00728 }
00729
00730 return true;
00731 }
00732
00733
00734
00735
00736
00737
00738 bool XFileToEggConverter::
00739 convert_texture(LPDIRECTXFILEDATA obj, XFileMaterial &material) {
00740 Datagram raw_data;
00741 if (!get_data(obj, raw_data)) {
00742 return false;
00743 }
00744
00745 if (!material.read_texture_data(raw_data)) {
00746 return false;
00747 }
00748
00749 return true;
00750 }
00751
00752
00753
00754
00755
00756
00757 string XFileToEggConverter::
00758 get_object_name(LPDIRECTXFILEOBJECT obj) {
00759 HRESULT hr;
00760
00761 DWORD length = 0;
00762 obj->GetName(NULL, &length);
00763
00764 if (length == 0) {
00765 return string();
00766 }
00767
00768 char *buffer = new char[length];
00769 hr = obj->GetName(buffer, &length);
00770
00771 string result;
00772 if (hr != DXFILE_OK) {
00773 xfile_cat.error()
00774 << "Unable to get object name.\n";
00775 } else {
00776 result = buffer;
00777 }
00778
00779 delete[] buffer;
00780 return result;
00781 }
00782
00783
00784
00785
00786
00787
00788 bool XFileToEggConverter::
00789 get_data(LPDIRECTXFILEDATA obj, Datagram &raw_data) {
00790 HRESULT hr;
00791 DWORD length;
00792 void *data;
00793 hr = obj->GetData(NULL, &length, &data);
00794 if (hr != DXFILE_OK) {
00795 xfile_cat.error()
00796 << "Unable to get data for " << get_object_name(obj) << "\n";
00797 return false;
00798 }
00799
00800 raw_data.clear();
00801 raw_data.append_data(data, length);
00802
00803 return true;
00804 }