00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "xFileMaker.h"
00020 #include "xFileMesh.h"
00021 #include "xFileMaterial.h"
00022 #include "xFileTemplates.h"
00023 #include "config_xfile.h"
00024
00025 #include "notify.h"
00026 #include "eggGroupNode.h"
00027 #include "eggGroup.h"
00028 #include "eggBin.h"
00029 #include "eggPolysetMaker.h"
00030 #include "eggVertexPool.h"
00031 #include "eggVertex.h"
00032 #include "eggPolygon.h"
00033 #include "eggData.h"
00034 #include "pvector.h"
00035 #include "vector_int.h"
00036 #include "string_utils.h"
00037 #include "datagram.h"
00038
00039
00040
00041
00042
00043
00044 XFileMaker::
00045 XFileMaker() {
00046 _dx_file = NULL;
00047 _dx_file_save = NULL;
00048 _mesh_index = 0;
00049 }
00050
00051
00052
00053
00054
00055
00056 XFileMaker::
00057 ~XFileMaker() {
00058 close();
00059 }
00060
00061
00062
00063
00064
00065
00066
00067
00068 bool XFileMaker::
00069 open(const Filename &filename) {
00070 HRESULT hr;
00071
00072 close();
00073 hr = DirectXFileCreate(&_dx_file);
00074 if (hr != DXFILE_OK) {
00075 nout << "Unable to create X interface.\n";
00076 return false;
00077 }
00078
00079
00080 hr = _dx_file->RegisterTemplates(D3DRM_XTEMPLATES, d3drm_xtemplates_length);
00081 if (hr != DXFILE_OK) {
00082 nout << "Unable to register templates.\n";
00083 return false;
00084 }
00085
00086 string os_file = filename.to_os_specific();
00087 hr = _dx_file->CreateSaveObject(os_file.c_str(), DXFILEFORMAT_TEXT,
00088 &_dx_file_save);
00089 if (hr != DXFILE_OK) {
00090 nout << "Unable to open X file: " << os_file << "\n";
00091 return false;
00092 }
00093
00094
00095 static const GUID *temps[] = {
00096 &mydef_TID_D3DRMHeader,
00097 &TID_D3DRMCoords2d,
00098 &TID_D3DRMVector,
00099 &TID_D3DRMColorRGBA,
00100 &TID_D3DRMColorRGB,
00101 &TID_D3DRMIndexedColor,
00102 &TID_D3DRMTextureFilename,
00103 &TID_D3DRMMatrix4x4,
00104 &TID_D3DRMMaterial,
00105 &TID_D3DRMMeshFace,
00106 &TID_D3DRMMesh,
00107 &TID_D3DRMMeshNormals,
00108 &TID_D3DRMMeshTextureCoords,
00109 &TID_D3DRMMeshMaterialList,
00110 &TID_D3DRMFrameTransformMatrix,
00111 &TID_D3DRMFrame,
00112 };
00113 static const int num_temps = sizeof(temps) / sizeof(temps[0]);
00114 hr = _dx_file_save->SaveTemplates(num_temps, temps);
00115 if (hr != DXFILE_OK) {
00116 nout << "Unable to save templates.\n";
00117 return false;
00118 }
00119
00120 return true;
00121 }
00122
00123
00124
00125
00126
00127
00128
00129 void XFileMaker::
00130 close() {
00131 if (_dx_file != NULL) {
00132 if (_dx_file_save != NULL) {
00133 _dx_file_save->Release();
00134 _dx_file_save = NULL;
00135 }
00136 _dx_file->Release();
00137 _dx_file = NULL;
00138 }
00139 }
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 bool XFileMaker::
00150 add_tree(EggData &egg_data) {
00151 _meshes.clear();
00152
00153
00154 EggPolysetMaker pmaker;
00155 int num_bins = pmaker.make_bins(&egg_data);
00156
00157
00158 if (!recurse_nodes(&egg_data, NULL)) {
00159 return false;
00160 }
00161
00162
00163 if (!finalize_mesh(NULL)) {
00164 return false;
00165 }
00166
00167 nassertr(_meshes.empty(), false);
00168 return true;
00169 }
00170
00171
00172
00173
00174
00175
00176
00177 bool XFileMaker::
00178 add_node(EggNode *egg_node, LPDIRECTXFILEDATA dx_parent) {
00179 if (egg_node->is_of_type(EggBin::get_class_type())) {
00180 return add_bin(DCAST(EggBin, egg_node), dx_parent);
00181
00182 } else if (egg_node->is_of_type(EggGroup::get_class_type())) {
00183 return add_group(DCAST(EggGroup, egg_node), dx_parent);
00184
00185 } else if (egg_node->is_of_type(EggGroupNode::get_class_type())) {
00186
00187 EggGroupNode *egg_group = DCAST(EggGroupNode, egg_node);
00188 LPDIRECTXFILEDATA obj;
00189
00190 if (xfile_one_mesh) {
00191
00192
00193 if (!recurse_nodes(egg_group, dx_parent)) {
00194 return false;
00195 }
00196
00197 } else {
00198
00199 if (!create_frame(obj, egg_group->get_name())) {
00200 return false;
00201 }
00202
00203 if (!recurse_nodes(egg_group, obj)) {
00204 obj->Release();
00205 return false;
00206 }
00207
00208 if (!attach_and_release(obj, dx_parent)) {
00209 return false;
00210 }
00211 }
00212
00213 return true;
00214 }
00215
00216
00217 return true;
00218 }
00219
00220
00221
00222
00223
00224
00225 bool XFileMaker::
00226 add_group(EggGroup *egg_group, LPDIRECTXFILEDATA dx_parent) {
00227 if (xfile_one_mesh) {
00228
00229
00230 if (!recurse_nodes(egg_group, dx_parent)) {
00231 return false;
00232 }
00233
00234 } else {
00235
00236 LPDIRECTXFILEDATA obj;
00237 if (!create_frame(obj, egg_group->get_name())) {
00238 return false;
00239 }
00240
00241
00242 if (egg_group->has_transform()) {
00243 add_frame_transform(obj, LCAST(float, egg_group->get_transform()));
00244 }
00245
00246 if (!recurse_nodes(egg_group, obj)) {
00247 obj->Release();
00248 return false;
00249 }
00250
00251 if (!attach_and_release(obj, dx_parent)) {
00252 return false;
00253 }
00254 }
00255
00256 return true;
00257 }
00258
00259
00260
00261
00262
00263
00264
00265 bool XFileMaker::
00266 add_bin(EggBin *egg_bin, LPDIRECTXFILEDATA dx_parent) {
00267 switch (egg_bin->get_bin_number()) {
00268 case EggPolysetMaker::BN_polyset:
00269 return add_polyset(egg_bin, dx_parent);
00270 }
00271
00272 xfile_cat.error()
00273 << "Unexpected bin type " << egg_bin->get_bin_number() << "\n";
00274 return false;
00275 }
00276
00277
00278
00279
00280
00281
00282
00283 bool XFileMaker::
00284 add_polyset(EggBin *egg_bin, LPDIRECTXFILEDATA dx_parent) {
00285
00286 egg_bin->remove_invalid_primitives();
00287
00288 XFileMesh *mesh = get_mesh(dx_parent);
00289
00290 EggGroupNode::iterator ci;
00291 for (ci = egg_bin->begin(); ci != egg_bin->end(); ++ci) {
00292 EggPolygon *poly;
00293 DCAST_INTO_R(poly, *ci, false);
00294
00295 mesh->add_polygon(poly);
00296 }
00297
00298 return true;
00299 }
00300
00301
00302
00303
00304
00305
00306
00307
00308 bool XFileMaker::
00309 recurse_nodes(EggGroupNode *egg_node, LPDIRECTXFILEDATA dx_parent) {
00310 EggGroupNode::iterator ci;
00311 for (ci = egg_node->begin(); ci != egg_node->end(); ++ci) {
00312 EggNode *node = (*ci);
00313 if (!add_node(node, dx_parent)) {
00314 return false;
00315 }
00316 }
00317
00318 return true;
00319 }
00320
00321
00322
00323
00324
00325
00326 bool XFileMaker::
00327 create_object(LPDIRECTXFILEDATA &obj, REFGUID template_id,
00328 const string &name, const Datagram &dg) {
00329 HRESULT hr;
00330
00331 string nice_name = make_nice_name(name);
00332
00333 int data_size = dg.get_length();
00334 void *data_pointer = (void *)dg.get_data();
00335
00336 if (data_size == 0) {
00337 data_pointer = (void *)NULL;
00338 }
00339
00340 hr = _dx_file_save->CreateDataObject
00341 (template_id, nice_name.c_str(), NULL,
00342 data_size, data_pointer, &obj);
00343
00344 if (hr != DXFILE_OK) {
00345 nout << "Unable to create data object for " << name << "\n";
00346 return false;
00347 }
00348 return true;
00349 }
00350
00351
00352
00353
00354
00355
00356 bool XFileMaker::
00357 create_frame(LPDIRECTXFILEDATA &obj, const string &name) {
00358 return create_object(obj, TID_D3DRMFrame, name, Datagram());
00359 }
00360
00361
00362
00363
00364
00365
00366 bool XFileMaker::
00367 add_frame_transform(LPDIRECTXFILEDATA obj, const LMatrix4f &mat) {
00368 Datagram raw_data;
00369 mat.write_datagram(raw_data);
00370
00371 LPDIRECTXFILEDATA xtransform;
00372 if (!create_object(xtransform, TID_D3DRMFrameTransformMatrix,
00373 "transform", raw_data)) {
00374 return false;
00375 }
00376 if (!attach_and_release(xtransform, obj)) {
00377 return false;
00378 }
00379
00380 return true;
00381 }
00382
00383
00384
00385
00386
00387
00388
00389 bool XFileMaker::
00390 attach_and_release(LPDIRECTXFILEDATA obj, LPDIRECTXFILEDATA dx_parent) {
00391 HRESULT hr;
00392
00393
00394
00395 if (!finalize_mesh(obj)) {
00396 return false;
00397 }
00398
00399 if (dx_parent == NULL) {
00400
00401 hr = _dx_file_save->SaveData(obj);
00402 if (hr != DXFILE_OK) {
00403 nout << "Unable to save data object\n";
00404 obj->Release();
00405 return false;
00406 }
00407 } else {
00408
00409 hr = dx_parent->AddDataObject(obj);
00410 if (hr != DXFILE_OK) {
00411 nout << "Unable to save data object\n";
00412 obj->Release();
00413 return false;
00414 }
00415 }
00416
00417 obj->Release();
00418 return true;
00419 }
00420
00421
00422
00423
00424
00425
00426
00427 string XFileMaker::
00428 make_nice_name(const string &str) {
00429 string result;
00430
00431 string::const_iterator si;
00432 for (si = str.begin(); si != str.end(); ++si) {
00433 if (isalnum(*si)) {
00434 result += *si;
00435 } else {
00436 result += "_";
00437 }
00438 }
00439
00440 if (!str.empty() && isdigit(str[0])) {
00441
00442
00443 result = '_' + result;
00444 }
00445
00446 return result;
00447 }
00448
00449
00450
00451
00452
00453
00454
00455 XFileMesh *XFileMaker::
00456 get_mesh(LPDIRECTXFILEDATA dx_parent) {
00457 Meshes::iterator mi = _meshes.find(dx_parent);
00458 if (mi != _meshes.end()) {
00459
00460
00461 return (*mi).second;
00462 }
00463
00464
00465 XFileMesh *mesh = new XFileMesh;
00466 _meshes.insert(Meshes::value_type(dx_parent, mesh));
00467 return mesh;
00468 }
00469
00470
00471
00472
00473
00474
00475
00476
00477 bool XFileMaker::
00478 finalize_mesh(LPDIRECTXFILEDATA dx_parent) {
00479 Meshes::iterator mi = _meshes.find(dx_parent);
00480 if (mi == _meshes.end()) {
00481
00482 return true;
00483 }
00484
00485 XFileMesh *mesh = (*mi).second;
00486 _meshes.erase(mi);
00487
00488
00489 _mesh_index++;
00490 string mesh_index = format_string(_mesh_index);
00491
00492
00493 Datagram raw_data;
00494 mesh->make_mesh_data(raw_data);
00495
00496 LPDIRECTXFILEDATA xobj;
00497 if (!create_object(xobj, TID_D3DRMMesh, "mesh" + mesh_index, raw_data)) {
00498 return false;
00499 }
00500
00501 if (mesh->has_normals()) {
00502
00503 LPDIRECTXFILEDATA xnormals;
00504 mesh->make_normal_data(raw_data);
00505 if (!create_object(xnormals, TID_D3DRMMeshNormals, "norms" + mesh_index,
00506 raw_data)) {
00507 return false;
00508 }
00509 if (!attach_and_release(xnormals, xobj)) {
00510 return false;
00511 }
00512 }
00513
00514 if (mesh->has_colors()) {
00515
00516 LPDIRECTXFILEDATA xcolors;
00517 mesh->make_color_data(raw_data);
00518 if (!create_object(xcolors, TID_D3DRMMeshVertexColors,
00519 "colors" + mesh_index, raw_data)) {
00520 return false;
00521 }
00522 if (!attach_and_release(xcolors, xobj)) {
00523 return false;
00524 }
00525 }
00526
00527 if (mesh->has_uvs()) {
00528
00529 LPDIRECTXFILEDATA xuvs;
00530 mesh->make_uv_data(raw_data);
00531 if (!create_object(xuvs, TID_D3DRMMeshTextureCoords,
00532 "uvs" + mesh_index, raw_data)) {
00533 return false;
00534 }
00535 if (!attach_and_release(xuvs, xobj)) {
00536 return false;
00537 }
00538 }
00539
00540 if (mesh->has_materials()) {
00541
00542 LPDIRECTXFILEDATA xmaterial_list;
00543 mesh->make_material_list_data(raw_data);
00544 if (!create_object(xmaterial_list, TID_D3DRMMeshMaterialList,
00545 "materials" + mesh_index, raw_data)) {
00546 return false;
00547 }
00548
00549
00550
00551 int num_materials = mesh->get_num_materials();
00552 for (int i = 0; i < num_materials; i++) {
00553 XFileMaterial *material = mesh->get_material(i);
00554 LPDIRECTXFILEDATA xmaterial;
00555 material->make_material_data(raw_data);
00556 if (!create_object(xmaterial, TID_D3DRMMaterial,
00557 "material" + mesh_index + "_" + format_string(i),
00558 raw_data)) {
00559 return false;
00560 }
00561
00562
00563
00564 if (material->has_texture()) {
00565 LPDIRECTXFILEDATA xtexture;
00566 material->make_texture_data(raw_data);
00567 if (!create_object(xtexture, TID_D3DRMTextureFilename,
00568 "texture" + mesh_index + "_" + format_string(i),
00569 raw_data)) {
00570 return false;
00571 }
00572
00573 if (!attach_and_release(xtexture, xmaterial)) {
00574 return false;
00575 }
00576 }
00577
00578 if (!attach_and_release(xmaterial, xmaterial_list)) {
00579 return false;
00580 }
00581 }
00582
00583 if (!attach_and_release(xmaterial_list, xobj)) {
00584 return false;
00585 }
00586 }
00587
00588 if (!attach_and_release(xobj, dx_parent)) {
00589 return false;
00590 }
00591 return true;
00592 }