bool SaveScene(FbxManager* pManager, FbxDocument* pScene, const char* pFilename, int pFileFormat = -1, bool pEmbedMedia = false) { int lMajor, lMinor, lRevision; bool lStatus = true; // Create an exporter. FbxExporter* lExporter = FbxExporter::Create(pManager, ""); if (pFileFormat < 0 || pFileFormat >= pManager->GetIOPluginRegistry()->GetWriterFormatCount()) { // Write in fall back format in less no ASCII format found pFileFormat = pManager->GetIOPluginRegistry()->GetNativeWriterFormat(); //Try to export in ASCII if possible int lFormatIndex, lFormatCount = pManager->GetIOPluginRegistry()->GetWriterFormatCount(); for (lFormatIndex = 0; lFormatIndex < lFormatCount; lFormatIndex++) { if (pManager->GetIOPluginRegistry()->WriterIsFBX(lFormatIndex)) { FbxString lDesc = pManager->GetIOPluginRegistry()->GetWriterFormatDescription(lFormatIndex); const char *lASCII = "ascii"; if (lDesc.Find(lASCII) >= 0) { pFileFormat = lFormatIndex; break; } } } } // Set the export states. By default, the export states are always set to // true except for the option eEXPORT_TEXTURE_AS_EMBEDDED. The code below // shows how to change these states. IOSETTING_REF.SetBoolProp(EXP_FBX_MATERIAL, true); IOSETTING_REF.SetBoolProp(EXP_FBX_TEXTURE, true); IOSETTING_REF.SetBoolProp(EXP_FBX_EMBEDDED, pEmbedMedia); IOSETTING_REF.SetBoolProp(EXP_FBX_SHAPE, true); IOSETTING_REF.SetBoolProp(EXP_FBX_GOBO, true); IOSETTING_REF.SetBoolProp(EXP_FBX_ANIMATION, true); IOSETTING_REF.SetBoolProp(EXP_FBX_GLOBAL_SETTINGS, true); // Initialize the exporter by providing a filename. if (lExporter->Initialize(pFilename, pFileFormat, pManager->GetIOSettings()) == false) { printf("Call to FbxExporter::Initialize() failed.\n"); printf("Error returned: %s\n\n", lExporter->GetStatus().GetErrorString()); return false; } FbxManager::GetFileFormatVersion(lMajor, lMinor, lRevision); printf("FBX file format version %d.%d.%d\n\n", lMajor, lMinor, lRevision); // Export the scene. lStatus = lExporter->Export(pScene); // Destroy the exporter. lExporter->Destroy(); return lStatus; }
int ILDLMesh::SaveScene(FbxManager* pManager, FbxDocument* pScene, const char* pFilename, int pFileFormat, bool pEmbedMedia) { int lMajor, lMinor, lRevision; int lStatus = -1; // Create an exporter. FbxExporter* lExporter = FbxExporter::Create(pManager, ""); if( pFileFormat < 0 || pFileFormat >= pManager->GetIOPluginRegistry()->GetWriterFormatCount() ) { // Write in fall back format in less no ASCII format found pFileFormat = pManager->GetIOPluginRegistry()->GetNativeWriterFormat(); //Try to export in ASCII if possible int lFormatIndex, lFormatCount = pManager->GetIOPluginRegistry()->GetWriterFormatCount(); for (lFormatIndex=0; lFormatIndex<lFormatCount; lFormatIndex++) { if (pManager->GetIOPluginRegistry()->WriterIsFBX(lFormatIndex)) { FbxString lDesc =pManager->GetIOPluginRegistry()->GetWriterFormatDescription(lFormatIndex); const char *lASCII = "ascii"; if (lDesc.Find(lASCII)>=0) { pFileFormat = lFormatIndex; break; } } } } // Initialize the exporter by providing a filename. if(lExporter->Initialize(pFilename, pFileFormat, pManager->GetIOSettings()) == false) { //FBXSDK_printf("Call to FbxExporter::Initialize() failed.\n"); //FBXSDK_printf("Error returned: %s\n\n", lExporter->GetStatus().GetErrorString()); return 431; } FbxManager::GetFileFormatVersion(lMajor, lMinor, lRevision); //FBXSDK_printf("FBX file format version %d.%d.%d\n\n", lMajor, lMinor, lRevision); // Export the scene. if ( !lExporter->Export(pScene) ) lStatus = 432; // Destroy the exporter. lExporter->Destroy(); return lStatus; }
/** * 現在のシーンを FBX ファイルに保存する * * @param file_path FBX ファイルパス */ bool FbxFileLoader::save_fbx( const char_t* file_path ) { bool result = false; FbxExporter* exporter = FbxExporter::Create( fbx_manager_, "" ); // if ( exporter->Initialize( boost::filesystem::absolute( file_path ).string().c_str(), -1, fbx_manager_->GetIOSettings() ) ) if ( exporter->Initialize( file_path, -1, fbx_manager_->GetIOSettings() ) ) { result = exporter->Export( fbx_scene_ ); } exporter->Destroy(); return result; }
void GenerateLOD::saveScene(const char *pFilename, FbxManager *pFbxManager, FbxScene *pFbxScene, bool pAsASCII = false) { //Save the scene using the Python FBX API FbxExporter *exporter = FbxExporter::Create(pFbxManager, ""); bool isInitialized; if (pAsASCII) { // DEBUG : Initialize the FbxExporter object to export in ASCII. int asciiFormatIndex = getASCIIFormatIndex(pFbxManager); isInitialized = exporter->Initialize(pFilename, asciiFormatIndex); } else isInitialized = exporter->Initialize(pFilename); exporter->Export(pFbxScene); exporter->Destroy(); }
int main(int argc, char** argv) { if (argc < 2) { printf("Usage: emdfbx model.emd skeleton.esk output.fbx\n Can include multiple emd and esk files into one fbx."); getchar(); return 1; } LibXenoverse::initializeDebuggingLog(); vector<string> model_filenames; vector<string> skeleton_filenames; vector<string> animation_filenames; string export_filename = ""; for (int i = 1; i < argc; i++) { string parameter = ToString(argv[i]); string extension = LibXenoverse::extensionFromFilename(parameter); if (extension == "emd") { model_filenames.push_back(parameter); } if (extension == "esk") { skeleton_filenames.push_back(parameter); } if (extension == "ean") { animation_filenames.push_back(parameter); } if (extension == "fbx") { export_filename = parameter; } } if (!export_filename.size()) { if (model_filenames.size()) { export_filename = model_filenames[0] + ".fbx"; } else if (skeleton_filenames.size()) { export_filename = skeleton_filenames[0] + ".fbx"; } else { export_filename = "Out.fbx"; } } // Create FBX Manager FbxManager *sdk_manager = FbxManager::Create(); FbxIOSettings *ios = FbxIOSettings::Create(sdk_manager, IOSROOT); ios->SetBoolProp(EXP_FBX_EMBEDDED, true); sdk_manager->SetIOSettings(ios); // Create Scene vector<FbxNode *> global_fbx_bones; global_fbx_bones.reserve(300); vector<size_t> global_fbx_bones_index; //TODO find a better way to link skeleton and animations global_fbx_bones_index.reserve(300); vector<FbxAnimCurveNode *> global_fbx_animation; global_fbx_animation.reserve(300); FbxScene *scene = FbxScene::Create(sdk_manager, "EMDFBXScene"); // Load Shaders and convert it to fx file (will be use by fbx). vector<string> shader_names; shader_names.push_back("adam_shader/shader_age_vs.emb"); //must specified vs folloxed by ps shaders shader_names.push_back("adam_shader/shader_age_ps.emb"); shader_names.push_back("adam_shader/shader_default_vs.emb"); shader_names.push_back("adam_shader/shader_default_ps.emb"); bool needs_install_shaders = false; for (size_t i = 0; i < shader_names.size(); i++) { if (!LibXenoverse::fileCheck(shader_names[i])) { needs_install_shaders = true; break; } } if (needs_install_shaders) { printf("Shaders not found. Please use Xenoviewer to prepare shaders in bin folder."); return -1; } for (size_t i = 0; i+1 < shader_names.size(); i+=2) { LibXenoverse::EMB *shader_pack_vs = new LibXenoverse::EMB(); LibXenoverse::EMB *shader_pack_ps = new LibXenoverse::EMB(); if (!shader_pack_vs->load(shader_names[i])) { delete shader_pack_vs; printf("Couldn't load Shader Pack %s. File is either missing, open by another application, or corrupt.", shader_names[i].c_str()); continue; } if (!shader_pack_ps->load(shader_names[i+1])) { delete shader_pack_vs; delete shader_pack_ps; printf("Couldn't load Shader Pack %s. File is either missing, open by another application, or corrupt.", shader_names[i].c_str()); continue; } shader_pack_vs->exportShadersToFx(shader_pack_vs, shader_pack_ps); //convert all shaders in fx file with defaults program parameters (like Ogre's version). } //build FBX skeleton for (size_t i = 0; i < skeleton_filenames.size(); i++) { LibXenoverse::ESK *esk_skeleton = new LibXenoverse::ESK(); esk_skeleton->load(skeleton_filenames[i]); vector<FbxNode *> fbx_bones = esk_skeleton->createFBXSkeleton(scene); for (size_t j = 0; j < fbx_bones.size(); j++) { global_fbx_bones.push_back(fbx_bones[j]); global_fbx_bones_index.push_back(j); //kepp index of bone to link with animations. } } //build FBX animations for (size_t i = 0; i < animation_filenames.size(); i++) { string filename = animation_filenames.at(i); string ean_name = LibXenoverse::nameFromFilenameNoExtension(filename, true); //vector<FbxAnimCurveNode *> global_fbx_animation; LibXenoverse::EAN *animation = new LibXenoverse::EAN(); if (animation->load(filename)) { std::vector<FbxAnimStack *> list_AnimStack; size_t nbAnims = animation->getAnimations().size(); for (size_t j = 0; j < nbAnims; j++) { //we create only one stack and one layer by animation. each will animate all bones of all skeleton. LibXenoverse::EANAnimation *anim_tmp = &(animation->getAnimations().at(j)); FbxAnimStack* lAnimStack = FbxAnimStack::Create(scene, anim_tmp->getName().c_str()); FbxAnimLayer* lAnimLayer = FbxAnimLayer::Create(scene, (anim_tmp->getName() + "_Layer0").c_str()); lAnimStack->AddMember(lAnimLayer); list_AnimStack.push_back(lAnimStack); } size_t k = 0; for (vector<FbxNode *>::iterator it = global_fbx_bones.begin(); it != global_fbx_bones.end(); it++) { vector<FbxAnimCurveNode *> fbx_anim = animation->exportFBXAnimations(scene, list_AnimStack, *it, global_fbx_bones_index.at(k)); for (size_t j = 0; j < fbx_anim.size(); j++) { global_fbx_animation.push_back(fbx_anim[j]); } k++; } } else { delete animation; animation = NULL; } } for (size_t i = 0; i < model_filenames.size(); i++) { string node_name = LibXenoverse::nameFromFilenameNoExtension(model_filenames[i]); string path = model_filenames[i].substr(0, model_filenames[i].size() - LibXenoverse::nameFromFilename(model_filenames[i]).size()); LibXenoverse::EMD *emd_model = new LibXenoverse::EMD(); emd_model->load(model_filenames[i]); // Fill Scene FbxNode *lMeshNode = NULL; // Create Node lMeshNode = FbxNode::Create(scene, node_name.c_str()); lMeshNode->LclTranslation.Set(FbxVector4(0, 0, 0)); lMeshNode->LclScaling.Set(FbxVector4(1, 1, 1)); lMeshNode->LclRotation.Set(FbxVector4(0, 0, 0)); // Create and attach Mesh FbxMesh *lMesh = emd_model->exportFBX(scene, lMeshNode, path); lMeshNode->SetNodeAttribute(lMesh); if (global_fbx_bones.size()) { emd_model->exportFBXSkin(scene, lMesh, global_fbx_bones, lMeshNode->EvaluateGlobalTransform()); } // Add node to scene FbxNode *lRootNode = scene->GetRootNode(); lRootNode->AddChild(lMeshNode); } // Export FBX int lFileFormat = sdk_manager->GetIOPluginRegistry()->GetNativeWriterFormat(); FbxExporter* lExporter = FbxExporter::Create(sdk_manager, ""); bool lExportStatus = lExporter->Initialize(export_filename.c_str(), lFileFormat, sdk_manager->GetIOSettings()); if (!lExportStatus) { printf("Call to FbxExporter::Initialize() failed.\n"); printf("Error returned: %s\n\n", lExporter->GetStatus().GetErrorString()); return 1; } scene->GetGlobalSettings().SetAxisSystem(FbxAxisSystem::eMax); scene->GetGlobalSettings().SetSystemUnit(FbxSystemUnit::m); // Export scene lExporter->Export(scene); lExporter->Destroy(); return 0; }
osgDB::ReaderWriter::WriteResult ReaderWriterFBX::writeNode( const osg::Node& node, const std::string& filename, const Options* options) const { try { std::string ext = osgDB::getLowerCaseFileExtension(filename); if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED; osg::ref_ptr<Options> localOptions = options ? static_cast<Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options; localOptions->getDatabasePathList().push_front(osgDB::getFilePath(filename)); FbxManager* pSdkManager = FbxManager::Create(); if (!pSdkManager) { return WriteResult::ERROR_IN_WRITING_FILE; } CleanUpFbx cleanUpFbx(pSdkManager); pSdkManager->SetIOSettings(FbxIOSettings::Create(pSdkManager, IOSROOT)); bool useFbxRoot = false; if (options) { std::istringstream iss(options->getOptionString()); std::string opt; while (iss >> opt) { if (opt == "Embedded") { pSdkManager->GetIOSettings()->SetBoolProp(EXP_FBX_EMBEDDED, true); } else if (opt == "UseFbxRoot") { useFbxRoot = true; } } } FbxScene* pScene = FbxScene::Create(pSdkManager, ""); pluginfbx::WriterNodeVisitor writerNodeVisitor(pScene, pSdkManager, filename, options, osgDB::getFilePath(node.getName().empty() ? filename : node.getName())); if (useFbxRoot && isBasicRootNode(node)) { // If root node is a simple group, put all elements under the FBX root const osg::Group * osgGroup = node.asGroup(); for (unsigned int child = 0; child < osgGroup->getNumChildren(); ++child) { const_cast<osg::Node *>(osgGroup->getChild(child))->accept(writerNodeVisitor); } } else { // Normal scene const_cast<osg::Node&>(node).accept(writerNodeVisitor); } FbxDocumentInfo* pDocInfo = pScene->GetDocumentInfo(); bool needNewDocInfo = pDocInfo != NULL; if (needNewDocInfo) { pDocInfo = FbxDocumentInfo::Create(pSdkManager, ""); } pDocInfo->LastSaved_ApplicationName.Set(FbxString("OpenSceneGraph")); pDocInfo->LastSaved_ApplicationVersion.Set(FbxString(osgGetVersion())); if (needNewDocInfo) { pScene->SetDocumentInfo(pDocInfo); } FbxExporter* lExporter = FbxExporter::Create(pSdkManager, ""); pScene->GetGlobalSettings().SetAxisSystem(FbxAxisSystem::eOpenGL); // Ensure the directory exists or else the FBX SDK will fail if (!osgDB::makeDirectoryForFile(filename)) { OSG_NOTICE << "Can't create directory for file '" << filename << "'. FBX SDK may fail creating the file." << std::endl; } // The FBX SDK interprets the filename as UTF-8 #ifdef OSG_USE_UTF8_FILENAME const std::string& utf8filename(filename); #else std::string utf8filename(osgDB::convertStringFromCurrentCodePageToUTF8(filename)); #endif if (!lExporter->Initialize(utf8filename.c_str())) { #if FBXSDK_VERSION_MAJOR < 2014 return std::string(lExporter->GetLastErrorString()); #else return std::string(lExporter->GetStatus().GetErrorString()); #endif } if (!lExporter->Export(pScene)) { #if FBXSDK_VERSION_MAJOR < 2014 return std::string(lExporter->GetLastErrorString()); #else return std::string(lExporter->GetStatus().GetErrorString()); #endif } return WriteResult::FILE_SAVED; } catch (const std::string& s) { return s; } catch (const char* s) { return std::string(s); } catch (...) { } return WriteResult::ERROR_IN_WRITING_FILE; }
int main(int argc, char **argv) { #ifndef _DEBUG if (argc != 2) { printf("invalid arg"); return 0; } const char* filename = argv[1]; #else const char* filename = "*****@*****.**"; #endif output.open("output.txt", ios::out | ios::trunc); output2.open("output2.txt", ios::out | ios::trunc); output3.open("output3.txt", ios::out | ios::trunc); if (!output.is_open()) { exit(1); } FbxManager* fm = FbxManager::Create(); FbxIOSettings *ios = FbxIOSettings::Create(fm, IOSROOT); //ios->SetBoolProp(EXP_FBX_ANIMATION, false); ios->SetIntProp(EXP_FBX_COMPRESS_LEVEL, 9); ios->SetAllObjectFlags(true); fm->SetIOSettings(ios); FbxImporter* importer = FbxImporter::Create(fm, ""); if (!importer->Initialize(filename, -1, fm->GetIOSettings())) { printf("error returned : %s\n", importer->GetStatus().GetErrorString()); exit(-1); } FbxScene* scene = FbxScene::Create(fm, "myscene"); importer->Import(scene); importer->Destroy(); output << "some\n"; output << "charcnt : " << scene->GetCharacterCount() << endl << "node cnt : " << scene->GetNodeCount() << endl; int animstackcnt = scene->GetSrcObjectCount<FbxAnimStack>(); output << "animstackcnt : " << animstackcnt << endl; output << "------------" << endl; vector<FbxNode*> removableNodes; for (int i = 0; i < scene->GetNodeCount(); i++) { FbxNode* node = scene->GetNode(i); output << "scene's node " << i << " : " << node->GetName() << ", childcnt : " << node->GetChildCount(); if (node->GetNodeAttribute()) { output <<", att type : " << node->GetNodeAttribute()->GetAttributeType(); if (node->GetNodeAttribute()->GetAttributeType() == FbxNodeAttribute::EType::eMesh) { FbxMesh* mesh = node->GetMesh(); output << ", mem usage : " << mesh->MemoryUsage() << ", deformer cnt : " << mesh->GetDeformerCount(FbxDeformer::EDeformerType::eSkin) << endl; collapseMesh(mesh); FbxSkin* skin = (FbxSkin*) (mesh->GetDeformer(0, FbxDeformer::EDeformerType::eSkin)); if (skin) { for (int cli = 0; cli < skin->GetClusterCount(); cli++) { FbxCluster* cluster = skin->GetCluster(cli); output << "\tcluster no." << cli << " has " << cluster->GetControlPointIndicesCount() << " connected verts" << endl; if (cluster->GetControlPointIndicesCount() == 0) removableNodes.push_back( cluster->GetLink() ); //cluster-> //skin->RemoveCluster(cluster);효과없음 } } if (mesh->IsTriangleMesh()) { output << "\tit's triangle mesh" << endl; } //mesh->RemoveDeformer(0);효과없음 } else output << endl; } else { output << ", att type : none" << endl; } } for (int rni = 0; rni < removableNodes.size(); rni++) { FbxNode* rnd = removableNodes[rni]; if (rnd && rnd->GetNodeAttribute()->GetAttributeType() == FbxNodeAttribute::EType::eSkeleton) { output3 << rnd->GetName() << " node with no vert attached's curve : " << rnd->GetSrcObjectCount<FbxAnimCurve>() << "," << rnd->GetSrcObjectCount<FbxAnimCurveNode>() << endl; } } output << "-----------animinfo" << endl; int cubic = 0, linear = 0, cons = 0; for (int si = 0; si < animstackcnt; si++) { FbxAnimStack* stack = scene->GetSrcObject<FbxAnimStack>(si); for (int i = 0; i < stack->GetMemberCount<FbxAnimLayer>(); i++) { FbxAnimLayer* layer = stack->GetMember<FbxAnimLayer>(i); int curvenodecnt = layer->GetMemberCount<FbxAnimCurveNode>(); int compositcnt = 0; for (int j = 0; j < curvenodecnt; j++) { FbxAnimCurveNode* cnode = layer->GetMember<FbxAnimCurveNode>(j); compositcnt += (cnode->IsComposite() ? 1 : 0); } output << "\tanimstack's layer " << i << " : " << layer->GetName() << ", curve node cnt : " << curvenodecnt << ", composit node cnt : " << compositcnt << endl; vector<FbxAnimCurveNode*> nodes2del; for (int j = 0; j < curvenodecnt; j++) { FbxAnimCurveNode* cnode = layer->GetMember<FbxAnimCurveNode>(j); output << "\t\tcurvenode " << j << " channel cnt : " << cnode->GetChannelsCount() << ", dst obj cnt " << cnode->GetDstObjectCount() << "("; for (int dsti = 0; dsti < cnode->GetDstObjectCount(); dsti++) { output << "," << cnode->GetDstObject(dsti)->GetName(); if (cnode->GetDstObject(dsti)->GetSrcObjectCount() > 0) output << "<" << cnode->GetDstObject(dsti)->GetSrcObjectCount<FbxSkeleton>() << ">"; } output << ")"; FbxTimeSpan interval; if (cnode->GetAnimationInterval(interval)) { output << ", start : " << interval.GetStart().GetTimeString() << ", end : " << interval.GetStop().GetTimeString() << endl; } else { nodes2del.push_back(cnode); output << ", no interval" << endl; } for (int chi = 0; chi < cnode->GetChannelsCount(); chi++) { int curvecnt = cnode->GetCurveCount(chi); output << "\t\t\tchannel." << chi << " curvecnt : " << curvecnt << endl; for (int ci = 0; ci < curvecnt; ci++) { FbxAnimCurve* curve = cnode->GetCurve(chi, ci); int keycnt = curve->KeyGetCount(); output << "\t\t\t\tcurve no." << ci << " : key count : " << keycnt; output2 << "curve " << ci << endl; vector<int> keys2Remove; for (int cki = 0; cki < keycnt; cki++) { FbxAnimCurveKey prevkey, currkey, nextkey; if (cki == 0 || cki == keycnt - 1) continue; currkey = curve->KeyGet(cki); prevkey = curve->KeyGet(cki-1); nextkey = curve->KeyGet(cki + 1); bool keepit = true; output2 << ci << "-" << cki; // keepit = keepTestHorizon(curve, prevkey, currkey, nextkey); // if (keepit) // keepit = slopkeepTest(curve, prevkey, currkey, nextkey); if (!keepit) { if (!(currkey.GetInterpolation() == FbxAnimCurveDef::EInterpolationType::eInterpolationConstant && nextkey.GetInterpolation() != FbxAnimCurveDef::EInterpolationType::eInterpolationConstant)) keys2Remove.push_back(cki); } } for (int kri = keys2Remove.size() - 1; kri >= 0; kri--) { //curve->KeyRemove(keys2Remove[kri]); } output2 << endl; //output << ", cubic:linear:const : " << cubic << ":" << linear << ":" << cons << endl; if (keys2Remove.size() > 0) output << ", " << keys2Remove.size() << " keys removed"; keycnt = curve->KeyGetCount(); } } } //이부분은 별로 효과없음 /* for (int di = 0; di < nodes2del.size(); di++) { layer->RemoveMember(nodes2del[di]); } */ } } output << "cubic:linear:const " << cubic << ":" << linear << ":" << cons << endl; FbxExporter* exporter = FbxExporter::Create(fm, ""); const char* outFBXName = "after.fbx"; bool exportstatus = exporter->Initialize(outFBXName, -1, fm->GetIOSettings()); if (exportstatus == false) { puts("err export fail"); } exporter->Export(scene); exporter->Destroy(); scene->Destroy(); ios->Destroy(); fm->Destroy(); output.close(); output2.close(); output3.close(); return 0; }
osgDB::ReaderWriter::WriteResult ReaderWriterFBX::writeNode( const osg::Node& node, const std::string& filename, const Options* options) const { try { std::string ext = osgDB::getLowerCaseFileExtension(filename); if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED; osg::ref_ptr<Options> localOptions = options ? static_cast<Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options; localOptions->getDatabasePathList().push_front(osgDB::getFilePath(filename)); FbxManager* pSdkManager = FbxManager::Create(); if (!pSdkManager) { return WriteResult::ERROR_IN_WRITING_FILE; } CleanUpFbx cleanUpFbx(pSdkManager); pSdkManager->SetIOSettings(FbxIOSettings::Create(pSdkManager, IOSROOT)); bool useFbxRoot = false; bool ascii(false); std::string exportVersion; if (options) { std::istringstream iss(options->getOptionString()); std::string opt; while (iss >> opt) { if (opt == "Embedded") { pSdkManager->GetIOSettings()->SetBoolProp(EXP_FBX_EMBEDDED, true); } else if (opt == "UseFbxRoot") { useFbxRoot = true; } else if (opt == "FBX-ASCII") { ascii = true; } else if (opt == "FBX-ExportVersion") { iss >> exportVersion; } } } FbxScene* pScene = FbxScene::Create(pSdkManager, ""); if (options) { if (options->getPluginData("FBX-AssetUnitMeter")) { float unit = *static_cast<const float*>(options->getPluginData("FBX-AssetUnitMeter")); FbxSystemUnit kFbxSystemUnit(unit*100); pScene->GetGlobalSettings().SetSystemUnit(kFbxSystemUnit); } } pluginfbx::WriterNodeVisitor writerNodeVisitor(pScene, pSdkManager, filename, options, osgDB::getFilePath(node.getName().empty() ? filename : node.getName())); if (useFbxRoot && isBasicRootNode(node)) { // If root node is a simple group, put all elements under the FBX root const osg::Group * osgGroup = node.asGroup(); for (unsigned int child = 0; child < osgGroup->getNumChildren(); ++child) { const_cast<osg::Node *>(osgGroup->getChild(child))->accept(writerNodeVisitor); } } else { // Normal scene const_cast<osg::Node&>(node).accept(writerNodeVisitor); } FbxDocumentInfo* pDocInfo = pScene->GetDocumentInfo(); bool needNewDocInfo = pDocInfo != NULL; if (needNewDocInfo) { pDocInfo = FbxDocumentInfo::Create(pSdkManager, ""); } pDocInfo->LastSaved_ApplicationName.Set(FbxString("OpenSceneGraph")); pDocInfo->LastSaved_ApplicationVersion.Set(FbxString(osgGetVersion())); if (needNewDocInfo) { pScene->SetDocumentInfo(pDocInfo); } FbxExporter* lExporter = FbxExporter::Create(pSdkManager, ""); pScene->GetGlobalSettings().SetAxisSystem(FbxAxisSystem::eOpenGL); // Ensure the directory exists or else the FBX SDK will fail if (!osgDB::makeDirectoryForFile(filename)) { OSG_NOTICE << "Can't create directory for file '" << filename << "'. FBX SDK may fail creating the file." << std::endl; } // The FBX SDK interprets the filename as UTF-8 #ifdef OSG_USE_UTF8_FILENAME const std::string& utf8filename(filename); #else std::string utf8filename(osgDB::convertStringFromCurrentCodePageToUTF8(filename)); #endif // Output format selection. Here we only handle "recent" FBX, binary or ASCII. // pSdkManager->GetIOPluginRegistry()->GetWriterFormatDescription() / GetReaderFormatCount() gives the following list: //FBX binary (*.fbx) //FBX ascii (*.fbx) //FBX encrypted (*.fbx) //FBX 6.0 binary (*.fbx) //FBX 6.0 ascii (*.fbx) //FBX 6.0 encrypted (*.fbx) //AutoCAD DXF (*.dxf) //Alias OBJ (*.obj) //Collada DAE (*.dae) //Biovision BVH (*.bvh) //Motion Analysis HTR (*.htr) //Motion Analysis TRC (*.trc) //Acclaim ASF (*.asf) int format = ascii ? pSdkManager->GetIOPluginRegistry()->FindWriterIDByDescription("FBX ascii (*.fbx)") : -1; // -1 = Default if (!lExporter->Initialize(utf8filename.c_str(), format)) { #if FBXSDK_VERSION_MAJOR < 2014 return std::string(lExporter->GetLastErrorString()); #else return std::string(lExporter->GetStatus().GetErrorString()); #endif } if (!exportVersion.empty() && !lExporter->SetFileExportVersion(FbxString(exportVersion.c_str()), FbxSceneRenamer::eNone)) { std::stringstream versionsStr; char const * const * versions = lExporter->GetCurrentWritableVersions(); if (versions) for(; *versions; ++versions) versionsStr << " " << *versions; OSG_WARN << "Can't set FBX export version to '" << exportVersion << "'. Using default. Available export versions are:" << versionsStr.str() << std::endl; } if (!lExporter->Export(pScene)) { #if FBXSDK_VERSION_MAJOR < 2014 return std::string(lExporter->GetLastErrorString()); #else return std::string(lExporter->GetStatus().GetErrorString()); #endif } return WriteResult::FILE_SAVED; }