export_fbx.h
Go to the documentation of this file.
00001 #ifndef EXPORT_FBX
00002 #define EXPORT_FBX
00003 
00004 #include <fbxsdk.h>
00005 
00006 /******************************
00007 ExporterFBX is the class devoted to export the info contained in a VCG mesh to an FBX file.
00008 In order to compile the following class you need to:
00009         - download the VCGlib from our SVN server and put the code in ../../vcglib
00010         - download from Autodesk website the FBXSDK-2012.1 and put the lib and include folders in ../fbx-2012.1
00011 */
00012 
00013 template <class SaveMeshType>
00014 class ExporterFBX
00015 {
00016 public:
00017         typedef typename SaveMeshType::VertexPointer VertexPointer;
00018         typedef typename SaveMeshType::ScalarType ScalarType;
00019         typedef typename SaveMeshType::VertexType VertexType;
00020         typedef typename SaveMeshType::FaceType FaceType;
00021         typedef typename SaveMeshType::FacePointer FacePointer;
00022         typedef typename SaveMeshType::VertexIterator VertexIterator;
00023         typedef typename SaveMeshType::FaceIterator FaceIterator;
00024         typedef typename SaveMeshType::CoordType CoordType;
00025 
00026         /****
00027                 The Save function save the info contained in a mesh into a FBX file.
00028                 Parameters:
00029                         - m is the mesh containing geometry, textures and materials info
00030                         - filename is the path of the file in which you want to save the data.
00031                         - binary says to the function if you want to save the file in binary or ascii format.
00032                         - embed Do you want textures directly embedded inside the file? 
00033                         Please note that accordingly to FBX SDK semantics is meaningless to ask for a ascii file with embedded textures. 
00034                         At the opposite it's perfectly legal to have a binary file without embedded textures.
00035                         - mask is used by the programmer to specify which attributes the function should save on the file. For example if I want to save vertex normal and wedge texture
00036                         I should write something like mask = tri::io::Mask::IOM_WEDGTEXCOORD | tri::io::Mask::IOM_VERTCOLOR | tri::io::Mask::IOM_VERTNORMAL;
00037         */
00038 
00039         static int Save(SaveMeshType &m, const char * filename,const bool binary,const bool embed,const int mask)
00040         {
00041                 KFbxSdkManager* sdkman = KFbxSdkManager::Create();
00042 
00043                 KFbxIOSettings * ios = KFbxIOSettings::Create(sdkman, IOSROOT );
00044                 ios->SetBoolProp(EXP_FBX_MATERIAL,true);
00045                 ios->SetBoolProp(EXP_FBX_TEXTURE,true);
00046                 ios->SetBoolProp(EXP_FBX_EMBEDDED,embed);
00047                 ios->SetBoolProp(EXP_FBX_SHAPE,true);
00048                 ios->SetBoolProp(EXP_FBX_ANIMATION,false);
00049                 ios->SetBoolProp(EXP_FBX_GLOBAL_SETTINGS, true);
00050                 sdkman->SetIOSettings(ios);
00051 
00052                 if(sdkman == NULL) 
00053                         return -1;
00054 
00055                 KFbxExporter* lExporter = KFbxExporter::Create(sdkman,"VCGFbxFileExporter");
00056                 int asciiexportind = -1;
00057 
00058                 if ((!binary) && (!embed))
00059                 {
00060                         int formatnum = sdkman->GetIOPluginRegistry()->GetWriterFormatCount();
00061                         bool asciifound = false;
00062                         int ii = 0;
00063                         while ((!asciifound) && (ii<formatnum))
00064                         {
00065                                 if (sdkman->GetIOPluginRegistry()->WriterIsFBX(ii))
00066                                 {
00067                                         KString plugdesc =sdkman->GetIOPluginRegistry()->GetWriterFormatDescription(ii);
00068                                         if (plugdesc.Find("ascii")>=0)
00069                                         {
00070                                                 asciiexportind = ii;
00071                                                 asciifound = true;
00072                                         }
00073                                 }
00074                                 ++ii;
00075                         }
00076                 }
00077 
00078 
00079                 if(!lExporter->Initialize(filename, asciiexportind,ios))
00080                         return false;
00081 
00082                 KFbxScene* scene = KFbxScene::Create(sdkman,"VCGScene");
00083                 bool result = fillScene(m,*scene,mask);
00084                 if (!result)
00085                         return -1;
00086                 result = lExporter->Export(scene);
00087                 lExporter->Destroy();
00088                 if (!result)
00089                         return -1;
00090                 return 0;
00091         }
00092 
00093         /********
00094                 GetExportCapability returns a mask with extra attributes that ExporterFBX class is able to export.  
00095                 It doesn't mean that in every file you export you will find all these attributes.
00096                 The attributes set you want to actually export are defined by the mask parameter in the Save function.
00097         */
00098 
00099         static int GetExportMaskCapability()
00100         {
00101                 int capability = 0;                     
00102                 capability |= vcg::tri::io::Mask::IOM_VERTCOORD;
00103                 capability |= vcg::tri::io::Mask::IOM_VERTCOLOR;
00104                 capability |= vcg::tri::io::Mask::IOM_VERTNORMAL;
00105                 capability |= vcg::tri::io::Mask::IOM_WEDGTEXCOORD;
00106                 return capability;
00107         }
00108 
00109 private:
00110 
00111         static KFbxFileTexture* newTexture(KFbxScene& scene,const char* name,const KFbxVector2& trans = KFbxVector2(0.0,0.0),const KFbxVector2& rot = KFbxVector2(0.0,0.0),const KFbxVector2& scal = KFbxVector2(1.0,1.0))
00112         {
00113                 static int conttext = 0;
00114                 std::string label = createName("texture_",conttext);
00115                 KFbxFileTexture* text = KFbxFileTexture::Create(&scene,label.c_str());
00116                 text->SetFileName(name); 
00117                 text->SetTextureUse(KFbxTexture::eSTANDARD);
00118                 text->SetMappingType(KFbxTexture::eUV);
00119                 text->SetMaterialUse(KFbxFileTexture::eMODEL_MATERIAL);
00120                 text->SetSwapUV(false);
00121                 text->SetTranslation(trans[0],trans[1]);
00122                 text->SetScale(scal[0],scal[1]);
00123                 text->SetRotation(rot[0],rot[1]);
00124                 ++conttext;
00125                 return text;
00126         }
00127 
00128         static KFbxSurfacePhong* newPhongMaterial(KFbxScene& scene,const char* name,KFbxFileTexture* text = NULL,const fbxDouble3& dif = fbxDouble3(1.0,1.0,1.0)/*,const fbxDouble3& amb = fbxDouble3(1.0,1.0,1.0),const fbxDouble3& em = fbxDouble3(1.0,1.0,1.0),const double& transp = 0.0,const double& shin = 0.0*/)
00129         {
00130                 KFbxSurfacePhong* mat = KFbxSurfacePhong::Create(&scene, name);
00131                 mat->Diffuse.Set(dif);
00132                 //mat->Ambient.Set(amb);
00133                 //mat->Emissive.Set(em);
00134                 //mat->TransparencyFactor.Set(transp);
00135                 //mat->ShadingModel.Set("Phong");
00136                 //mat->Shininess.Set(shin);
00137                 if (text)
00138                         mat->Diffuse.ConnectSrcObject(text);
00139                 return mat;
00140         }
00141 
00142         static void insertMaterialElementLayer(KFbxMesh* vcgmesh)
00143         {
00144                 KFbxGeometryElementMaterial* lMaterialElement = vcgmesh->CreateElementMaterial();
00145                 lMaterialElement->SetMappingMode(KFbxGeometryElement::eBY_POLYGON);
00146                 lMaterialElement->SetReferenceMode(KFbxGeometryElement::eINDEX_TO_DIRECT);
00147         }
00148 
00149         static std::string      createName(const char* base,const int ind)
00150         {
00151                 char buffer[33];
00152                 sprintf(buffer,"%d",ind);
00153                 std::string res = std::string(base) + std::string(buffer);
00154                 return res;
00155         }
00156 
00157         static bool fillScene(SaveMeshType& m,KFbxScene& scene,const int mask)
00158         {
00159                 bool wedgetexcoord = (vcg::tri::HasPerWedgeTexCoord(m) && (mask | vcg::tri::io::Mask::IOM_WEDGTEXCOORD));
00160                 bool vertnorm = (vcg::tri::HasPerVertexNormal(m) && (mask | vcg::tri::io::Mask::IOM_VERTNORMAL));
00161                 bool facecolasmaterial = false;
00162                 int fn = int(m.face.size());
00163                 std::set<vcg::Color4b> matset;  
00164                 
00165                 
00166 
00167                 if (wedgetexcoord)
00168                 {
00169                         for(int ii = 0;ii < fn;++ii)
00170                         {
00171                                 if (!m.face[ii].IsD())
00172                                 {
00173                                         int ind = m.face[ii].WT(0).N();
00174                                         if ((ind == -1) && vcg::tri::HasPerVertexColor(m))
00175                                         {
00176                                                 for(int hh = 0;hh < 3;++hh)
00177                                                         matset.insert(m.face[ii].V(hh)->C());
00178                                                 facecolasmaterial = true;
00179                                         }
00180                                 }
00181                         }
00182                 }
00183 
00184                 bool vertcol = (vcg::tri::HasPerVertexColor(m) && (mask | vcg::tri::io::Mask::IOM_VERTCOLOR)) && !facecolasmaterial;
00185                 /*KFbxNode* cam  = insertCamera(&scene, "VCGCamera");*/
00186 
00187                 KFbxMesh* vcgmesh = KFbxMesh::Create(&scene,"VCGMeshAttribute");
00188                 KFbxNode* meshnode = KFbxNode::Create(&scene,"VCGMeshNode");
00189                 meshnode->SetNodeAttribute(vcgmesh);
00190                 if (m.textures.size() > 0)
00191                         meshnode->SetShadingMode(KFbxNode::eTEXTURE_SHADING);
00192                 else
00193                         meshnode->SetShadingMode(KFbxNode::eHARD_SHADING);
00194 
00195                 KFbxGeometryElementVertexColor* vcolorlay = NULL;
00196                 if (vertcol)
00197                 {
00198                         vcolorlay = vcgmesh->CreateElementVertexColor();
00199                         vcolorlay->SetMappingMode(KFbxGeometryElement::eBY_CONTROL_POINT);
00200                         vcolorlay->SetReferenceMode(KFbxGeometryElement::eDIRECT);
00201                 }
00202 
00203                 KFbxGeometryElementNormal* vnormlay = NULL;
00204                 if (vertnorm)
00205                 {
00206                         vnormlay = vcgmesh->CreateElementNormal();
00207                         vnormlay->SetMappingMode(KFbxGeometryElement::eBY_CONTROL_POINT);
00208                         vnormlay->SetReferenceMode(KFbxGeometryElement::eDIRECT);
00209                 }
00210                 int zz;
00211                 for(zz = 0;zz < m.textures.size();++zz)
00212                 {
00213                         KFbxFileTexture* tex = newTexture(scene,m.textures[zz].c_str());
00214                         KFbxSurfacePhong* phong = newPhongMaterial(scene,createName("mat_",zz).c_str(),tex);
00215                         KFbxNode* meshnode = vcgmesh->GetNode();
00216                         if(meshnode == NULL) 
00217                                 return false;
00218                         meshnode->AddMaterial(phong);
00219                 }
00220                 
00221                 for(std::set<vcg::Color4b>::iterator it = matset.begin();it != matset.end();++it)
00222                 {
00223                         vcg::Color4b vcgcol = *it;
00224                         fbxDouble3 fbxcol(vcgcol[0] / 255.0f,vcgcol[1]/ 255.0f,vcgcol[2]/ 255.0f);
00225                         KFbxSurfacePhong* phong = newPhongMaterial(scene,createName("mat_",zz).c_str(),NULL,fbxcol);
00226                         KFbxNode* meshnode = vcgmesh->GetNode();
00227                         if(meshnode == NULL) 
00228                                 return false;
00229                         meshnode->AddMaterial(phong);
00230                         ++zz;
00231                 }
00232                 if (m.textures.size() > 0)
00233                         insertMaterialElementLayer(vcgmesh);
00234 
00235                 int vn = int(m.vert.size());
00236                 int notdeletedvert = m.vn;
00237                 int deletedvert = int(vn - notdeletedvert);
00238                 vcgmesh->InitControlPoints(notdeletedvert);
00239                 std::vector<int> deletedBeforeValid(vn);
00240                 KFbxVector4* controlp = vcgmesh->GetControlPoints();
00241                 int validvert = 0;
00242                 int invalidvert = 0;
00243                 for(int ii = 0;ii < vn;++ii)
00244                 {
00245                         if (!m.vert[ii].IsD())
00246                         {
00247                                 deletedBeforeValid[ii] = invalidvert;
00248                                 vcg::Point3<ScalarType> p = m.vert[ii].P();
00249                                 
00250                                 controlp[validvert] = KFbxVector4(p.X(),p.Y(),p.Z());
00251                                 if (vertcol)
00252                                 {
00253                                         //Paolo imposed the non templetization of color scalar type. Always byte!
00254                                         vcg::Color4b vcgcol = m.vert[ii].C();
00255                                         KFbxColor fbxcol(vcgcol[0] / 255.0f,vcgcol[1] / 255.0f,vcgcol[2] / 255.0f,vcgcol[3] / 255.0f);
00256                                         if (vcolorlay)
00257                                         {
00258                                                 KFbxLayerElementArrayTemplate<KFbxColor>& carr = vcolorlay->GetDirectArray();   
00259                                                 carr.Add(fbxcol);
00260                                         }
00261                                 }
00262 
00263                                 if(vertnorm)
00264                                 {
00265                                         CoordType vcgnorm = m.vert[ii].N();
00266                                         KFbxVector4 fbxnorm(vcgnorm[0],vcgnorm[1],vcgnorm[2]);
00267                                         if (vnormlay)
00268                                         {
00269                                                 KFbxLayerElementArrayTemplate<KFbxVector4>& narr = vnormlay->GetDirectArray();  
00270                                                 narr.Add(fbxnorm);
00271                                         }
00272                                 }
00273                                 ++validvert;
00274                         }
00275                         else
00276                                 ++invalidvert;
00277                 }
00278 
00279                 KFbxGeometryElementUV* uvel = NULL; 
00280                 
00281 
00282                 if (wedgetexcoord)
00283                 {
00284                         uvel = vcgmesh->CreateElementUV("UV");
00285                         uvel->SetMappingMode(KFbxGeometryElement::eBY_POLYGON_VERTEX);
00286                         uvel->SetReferenceMode(KFbxGeometryElement::eINDEX_TO_DIRECT);
00287                 }
00288 
00289                 int validface = 0;
00290                 for(int ii = 0;ii < fn;++ii)
00291                 {
00292                         if (!m.face[ii].IsD())
00293                         {
00294                                 if (wedgetexcoord)
00295                                 {
00296                                         vcg::Color4b facecol;
00297                                         int textind = m.face[ii].WT(0).N();
00298                                         int matind = textind;
00299                                         if ((textind == -1) && vcg::tri::HasPerVertexColor(m))
00300                                         {       
00301                                                 std::set<vcg::Color4b>::iterator it = matset.find(m.face[ii].V(0)->C());
00302                                                 matind = int(std::distance(matset.begin(),it) + m.textures.size());
00303                                         }
00304                                         vcgmesh->BeginPolygon(matind,textind);
00305                                 }
00306                                 else
00307                                         vcgmesh->BeginPolygon();
00308                                 int validvertex = 0;
00309                                 for (int jj = 0;jj < 3;++jj)
00310                                 {
00311                                         
00312                                         if (!m.face[ii].V(jj)->IsD())
00313                                         {
00314                                                 int vi_with_invalid = int(m.face[ii].V(jj) - &(*m.vert.begin()));
00315                                                 int vi = vi_with_invalid - deletedBeforeValid[vi_with_invalid];
00316                                                 vcgmesh->AddPolygon(vi);
00317                                                 if (wedgetexcoord)
00318                                                 {
00319                                                         ScalarType u = m.face[ii].WT(jj).U();
00320                                                         ScalarType v = m.face[ii].WT(jj).V();
00321                                                         
00322                                                         uvel->GetDirectArray().Add(KFbxVector2(u,v));
00323                                                         uvel->GetIndexArray().Add(validface * 3 + validvertex);
00324                                                         ++validvertex;
00325                                                 }
00326                                         }
00327                                 }
00328                                 vcgmesh->EndPolygon();
00329                                 ++validface;
00330                         }
00331                 }
00332                 /*for(std::set<KFbxVector2>::iterator it = indexset.begin();it != indexset.end();++it)
00333                         uvel->GetDirectArray().Add(*it);*/
00334                 
00335                 KFbxNode* root = scene.GetRootNode();
00336                 root->AddChild(meshnode);
00337 
00338                 return true;
00339         }
00340 };
00341 #endif


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