00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 #ifndef __VCGLIB_EXPORT_3DS
00135 #define __VCGLIB_EXPORT_3DS
00136
00137 #include <map>
00138 #include <wrap/callback.h>
00139 #include <vcg/complex/trimesh/allocate.h>
00140 #include <wrap/io_trimesh/io_mask.h>
00141
00142 #include "io_material.h"
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 #include <lib3ds/file.h>
00164 #include <lib3ds/io.h>
00165 #include <lib3ds/mesh.h>
00166 #include <lib3ds/types.h>
00167 #include <lib3ds/material.h>
00168
00169 #include <vector>
00170 #include <iostream>
00171 #include <fstream>
00172
00173 #include <QString>
00174 #include <QMessageBox>
00175
00176 #define MAX_POLYGONS 65535
00177
00178 namespace vcg {
00179 namespace tri {
00180 namespace io {
00181
00182 template <class SaveMeshType>
00183 class Exporter3DS
00184 {
00185 public:
00186 typedef typename SaveMeshType::FaceIterator FaceIterator;
00187 typedef typename SaveMeshType::VertexIterator VertexIterator;
00188 typedef typename SaveMeshType::VertexType VertexType;
00189
00190
00191
00192 typedef std::pair<int,vcg::TexCoord2<float> > Key;
00193
00194
00195
00196
00197 enum SaveError
00198 {
00199 E_NOERROR,
00200 E_CANTOPENFILE,
00201 E_CANTCLOSEFILE,
00202 E_UNESPECTEDEOF,
00203 E_ABORTED,
00204 E_NOTDEFINITION,
00205 E_NOTVEXTEXVALID,
00206 E_NOTFACESVALID,
00207 E_NOTEXCOORDVALID,
00208 E_NOTNUMBERVERTVALID
00209 };
00210
00211
00212
00213
00214 static const char* ErrorMsg(int error)
00215 {
00216 static const char* obj_error_msg[] =
00217 {
00218 "No errors",
00219 "Can't open file",
00220 "can't close file",
00221 "Premature End of file",
00222 "File saving aborted",
00223 "Function not defined",
00224 "Vertices not valid",
00225 "Faces not valid",
00226 "Texture Coord not valid",
00227 "You cannot save more than 65535 vertices for the 3DS format"
00228 };
00229
00230 if(error>9 || error<0) return "Unknown error";
00231 else return obj_error_msg[error];
00232 };
00233
00234
00235
00236
00237 static int GetExportMaskCapability()
00238 {
00239 int capability = 0;
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 capability |= Mask::IOM_FACECOLOR;
00250 capability |= Mask::IOM_FACENORMAL;
00251
00252
00253 capability |= Mask::IOM_WEDGTEXCOORD;
00254 capability |= Mask::IOM_WEDGNORMAL;
00255
00256 return capability;
00257 }
00258
00259
00260
00261
00262 static int SaveBinary(SaveMeshType &m, const char * filename, const int &mask, CallBackPos *cb=0)
00263 {
00264 if(m.vn > MAX_POLYGONS)
00265 return E_NOTNUMBERVERTVALID;
00266
00267 if(m.vn == 0)
00268 return E_NOTVEXTEXVALID;
00269 if(m.fn == 0)
00270 return E_NOTFACESVALID;
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328 std::map<Key,int> ListOfDuplexVert;
00329 std::vector<VertexType> VectorOfVertexType;
00330 std::vector<int> VertRemap;
00331 int count = 1;
00332 int nface = 0;
00333 if(HasPerWedgeTexCoord(m) && (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD) )
00334 {
00335 FaceIterator fi;
00336 for(fi=m.face.begin(); fi!=m.face.end(); ++fi) if( !(*fi).IsD() )
00337 {
00338 for(unsigned int k=0;k<3;k++)
00339 {
00340 int i = GetIndexVertex(m, (*fi).V(k));
00341 vcg::TexCoord2<float> t = (*fi).WT(k);
00342 if(!m.vert[i].IsD())
00343 {
00344 if(AddDuplexVertexCoord(ListOfDuplexVert,Key(i,t)))
00345 {
00346 VectorOfVertexType.push_back((*(*fi).V(k)));
00347 ListOfDuplexVert[Key(i,t)] = VectorOfVertexType.size()-1;
00348 count++;
00349 }
00350 }
00351 }
00352
00353 if (cb !=NULL)
00354 (*cb)(100.0 * (float)++nface/(float)m.face.size(), "calc duplex vertex ...");
00355 else
00356 return E_ABORTED;
00357 }
00358 }
00359
00360 int number_vertex_to_duplicate = 0;
00361
00362 if(HasPerWedgeTexCoord(m) && (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD ))
00363 number_vertex_to_duplicate = (count-1) - m.vn;
00364
00365 Lib3dsFile *file = lib3ds_file_new();
00366 Lib3dsMesh *mesh = lib3ds_mesh_new("mesh");
00367
00368 QString qnamematerial = "Material - %1";
00369 std::vector<Material> materials;
00370
00371 int current = 0;
00372 int max = m.vn+m.fn+number_vertex_to_duplicate;
00373
00374 lib3ds_mesh_new_point_list(mesh, m.vn + number_vertex_to_duplicate);
00375
00376 if(HasPerWedgeTexCoord(m) && (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD ))
00377 lib3ds_mesh_new_texel_list(mesh,m.vn + number_vertex_to_duplicate);
00378
00379 int v_index = 0;
00380 VertexIterator vi;
00381
00382 if(HasPerWedgeTexCoord(m) && (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD ))
00383 {
00384 for(unsigned int i=0; i< VectorOfVertexType.size();i++)
00385 {
00386 Lib3dsPoint point;
00387 point.pos[0] = VectorOfVertexType[i].P()[0];
00388 point.pos[1] = VectorOfVertexType[i].P()[1];
00389 point.pos[2] = VectorOfVertexType[i].P()[2];
00390
00391 mesh->pointL[i] = point;
00392
00393 if (cb !=NULL)
00394 (*cb)(100.0 * (float)++current/(float)max, "writing vertices ");
00395 else
00396 return E_ABORTED;
00397 }
00398 }
00399 else
00400 {
00401 VertRemap.resize(m.vert.size(),-1);
00402 for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi) if( !(*vi).IsD() )
00403 {
00404 Lib3dsPoint point;
00405 point.pos[0] = (*vi).P()[0];
00406 point.pos[1] = (*vi).P()[1];
00407 point.pos[2] = (*vi).P()[2];
00408
00409 mesh->pointL[v_index] = point;
00410 VertRemap[vi-m.vert.begin()]=v_index;
00411 if (cb !=NULL)
00412 (*cb)(100.0 * (float)++current/(float)max, "writing vertices ");
00413 else
00414 return E_ABORTED;
00415 v_index++;
00416 }
00417 }
00418
00419 lib3ds_mesh_new_face_list (mesh, m.face.size());
00420 int f_index = 0;
00421
00422 FaceIterator fi;
00423 for(fi=m.face.begin(); fi!=m.face.end(); ++fi) if( !(*fi).IsD() )
00424 {
00425 vcg::TexCoord2<float> t0(0,0),t1(0,0),t2(0,0);
00426 int i0 = GetIndexVertex(m, (*fi).V(0));
00427 int i1 = GetIndexVertex(m, (*fi).V(1));
00428 int i2 = GetIndexVertex(m, (*fi).V(2));
00429 if(HasPerWedgeTexCoord(m) && (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD ) )
00430 {
00431 t0 = (*fi).WT(0);
00432 t1 = (*fi).WT(1);
00433 t2 = (*fi).WT(2);
00434 }
00435
00436 Lib3dsFace face;
00437 if(HasPerWedgeTexCoord(m) && (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD ))
00438 {
00439 face.points[0] = GetIndexDuplexVertex(ListOfDuplexVert,Key(i0,t0));
00440 face.points[1] = GetIndexDuplexVertex(ListOfDuplexVert,Key(i1,t1));
00441 face.points[2] = GetIndexDuplexVertex(ListOfDuplexVert,Key(i2,t2));
00442 }
00443 else
00444 {
00445 face.points[0] = VertRemap[i0];
00446 face.points[1] = VertRemap[i1];
00447 face.points[2] = VertRemap[i2];
00448 }
00449
00450
00451 if(HasPerWedgeTexCoord(m) && (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD ) )
00452 {
00453 mesh->texelL[face.points[0]][0] = t0.u();
00454 mesh->texelL[face.points[0]][1] = t0.v();
00455 mesh->texelL[face.points[1]][0] = t1.u();
00456 mesh->texelL[face.points[1]][1] = t1.v();
00457 mesh->texelL[face.points[2]][0] = t2.u();
00458 mesh->texelL[face.points[2]][1] = t2.v();
00459 }
00460
00461 if(mask & vcg::tri::io::Mask::IOM_FACEFLAGS)
00462 face.flags = 0;
00463
00464 face.smoothing = 10;
00465
00466 if((mask & vcg::tri::io::Mask::IOM_FACENORMAL) | (mask & vcg::tri::io::Mask::IOM_WEDGNORMAL) )
00467 {
00468 face.normal[0] = (*fi).N()[0];
00469 face.normal[1] = (*fi).N()[1];
00470 face.normal[2] = (*fi).N()[2];
00471 }
00472
00473 if((mask & vcg::tri::io::Mask::IOM_FACECOLOR) | (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD))
00474 {
00475 int material_index = vcg::tri::io::Materials<SaveMeshType>::CreateNewMaterial(m, materials, 0, fi);
00476 if(material_index == (int)materials.size())
00477 {
00478 Lib3dsMaterial *material = lib3ds_material_new();
00479
00480 std::string name = qnamematerial.arg(material_index-1).toStdString();
00481 strcpy(material->name,name.c_str());
00482
00483 if(mask & vcg::tri::io::Mask::IOM_FACECOLOR)
00484 {
00485
00486 material->ambient[0] = materials[materials.size()-1].Ka[0];
00487 material->ambient[1] = materials[materials.size()-1].Ka[1];
00488 material->ambient[2] = materials[materials.size()-1].Ka[2];
00489 material->ambient[3] = materials[materials.size()-1].Tr;
00490
00491
00492 material->diffuse[0] = materials[materials.size()-1].Kd[0];
00493 material->diffuse[1] = materials[materials.size()-1].Kd[1];
00494 material->diffuse[2] = materials[materials.size()-1].Kd[2];
00495 material->diffuse[3] = materials[materials.size()-1].Tr;
00496
00497
00498 material->specular[0] = materials[materials.size()-1].Ks[0];
00499 material->specular[1] = materials[materials.size()-1].Ks[1];
00500 material->specular[2] = materials[materials.size()-1].Ks[2];
00501 material->specular[3] = materials[materials.size()-1].Tr;
00502
00503
00504 material->shininess = materials[materials.size()-1].Ns;
00505 }
00506
00507
00508 if(HasPerWedgeTexCoord(m) && (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD ) )
00509 strcpy(material->texture1_map.name,materials[materials.size()-1].map_Kd.c_str());
00510
00511 lib3ds_file_insert_material(file,material);
00512 strcpy(face.material,name.c_str());
00513 }
00514 else
00515 {
00516 std::string name = qnamematerial.arg(material_index).toStdString();
00517 strcpy(face.material,name.c_str());
00518 }
00519 }
00520
00521 mesh->faceL[f_index]=face;
00522
00523 if (cb !=NULL)
00524 (*cb)(100.0 * (float)++current/(float)max, "writing faces ");
00525 else
00526 return E_ABORTED;
00527 f_index++;
00528
00529 }
00530
00531 lib3ds_file_insert_mesh(file, mesh);
00532
00533 Lib3dsNode *node = lib3ds_node_new_object();
00534 strcpy(node->name,mesh->name);
00535 node->parent_id = LIB3DS_NO_PARENT;
00536 lib3ds_file_insert_node(file,node);
00537
00538 bool result = lib3ds_file_save(file, filename);
00539 if(result)
00540 return E_NOERROR;
00541 else
00542 return E_ABORTED;
00543 }
00544
00545
00546
00547
00548 static int Save(SaveMeshType &m, const char * filename, const int &mask, CallBackPos *cb=0)
00549 {
00550 return SaveBinary(m,filename,mask,cb);
00551 }
00552
00553
00554
00555
00556 inline static int GetIndexVertex(SaveMeshType &m, VertexType *p)
00557 {
00558 return p-&*(m.vert.begin());
00559 }
00560
00561
00562
00563
00564 inline static bool AddDuplexVertexCoord(std::map<Key,int> &m,Key key)
00565 {
00566 int index = m[key];
00567 if(index==0)
00568 return true;
00569 return false;
00570 }
00571
00572
00573
00574
00575 inline static int GetIndexDuplexVertex(std::map<Key,int> &m,Key key)
00576 {
00577 return m[key];
00578 }
00579
00580 };
00581
00582 }
00583 }
00584 }
00585
00586 #endif