export_3ds.h
Go to the documentation of this file.
00001 /****************************************************************************
00002 * VCGLib                                                            o o     *
00003 * Visual and Computer Graphics Library                            o     o   *
00004 *                                                                _   O  _   *
00005 * Copyright(C) 2004                                                \/)\/    *
00006 * Visual Computing Lab                                            /\/|      *
00007 * ISTI - Italian National Research Council                           |      *
00008 *                                                                    \      *
00009 * All rights reserved.                                                      *
00010 *                                                                           *
00011 * This program is free software; you can redistribute it and/or modify      *   
00012 * it under the terms of the GNU General Public License as published by      *
00013 * the Free Software Foundation; either version 2 of the License, or         *
00014 * (at your option) any later version.                                       *
00015 *                                                                           *
00016 * This program is distributed in the hope that it will be useful,           *
00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
00019 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
00020 * for more details.                                                         *
00021 *                                                                           *
00022 ****************************************************************************/
00023 
00024 
00025 #ifndef __VCGLIB_EXPORT_3DS
00026 #define __VCGLIB_EXPORT_3DS
00027 
00028 #include <map>
00029 #include <wrap/callback.h>
00030 #include <wrap/io_trimesh/io_mask.h>
00031 
00032 #include "io_material.h"
00033 
00034 /*
00035         3DS export needs the Lib3ds library.
00036 
00037         lib3ds is a free ANSI-C library for working with the popular "3ds" 3D model format.
00038 
00039         Supported platforms include GNU (autoconf, automake, libtool, make, GCC) on Unix and 
00040         Cygwin, and MS Visual C++ 6.0. lib3ds loads and saves Atmosphere settings, Background 
00041         settings, Shadow map settings, Viewport setting, Materials, Cameras, Lights, Meshes, 
00042         Hierarchy, Animation keyframes. It also contains useful matrix, vector and quaternion 
00043         mathematics tools. lib3ds usually integrates well with OpenGL. In addition, some 
00044         diagnostic and conversion tools are included. 
00045         
00046         lib3ds is distributed under the terms of the GNU Lesser General Public License.
00047 
00048         this information has been taken by the official site.
00049 
00050         runable from http://lib3ds.sourceforge.net/
00051 
00052 */
00053 #include <lib3ds/file.h>
00054 #include <lib3ds/io.h>
00055 #include <lib3ds/mesh.h>
00056 #include <lib3ds/types.h>
00057 #include <lib3ds/material.h>
00058 
00059 #include <vector>
00060 #include <iostream>
00061 #include <fstream>
00062 
00063 #include <QString>
00064 #include <QMessageBox>
00065 
00066 #define MAX_POLYGONS 65535
00067 
00068 namespace vcg {
00069 namespace tri {
00070 namespace io {
00071 
00072         template <class SaveMeshType>
00073         class Exporter3DS
00074         {
00075         public: 
00076                 typedef typename SaveMeshType::FaceIterator FaceIterator;
00077                 typedef typename SaveMeshType::VertexIterator VertexIterator;
00078                 typedef typename SaveMeshType::VertexType VertexType;
00079 
00080                 //int: old index vertex
00081                 //TexCoord2: tex coord with vertex's index i
00082                 typedef std::pair<int,vcg::TexCoord2<float> > Key;
00083         
00084                 /*
00085                         enum of all the types of error
00086                 */
00087                 enum SaveError
00088                 {
00089                         E_NOERROR,                                      // 0
00090                         E_CANTOPENFILE,                         // 1
00091                         E_CANTCLOSEFILE,                        // 2
00092                         E_UNESPECTEDEOF,                        // 3
00093                         E_ABORTED,                                      // 4
00094                         E_NOTDEFINITION,                        // 5
00095                         E_NOTVEXTEXVALID,                       // 6
00096                         E_NOTFACESVALID,                        // 7
00097                         E_NOTEXCOORDVALID,                      // 8
00098                         E_NOTNUMBERVERTVALID            // 9
00099                 };
00100 
00101                 /*
00102                         this function takes an index and the relative error message gets back
00103                 */
00104                 static const char* ErrorMsg(int error)
00105                 {
00106                         static const char* obj_error_msg[] =
00107                         {
00108                                         "No errors",                                                                                                    // 0
00109                                         "Can't open file",                                                                                              // 1
00110                                         "can't close file",                                                                                             // 2
00111                                         "Premature End of file",                                                                                // 3
00112                                         "File saving aborted",                                                                                  // 4
00113                                         "Function not defined",                                                                                 // 5
00114                                         "Vertices not valid",                                                                                   // 6
00115                                         "Faces not valid",                                                                                              // 7
00116                                         "Texture Coord not valid",                                                                              // 8
00117                                         "You cannot save more than 65535 vertices for the 3DS format"   // 9
00118                                 };
00119 
00120                         if(error>9 || error<0) return "Unknown error";
00121                         else return obj_error_msg[error];
00122                 };
00123 
00124                 /*
00125                         returns mask of capability one define with what are the saveable information of the format.
00126                 */
00127                 static int GetExportMaskCapability()
00128                 {
00129                         int capability = 0;
00130 
00131                         //camera
00132                         //capability |= vcg::tri::io::Mask::IOM_CAMERA;
00133 
00134                         //vert
00135                         //capability |= vcg::tri::io::Mask::IOM_VERTTEXCOORD;
00136 
00137                         //face
00138                         //capability |= vcg::tri::io::Mask::IOM_FACEFLAGS;
00139                         capability |= Mask::IOM_FACECOLOR;
00140                         capability |= Mask::IOM_FACENORMAL;
00141 
00142                         //wedg
00143                         capability |= Mask::IOM_WEDGTEXCOORD;
00144                         capability |= Mask::IOM_WEDGNORMAL;
00145 
00146                         return capability;
00147                 }
00148 
00149                 /*
00150                         function which saves in 3DS file format
00151                 */
00152                 static int SaveBinary(SaveMeshType &m, const char * filename, const int &mask, CallBackPos *cb=0)
00153                 {
00154                         if(m.vn > MAX_POLYGONS)//check max polygons
00155                                 return E_NOTNUMBERVERTVALID;
00156 
00157                         if(m.vn == 0)
00158                                 return E_NOTVEXTEXVALID;
00159                         if(m.fn == 0)
00160                                 return E_NOTFACESVALID;
00161 
00162                         /*
00163                                 <<concetto:>>
00164                                 si tiene in considerazione una mappa ListOfDuplexVert<Key,int>, alla quale gli viene associato il seguente significato:
00165                                         Key:e' una coppia (int,TexCoord) formata da un int che rappresenta l'indice del vettore nella mesh originale e la sua 
00166                                                 coordinata di texture. tale coppia rappresenta una chiave, essendo univoca in tutta la mesh. Non e' possibile che 
00167                                                 si incontrino due vertici che hanno solito indice di vertice e solite coordinate di texture, se un vertice di 
00168                                                 questo tipo esistesse allora i due vertici rappresenterebbero lo stesso vertice.
00169                                         int:e' l'indice del vertice inserito all'interno del vettore VectorOfVertexType<VertexType>
00170                                         
00171                                         Nel vertice VectorOfVertexType vengono inseriti tutti i vertici appartenenti alla mesh + i k vertici dublicati. la scelta 
00172                                         di tali vertici va in base alla seguente regola:
00173                                                 se un vertice con indice x(originale) ha piu' di una coordinata di texture allora tale vertice viene duplicato e 
00174                                                 inserito in ListOfDuplexVert e in VectorOfVertexType(in VectorOfVertexType, l'inserimento del doppio vertice non 
00175                                                 sarebbe necessario, pero' viene fatto per comodita', in caso contrario dovremmo cercare il vertice dentro il vettore).
00176 
00177                                         rappresentazione grafica:
00178 
00179                                         ListOfDuplexVert                                                VectorOfVertexType
00180                                                 ------                                                                  ---------
00181                                                 |key1| -> index1 ---------              |vertex1|
00182                                                 ------                                   |                  ---------
00183                                                 |key2| -> index2 ----    -------------> |vertex2|
00184                                                 ------                          |                                       ---------
00185                                                 |key3|                          |                                       |vertex3|
00186                                                 ------                          |                                       ---------
00187                                                 |key4|                          ------------------>     |vertex4|
00188                                                 ------                                                                  ---------
00189                                                 |key5|                          --------------> |vertex5|
00190                                                 ------                                  |                               ---------
00191                                                   .                                             |                                       .
00192                                                   .                                             |                                       .
00193                                                   .                                             |                                       .
00194                                                 ------                                  |                               ---------
00195                                                 |keyn| -> indexn --------                               |vertexn|
00196                                                 ------                                                                  ---------
00197 
00198 
00199                                 questo tipo di struttura permette di selezionare l'indice del vertice in VectorOfVertexType con costo O(1).
00200 
00201                                 <<code:>>
00202                                 questo pezzo di codice itera su tutte le facce della mesh per riempire la mappa e il vettore.
00203                                 per ogni faccia e per ogni vertice di faccia costruisce la coppia (indice,texture), controlla se
00204                                 all'interno di ListOfDuplexVert esiste gia' in tal caso non fa niente, in caso contrario aggiunte la
00205                                 coppia in ListOfDuplexVert e l'oggetto VertexType in VectorOfVertexType associando al valore della
00206                                 chiave (indice,texture) l'indice del vertice a cui punta.
00207 
00208                                 alla fine vengono duplicati solamente quei vertici che hanno piu' coordinate di texture.
00209 
00210                                 c'e' da tenere presente che il codice appena descritto viene eseguito SOLAMENTE se la mesh contiene texture e
00211                                 se dalla dialog di exporter viene spuntato il salvataggio delle texture. In caso contrario non esegue niente e tratta
00212                                 solamente i vertici che sono presenti nella mesh senza creare duplicati. Le informazioni presenti in assenza di
00213                                 texture sono piu' che sufficienti.
00214 
00215 
00216                                                                                                                                                                                                                 Federico Mazzanti
00217                         */                      
00218                         std::map<Key,int> ListOfDuplexVert;
00219                         std::vector<VertexType> VectorOfVertexType;
00220       std::vector<int> VertRemap; // VertRemap[i] keep the final position of m.vert[i] inside the 3ds vertex list. used for remapping the pointers to vertex in the faces
00221                         int count = 1;
00222                         int nface = 0;
00223                         if(HasPerWedgeTexCoord(m) && (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD) )
00224                         {
00225                                 FaceIterator fi;
00226                                 for(fi=m.face.begin(); fi!=m.face.end(); ++fi) if( !(*fi).IsD() )
00227                                 {
00228                                         for(unsigned int k=0;k<3;k++)
00229                                         {
00230                                                 int i = GetIndexVertex(m, (*fi).V(k));
00231                                                 vcg::TexCoord2<float> t = (*fi).WT(k);
00232                                                 if(!m.vert[i].IsD())
00233                                                 {
00234                                                         if(AddDuplexVertexCoord(ListOfDuplexVert,Key(i,t)))
00235                                                         {
00236                                                                 VectorOfVertexType.push_back((*(*fi).V(k)));
00237                                                                 ListOfDuplexVert[Key(i,t)] = VectorOfVertexType.size()-1;
00238                                                                 count++;
00239                                                         }
00240                                                 }
00241                                         }
00242 
00243                                         if (cb !=NULL)
00244                                                 (*cb)(100.0 * (float)++nface/(float)m.face.size(), "calc duplex vertex ...");
00245                                         else
00246                                                 return E_ABORTED;
00247                                 }
00248                         }
00249 
00250                         int number_vertex_to_duplicate = 0;
00251                         
00252                         if(HasPerWedgeTexCoord(m) && (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD ))
00253                                 number_vertex_to_duplicate = (count-1) - m.vn;
00254 
00255                         Lib3dsFile *file = lib3ds_file_new();//creates new file
00256                         Lib3dsMesh *mesh = lib3ds_mesh_new("mesh");//creates a new mesh with mesh's name "mesh"         
00257 
00258                         QString qnamematerial = "Material - %1";
00259                         std::vector<Material> materials;
00260                         
00261                         int current = 0;
00262                         int max = m.vn+m.fn+number_vertex_to_duplicate;
00263                         
00264                         lib3ds_mesh_new_point_list(mesh, m.vn + number_vertex_to_duplicate);// set number of vertexs
00265         
00266                         if(HasPerWedgeTexCoord(m) && (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD ))
00267                                 lib3ds_mesh_new_texel_list(mesh,m.vn + number_vertex_to_duplicate); //set number of textures
00268 
00269                         int v_index = 0;
00270                         VertexIterator vi;
00271                         //saves vert
00272                         if(HasPerWedgeTexCoord(m) && (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD ))
00273                         {
00274                                 for(unsigned int i=0; i< VectorOfVertexType.size();i++)
00275                                 {
00276                                         Lib3dsPoint point;
00277                                         point.pos[0] = VectorOfVertexType[i].P()[0];
00278                                         point.pos[1] = VectorOfVertexType[i].P()[1];
00279                                         point.pos[2] = VectorOfVertexType[i].P()[2];
00280                 
00281                                         mesh->pointL[i] = point;                
00282 
00283                                         if (cb !=NULL)
00284                                                 (*cb)(100.0 * (float)++current/(float)max, "writing vertices ");
00285                                         else
00286                                                 return E_ABORTED;
00287                                 }
00288                         }
00289                         else
00290                         {
00291         VertRemap.resize(m.vert.size(),-1);
00292                                 for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi) if( !(*vi).IsD() )
00293                                 {
00294                                         Lib3dsPoint point;
00295                                         point.pos[0] = (*vi).P()[0];
00296                                         point.pos[1] = (*vi).P()[1];
00297                                         point.pos[2] = (*vi).P()[2];
00298 
00299                                         mesh->pointL[v_index] = point;          
00300           VertRemap[vi-m.vert.begin()]=v_index;
00301                                         if (cb !=NULL)
00302                                                 (*cb)(100.0 * (float)++current/(float)max, "writing vertices ");
00303                                         else
00304                                                 return E_ABORTED;
00305                                         v_index++;
00306                                 }
00307                         }
00308 
00309                         lib3ds_mesh_new_face_list (mesh, m.face.size());//set number of faces
00310                         int f_index = 0;//face index
00311                         //int t_index = 0;//texture index
00312                         FaceIterator fi;
00313                         for(fi=m.face.begin(); fi!=m.face.end(); ++fi) if( !(*fi).IsD() )
00314                         {
00315         vcg::TexCoord2<float> t0(0,0),t1(0,0),t2(0,0);
00316                                 int i0 = GetIndexVertex(m, (*fi).V(0));
00317                                 int i1 = GetIndexVertex(m, (*fi).V(1));
00318                                 int i2 = GetIndexVertex(m, (*fi).V(2));
00319                                 if(HasPerWedgeTexCoord(m) && (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD ) )
00320                                 {
00321                                         t0 = (*fi).WT(0);
00322                                         t1 = (*fi).WT(1);
00323                                         t2 = (*fi).WT(2);
00324                                 }
00325 
00326                                 Lib3dsFace face;
00327                                 if(HasPerWedgeTexCoord(m) && (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD ))
00328                                 {
00329                                         face.points[0] = GetIndexDuplexVertex(ListOfDuplexVert,Key(i0,t0));
00330                                         face.points[1] = GetIndexDuplexVertex(ListOfDuplexVert,Key(i1,t1));
00331                                         face.points[2] = GetIndexDuplexVertex(ListOfDuplexVert,Key(i2,t2));
00332                                 }
00333                                 else
00334                                 {
00335                                         face.points[0] = VertRemap[i0];
00336                                         face.points[1] = VertRemap[i1];
00337                                         face.points[2] = VertRemap[i2];
00338                                 }
00339                                 
00340                                 //saves coord textures
00341                                 if(HasPerWedgeTexCoord(m) && (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD ) )
00342                                 {
00343                                         mesh->texelL[face.points[0]][0] = t0.u();
00344                                         mesh->texelL[face.points[0]][1] = t0.v();
00345                                         mesh->texelL[face.points[1]][0] = t1.u();
00346                                         mesh->texelL[face.points[1]][1] = t1.v();
00347                                         mesh->texelL[face.points[2]][0] = t2.u();
00348                                         mesh->texelL[face.points[2]][1] = t2.v();
00349                                 }
00350 
00351                                 if(mask & vcg::tri::io::Mask::IOM_FACEFLAGS)
00352                                         face.flags = 0;
00353                                 
00354                                 face.smoothing = 10;
00355 
00356                                 if((mask & vcg::tri::io::Mask::IOM_FACENORMAL) | (mask & vcg::tri::io::Mask::IOM_WEDGNORMAL) )
00357                                 {
00358                                         face.normal[0] = (*fi).N()[0];
00359                                         face.normal[1] = (*fi).N()[1];
00360                                         face.normal[2] = (*fi).N()[2];
00361                                 }
00362 
00363                                 if((mask & vcg::tri::io::Mask::IOM_FACECOLOR) | (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD))
00364                                 {
00365                                         int material_index = vcg::tri::io::Materials<SaveMeshType>::CreateNewMaterial(m, materials, 0, fi);
00366                                         if(material_index == (int)materials.size())
00367                                         {
00368                                                 Lib3dsMaterial *material = lib3ds_material_new();//creates a new material
00369                                                 
00370                                                 std::string name = qnamematerial.arg(material_index-1).toStdString();
00371                                                 strcpy(material->name,name.c_str());//copy new name of material
00372 
00373                                                 if(mask & vcg::tri::io::Mask::IOM_FACECOLOR)
00374                                                 {
00375                                                         //ambient
00376                                                         material->ambient[0] = materials[materials.size()-1].Ka[0];
00377                                                         material->ambient[1] = materials[materials.size()-1].Ka[1];
00378                                                         material->ambient[2] = materials[materials.size()-1].Ka[2];
00379                                                         material->ambient[3] = materials[materials.size()-1].Tr;
00380 
00381                                                         //diffuse
00382                                                         material->diffuse[0] = materials[materials.size()-1].Kd[0];
00383                                                         material->diffuse[1] = materials[materials.size()-1].Kd[1];
00384                                                         material->diffuse[2] = materials[materials.size()-1].Kd[2];
00385                                                         material->diffuse[3] = materials[materials.size()-1].Tr;
00386 
00387                                                         //specular
00388                                                         material->specular[0] = materials[materials.size()-1].Ks[0];
00389                                                         material->specular[1] = materials[materials.size()-1].Ks[1];
00390                                                         material->specular[2] = materials[materials.size()-1].Ks[2];
00391                                                         material->specular[3] = materials[materials.size()-1].Tr;
00392 
00393                                                         //shininess
00394                                                         material->shininess = materials[materials.size()-1].Ns;
00395                                                 }
00396                                                                                         
00397                                                 //texture
00398                                     if(HasPerWedgeTexCoord(m) && (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD ) )
00399                                                         strcpy(material->texture1_map.name,materials[materials.size()-1].map_Kd.c_str());
00400 
00401                                                 lib3ds_file_insert_material(file,material);//inserts the material inside the file
00402                                                 strcpy(face.material,name.c_str());
00403                                         }
00404                                         else
00405                                         {       
00406                                                 std::string name = qnamematerial.arg(material_index).toStdString();
00407                                                 strcpy(face.material,name.c_str());//set name of material
00408                                         }
00409                                 }
00410 
00411                                 mesh->faceL[f_index]=face;
00412 
00413                                 if (cb !=NULL)
00414                                         (*cb)(100.0 * (float)++current/(float)max, "writing faces ");
00415                                 else 
00416                                         return E_ABORTED;
00417                                 f_index++;
00418                                 
00419                         }
00420 
00421                         lib3ds_file_insert_mesh(file, mesh);//inserts the Mesh into file
00422                         
00423                         Lib3dsNode *node = lib3ds_node_new_object();//creates a new node
00424                         strcpy(node->name,mesh->name);
00425                         node->parent_id = LIB3DS_NO_PARENT;     
00426                         lib3ds_file_insert_node(file,node);//inserts the node into file
00427 
00428                         bool result = lib3ds_file_save(file, filename); //saves the file
00429                         if(result)
00430                                 return E_NOERROR; 
00431                         else 
00432                                 return E_ABORTED;
00433                 }
00434                 
00435                 /*
00436                         function which saves in 3DS format
00437                 */
00438                 static int Save(SaveMeshType &m, const char * filename, const int &mask, CallBackPos *cb=0)
00439                 {
00440                         return SaveBinary(m,filename,mask,cb);  
00441                 }
00442 
00443                 /*
00444                         returns index of the vertex
00445                 */
00446                 inline static int GetIndexVertex(SaveMeshType &m, VertexType *p)
00447                 {
00448                         return p-&*(m.vert.begin());
00449                 }
00450 
00451                 /*
00452                         added pair Key,int into map
00453                 */
00454                 inline static bool AddDuplexVertexCoord(std::map<Key,int> &m,Key key)
00455                 {
00456                         int index = m[key];
00457                         if(index==0)
00458                                 return true;
00459                         return false;
00460                 }
00461 
00462                 /*
00463                         returns value of key key into map. this value is vertex's index into list all duplicate vertex
00464                 */
00465                 inline static int GetIndexDuplexVertex(std::map<Key,int> &m,Key key)
00466                 {
00467                         return m[key];
00468                 }
00469 
00470         }; // end class
00471 
00472 } // end Namespace tri
00473 } // end Namespace io
00474 } // end Namespace vcg
00475 
00476 #endif


shape_reconstruction
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:30:49