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) { 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; }
HRESULT FBXLoader::loadFBXFile(char* filePath, VertexBuffer** vBuf, IndexBuffer** iBuf, Renderer* renderer, bool centerShift) { if (g_pFbxSdkManager == nullptr) { g_pFbxSdkManager = FbxManager::Create(); FbxIOSettings* pIOsettings = FbxIOSettings::Create(g_pFbxSdkManager, IOSROOT); g_pFbxSdkManager->SetIOSettings(pIOsettings); } this->shiftCenter = centerShift; FbxImporter* pImporter = FbxImporter::Create(g_pFbxSdkManager, ""); FbxScene* pFbxScene = FbxScene::Create(g_pFbxSdkManager, ""); bool bSuccess = pImporter->Initialize(filePath, -1, g_pFbxSdkManager->GetIOSettings()); if (!bSuccess) return E_FAIL; bSuccess = pImporter->Import(pFbxScene); if (!bSuccess) return E_FAIL; FbxAxisSystem sceneAxisSystem = pFbxScene->GetGlobalSettings().GetAxisSystem(); FbxAxisSystem DirectXAxisSystem(FbxAxisSystem::eYAxis, FbxAxisSystem::eParityOdd, FbxAxisSystem::eLeftHanded); if (sceneAxisSystem != DirectXAxisSystem) { DirectXAxisSystem.ConvertScene(pFbxScene); } pImporter->Destroy(); FbxNode* pFbxRootNode = pFbxScene->GetRootNode(); if (pFbxRootNode) { // Check if the getChildCount is > 1 TODO int test = pFbxRootNode->GetChildCount(); for (int i = 0; i < pFbxRootNode->GetChildCount(); i++) { FbxNode* pFbxChildNode = pFbxRootNode->GetChild(i); if (pFbxChildNode->GetNodeAttribute() == NULL) continue; FbxNodeAttribute::EType AttributeType = pFbxChildNode->GetNodeAttribute()->GetAttributeType(); if (AttributeType != FbxNodeAttribute::eMesh) continue; FbxMesh* pMesh = (FbxMesh*)pFbxChildNode->GetNodeAttribute(); int numControlPoints = pMesh->GetControlPointsCount(); bool initial = true; float xMin, yMin, zMin; float xMax, yMax, zMax; float xIn, yIn, zIn; float xCenter, yCenter, zCenter; if (this->shiftCenter){ for (int c = 0; c < numControlPoints; c++) { xIn = (float)pMesh->GetControlPointAt(c).mData[0]; yIn = (float)pMesh->GetControlPointAt(c).mData[1]; zIn = (float)pMesh->GetControlPointAt(c).mData[2]; if (initial) { xMin = xIn; yMin = yIn; zMin = zIn; xMax = xIn; yMax = yIn; zMax = zIn; initial = false; } else { if (xIn < xMin) { xMin = xIn; } if (yIn < yMin) { yMin = yIn; } if (zIn < zMin) { zMin = zIn; } if (xIn > xMax) { xMax = xIn; } if (yIn > yMax) { yMax = yIn; } if (zIn > zMax) { zMax = zIn; } } } xCenter = (xMin + xMax) / 2.0f; yCenter = (yMin + yMax) / 2.0f; zCenter = (zMin + zMax) / 2.0f; } else { xCenter = 0; yCenter = 0; zCenter = 0; } FbxVector4* pVertices = pMesh->GetControlPoints(); int vertexCount = pMesh->GetPolygonVertexCount(); //Vertex vertex; Vertex* vertexArray = new Vertex[vertexCount]; //Vertex vertexArray[2592]; int numIndices = vertexCount; unsigned int* indexArray = new unsigned int[numIndices]; FbxVector4 fbxNorm(0, 0, 0, 0); FbxVector2 fbxUV(0, 0); bool isMapped; int vertexIndex = 0; // Loop iterates through the polygons and fills the vertex and index arrays for the buffers for (int j = 0; j < pMesh->GetPolygonCount(); j++) { int iNumVertices = pMesh->GetPolygonSize(j); assert(iNumVertices == 3); //1st vertex int controlIndex = pMesh->GetPolygonVertex(j, 2); pMesh->GetPolygonVertexUV(j, 2, "map1", fbxUV, isMapped); pMesh->GetPolygonVertexNormal(j, 2, fbxNorm); vertexArray[vertexIndex].point[0] = (float)pVertices[controlIndex].mData[0] - xCenter; vertexArray[vertexIndex].point[1] = (float)pVertices[controlIndex].mData[1] - yCenter; vertexArray[vertexIndex].point[2] = -(float)pVertices[controlIndex].mData[2] - zCenter; vertexArray[vertexIndex].texCoord[0] = (float)fbxUV[0]; vertexArray[vertexIndex].texCoord[1] = 1.0f - (float)fbxUV[1]; vertexArray[vertexIndex].normal[0] = (float)fbxNorm[0]; vertexArray[vertexIndex].normal[1] = (float)fbxNorm[1]; vertexArray[vertexIndex].normal[2] = -(float)fbxNorm[2]; indexArray[vertexIndex] = vertexIndex; vertexIndex++; //2nd vertex controlIndex = pMesh->GetPolygonVertex(j, 1); pMesh->GetPolygonVertexUV(j, 1, "map1", fbxUV, isMapped); pMesh->GetPolygonVertexNormal(j, 1, fbxNorm); vertexArray[vertexIndex].point[0] = (float)pVertices[controlIndex].mData[0] - xCenter; vertexArray[vertexIndex].point[1] = (float)pVertices[controlIndex].mData[1] - yCenter; vertexArray[vertexIndex].point[2] = -(float)pVertices[controlIndex].mData[2] - zCenter; vertexArray[vertexIndex].texCoord[0] = (float)fbxUV[0]; vertexArray[vertexIndex].texCoord[1] = 1.0f - (float)fbxUV[1]; vertexArray[vertexIndex].normal[0] = (float)fbxNorm[0]; vertexArray[vertexIndex].normal[1] = (float)fbxNorm[1]; vertexArray[vertexIndex].normal[2] = -(float)fbxNorm[2]; indexArray[vertexIndex] = vertexIndex; vertexIndex++; //3rd vertex controlIndex = pMesh->GetPolygonVertex(j, 0); pMesh->GetPolygonVertexUV(j, 0, "map1", fbxUV, isMapped); pMesh->GetPolygonVertexNormal(j, 0, fbxNorm); vertexArray[vertexIndex].point[0] = (float)pVertices[controlIndex].mData[0] - xCenter; vertexArray[vertexIndex].point[1] = (float)pVertices[controlIndex].mData[1] - yCenter; vertexArray[vertexIndex].point[2] = -(float)pVertices[controlIndex].mData[2] - zCenter; vertexArray[vertexIndex].texCoord[0] = (float)fbxUV[0]; vertexArray[vertexIndex].texCoord[1] = 1.0f - (float)fbxUV[1]; vertexArray[vertexIndex].normal[0] = (float)fbxNorm[0]; vertexArray[vertexIndex].normal[1] = (float)fbxNorm[1]; vertexArray[vertexIndex].normal[2] = -(float)fbxNorm[2]; indexArray[vertexIndex] = vertexIndex; vertexIndex++; } // Generate vertex and index buffers from the vertex and index arrays *vBuf = renderer->createVertexBuffer(vertexArray, vertexCount); *iBuf = renderer->createIndexBuffer(indexArray, numIndices); delete[] vertexArray; delete[] indexArray; } } return S_OK; }
osgDB::ReaderWriter::ReadResult ReaderWriterFBX::readNode(const std::string& filenameInit, const Options* options) const { try { std::string ext(osgDB::getLowerCaseFileExtension(filenameInit)); if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; std::string filename(osgDB::findDataFile(filenameInit, options)); if (filename.empty()) return ReadResult::FILE_NOT_FOUND; FbxManager* pSdkManager = FbxManager::Create(); if (!pSdkManager) { return ReadResult::ERROR_IN_READING_FILE; } CleanUpFbx cleanUpFbx(pSdkManager); pSdkManager->SetIOSettings(FbxIOSettings::Create(pSdkManager, IOSROOT)); FbxScene* pScene = FbxScene::Create(pSdkManager, ""); // 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 FbxImporter* lImporter = FbxImporter::Create(pSdkManager, ""); if (!lImporter->Initialize(utf8filename.c_str(), -1, pSdkManager->GetIOSettings())) { #if FBXSDK_VERSION_MAJOR < 2014 return std::string(lImporter->GetLastErrorString()); #else return std::string(lImporter->GetStatus().GetErrorString()); #endif } if (!lImporter->IsFBX()) { return ReadResult::ERROR_IN_READING_FILE; } for (int i = 0; FbxTakeInfo* lTakeInfo = lImporter->GetTakeInfo(i); i++) { lTakeInfo->mSelect = true; } if (!lImporter->Import(pScene)) { #if FBXSDK_VERSION_MAJOR < 2014 return std::string(lImporter->GetLastErrorString()); #else return std::string(lImporter->GetStatus().GetErrorString()); #endif } //FbxAxisSystem::OpenGL.ConvertScene(pScene); // Doesn't work as expected. Still need to transform vertices. if (FbxNode* pNode = pScene->GetRootNode()) { bool useFbxRoot = false; bool lightmapTextures = false; bool tessellatePolygons = false; if (options) { std::istringstream iss(options->getOptionString()); std::string opt; while (iss >> opt) { if (opt == "UseFbxRoot") { useFbxRoot = true; } if (opt == "LightmapTextures") { lightmapTextures = true; } if (opt == "TessellatePolygons") { tessellatePolygons = true; } } } bool bIsBone = false; int nLightCount = 0; osg::ref_ptr<Options> localOptions = NULL; if (options) localOptions = options->cloneOptions(); else localOptions = new osgDB::Options(); localOptions->setObjectCacheHint(osgDB::ReaderWriter::Options::CACHE_IMAGES); std::string filePath = osgDB::getFilePath(filename); FbxMaterialToOsgStateSet fbxMaterialToOsgStateSet(filePath, localOptions.get(), lightmapTextures); std::set<const FbxNode*> fbxSkeletons; findLinkedFbxSkeletonNodes(pNode, fbxSkeletons); OsgFbxReader::AuthoringTool authoringTool = OsgFbxReader::UNKNOWN; if (FbxDocumentInfo* pDocInfo = pScene->GetDocumentInfo()) { struct ToolName { const char* name; OsgFbxReader::AuthoringTool tool; }; ToolName authoringTools[] = { {"OpenSceneGraph", OsgFbxReader::OPENSCENEGRAPH}, {"3ds Max", OsgFbxReader::AUTODESK_3DSTUDIO_MAX} }; FbxString appName = pDocInfo->LastSaved_ApplicationName.Get(); for (unsigned int i = 0; i < sizeof(authoringTools) / sizeof(authoringTools[0]); ++i) { if (0 == #ifdef WIN32 _strnicmp #else strncasecmp #endif (appName, authoringTools[i].name, strlen(authoringTools[i].name))) { authoringTool = authoringTools[i].tool; break; } } } OsgFbxReader reader(*pSdkManager, *pScene, fbxMaterialToOsgStateSet, fbxSkeletons, *localOptions, authoringTool, lightmapTextures, tessellatePolygons); ReadResult res = reader.readFbxNode(pNode, bIsBone, nLightCount); if (res.success()) { fbxMaterialToOsgStateSet.checkInvertTransparency(); resolveBindMatrices(*res.getNode(), reader.boneBindMatrices, reader.nodeMap); osg::Node* osgNode = res.getNode(); osgNode->getOrCreateStateSet()->setMode(GL_RESCALE_NORMAL,osg::StateAttribute::ON); osgNode->getOrCreateStateSet()->setMode(GL_NORMALIZE,osg::StateAttribute::ON); if (reader.pAnimationManager.valid()) { if (osgNode->getUpdateCallback()) { osg::Group* osgGroup = new osg::Group; osgGroup->addChild(osgNode); osgNode = osgGroup; } //because the animations may be altered after registering reader.pAnimationManager->buildTargetReference(); osgNode->setUpdateCallback(reader.pAnimationManager.get()); } FbxAxisSystem fbxAxis = pScene->GetGlobalSettings().GetAxisSystem(); if (fbxAxis != FbxAxisSystem::OpenGL) { int upSign; FbxAxisSystem::EUpVector eUp = fbxAxis.GetUpVector(upSign); bool bLeftHanded = fbxAxis.GetCoorSystem() == FbxAxisSystem::eLeftHanded; float fSign = upSign < 0 ? -1.0f : 1.0f; float zScale = bLeftHanded ? -1.0f : 1.0f; osg::Matrix mat; switch (eUp) { case FbxAxisSystem::eXAxis: mat.set(0,fSign,0,0,-fSign,0,0,0,0,0,zScale,0,0,0,0,1); break; case FbxAxisSystem::eYAxis: mat.set(1,0,0,0,0,fSign,0,0,0,0,fSign*zScale,0,0,0,0,1); break; case FbxAxisSystem::eZAxis: mat.set(1,0,0,0,0,0,-fSign*zScale,0,0,fSign,0,0,0,0,0,1); break; } osg::Transform* pTransformTemp = osgNode->asTransform(); osg::MatrixTransform* pMatrixTransform = pTransformTemp ? pTransformTemp->asMatrixTransform() : NULL; if (pMatrixTransform) { pMatrixTransform->setMatrix(pMatrixTransform->getMatrix() * mat); } else { pMatrixTransform = new osg::MatrixTransform(mat); if (useFbxRoot && isBasicRootNode(*osgNode)) { // If root node is a simple group, put all FBX elements under the OSG root osg::Group* osgGroup = osgNode->asGroup(); for(unsigned int i = 0; i < osgGroup->getNumChildren(); ++i) { pMatrixTransform->addChild(osgGroup->getChild(i)); } pMatrixTransform->setName(osgGroup->getName()); } else { pMatrixTransform->addChild(osgNode); } } osgNode = pMatrixTransform; } osgNode->setName(filenameInit); return osgNode; } } } catch (...) { OSG_WARN << "Exception thrown while importing \"" << filenameInit << '\"' << std::endl; } return ReadResult::ERROR_IN_READING_FILE; }
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; }
void LoadMeshes(Scene* pScene, std::vector<uint32_t>* loadedMeshIDs) { FbxManager* fbxManager = FbxManager::Create(); FbxIOSettings* pFbxIOSettings = FbxIOSettings::Create(fbxManager, IOSROOT); fbxManager->SetIOSettings(pFbxIOSettings); (*(fbxManager->GetIOSettings())).SetBoolProp(IMP_FBX_MATERIAL, true); (*(fbxManager->GetIOSettings())).SetBoolProp(IMP_FBX_TEXTURE, true); (*(fbxManager->GetIOSettings())).SetBoolProp(IMP_FBX_LINK, false); (*(fbxManager->GetIOSettings())).SetBoolProp(IMP_FBX_SHAPE, false); (*(fbxManager->GetIOSettings())).SetBoolProp(IMP_FBX_GOBO, false); (*(fbxManager->GetIOSettings())).SetBoolProp(IMP_FBX_ANIMATION, true); (*(fbxManager->GetIOSettings())).SetBoolProp(IMP_FBX_GLOBAL_SETTINGS, true); bool bEmbedMedia = true; (*(fbxManager->GetIOSettings())).SetBoolProp(EXP_FBX_MATERIAL, true); (*(fbxManager->GetIOSettings())).SetBoolProp(EXP_FBX_TEXTURE, true); (*(fbxManager->GetIOSettings())).SetBoolProp(EXP_FBX_EMBEDDED, bEmbedMedia); (*(fbxManager->GetIOSettings())).SetBoolProp(EXP_FBX_SHAPE, true); (*(fbxManager->GetIOSettings())).SetBoolProp(EXP_FBX_GOBO, true); (*(fbxManager->GetIOSettings())).SetBoolProp(EXP_FBX_ANIMATION, true); (*(fbxManager->GetIOSettings())).SetBoolProp(EXP_FBX_GLOBAL_SETTINGS, true); FbxImporter* pFbxImporter = FbxImporter::Create(fbxManager, ""); // Initialize the importer. bool result = pFbxImporter->Initialize(pScene->loadPath.c_str(), -1, fbxManager->GetIOSettings()); if (!result) { printf("Get error when init FBX Importer: %s\n\n", pFbxImporter->GetStatus().GetErrorString()); exit(-1); } // fbx version number int major, minor, revision; pFbxImporter->GetFileVersion(major, minor, revision); // import pFbxScene FbxScene* pFbxScene = FbxScene::Create(fbxManager, "myScene"); pFbxImporter->Import(pFbxScene); pFbxImporter->Destroy(); pFbxImporter = nullptr; // check axis system FbxAxisSystem axisSystem = pFbxScene->GetGlobalSettings().GetAxisSystem(); FbxAxisSystem vulkanAxisSystem(FbxAxisSystem::eYAxis, FbxAxisSystem::eParityOdd, FbxAxisSystem::eRightHanded); if (axisSystem != vulkanAxisSystem) { axisSystem.ConvertScene(pFbxScene); } // check unit system FbxSystemUnit systemUnit = pFbxScene->GetGlobalSettings().GetSystemUnit(); if (systemUnit.GetScaleFactor() != 1.0) { FbxSystemUnit::cm.ConvertScene(pFbxScene); } // Triangulate Mesh FbxGeometryConverter fbxGeometryConverter(fbxManager); fbxGeometryConverter.Triangulate(pFbxScene, true); // Load Texture int textureCount = pFbxScene->GetTextureCount(); for (int i = 0; i < textureCount; ++i) { FbxTexture* pFbxTexture = pFbxScene->GetTexture(i); FbxFileTexture* pFbxFileTexture = FbxCast<FbxFileTexture>(pFbxTexture); if (pFbxTexture && pFbxFileTexture->GetUserDataPtr()) { } } LoadMeshes(pFbxScene->GetRootNode(), pScene->meshes); }
CGeometryComponent * CModelLoader::loadFbxModelFromFile(ID3D10Device *pDevice,const string& filename) { CGeometryComponent * pRenderable=NULL; FbxManager* lSdkManager = FbxManager::Create(); FbxIOSettings *ios = FbxIOSettings::Create(lSdkManager, IOSROOT); lSdkManager->SetIOSettings(ios); // Create an importer using our sdk manager. FbxImporter* lImporter = FbxImporter::Create(lSdkManager,""); //Sean: uncomment back to this when you compile, I am using the latest version of fbx SDK //KFbxGeometryConverter converter( lSdkManager); //Sean: has comment out the line below FbxGeometryConverter converter( lSdkManager); // Use the first argument as the filename for the importer. if(!lImporter->Initialize(filename.c_str(), -1, lSdkManager->GetIOSettings())) { return NULL; } // Create a new scene so it can be populated by the imported file. FbxScene* lScene = FbxScene::Create(lSdkManager,"myScene"); FbxAxisSystem SceneAxisSystem = lScene->GetGlobalSettings().GetAxisSystem(); //FbxAxisSystem::DirectX.ConvertScene( lScene ); INT iUpAxisSign; //Sean: Uncomment this below //KFbxAxisSystem::eUpVector UpVector = SceneAxisSystem.GetUpVector( iUpAxisSign ); //Sean: and comment this out FbxAxisSystem::EUpVector UpVector = SceneAxisSystem.GetUpVector( iUpAxisSign ); // Import the contents of the file into the scene. lImporter->Import(lScene); // The file has been imported; we can get rid of the importer. lImporter->Destroy(); FbxNode* lRootNode = lScene->GetRootNode(); FbxMesh * pMesh=NULL; if(lRootNode) { for (int i=0;i<lRootNode->GetChildCount();i++){ FbxNode * modelNode=lRootNode->GetChild(i); for(int i=0;i<modelNode->GetNodeAttributeCount();i++) { FbxNodeAttribute *pAttributeNode=modelNode->GetNodeAttributeByIndex(i); //Sean: Uncomment this //if (pAttributeNode->GetAttributeType()==KFbxNodeAttribute::eMESH) //Sean Comment this out if (pAttributeNode->GetAttributeType()==FbxNodeAttribute::eMesh) { //found mesh pMesh=(FbxMesh*)pAttributeNode; break; } } } if (pMesh) { pMesh=converter.TriangulateMesh(pMesh); FbxVector4 * verts=pMesh->GetControlPoints(); int noVerts=pMesh->GetControlPointsCount(); int noIndices=pMesh->GetPolygonVertexCount(); int *pIndices=pMesh->GetPolygonVertices(); Vertex * pVerts=new Vertex[noVerts]; for(int i=0;i<noVerts;i++) { pVerts[i].Pos.x=verts[i][0]; pVerts[i].Pos.y=verts[i][1]; pVerts[i].Pos.z=verts[i][2]; } for (int iPolygon = 0; iPolygon < pMesh->GetPolygonCount(); iPolygon++) { for (unsigned iPolygonVertex = 0; iPolygonVertex < 3; iPolygonVertex++) { int fbxCornerIndex = pMesh->GetPolygonVertex(iPolygon, iPolygonVertex); FbxVector4 fbxVertex = verts[fbxCornerIndex]; FbxVector4 fbxNormal; pMesh->GetPolygonVertexNormal(iPolygon, iPolygonVertex, fbxNormal); fbxNormal.Normalize(); //pVerts[fbxCornerIndex].Normal=D3DXVECTOR3(fbxNormal[0],fbxNormal[1],fbxNormal[2]); FbxVector2 fbxUV = FbxVector2(0.0, 0.0); FbxLayerElementUV* fbxLayerUV = pMesh->GetLayer(0)->GetUVs(); // Get texture coordinate if (fbxLayerUV) { int iUVIndex = 0; switch (fbxLayerUV->GetMappingMode()) { //Sean Uncomment this //case KFbxLayerElement::eBY_CONTROL_POINT: //Sean comment the line below out case FbxLayerElement::eByControlPoint: iUVIndex = fbxCornerIndex; break; //Sean Uncomment this //case KFbxLayerElement::eBY_POLYGON_VERTEX: //Sean comment the line below out case FbxLayerElement::eByPolygonVertex: //Sean Uncomment this //iUVIndex = pMesh->GetTextureUVIndex(iPolygon, iPolygonVertex, KFbxLayerElement::eDIFFUSE_TEXTURES); //Sean comment this out iUVIndex = pMesh->GetTextureUVIndex(iPolygon, iPolygonVertex, FbxLayerElement::eTextureDiffuse); break; } fbxUV = fbxLayerUV->GetDirectArray().GetAt(iUVIndex); //pVerts[fbxCornerIndex].TextureCoords.x=fbxUV[0]; //pVerts[fbxCornerIndex].TextureCoords.y= 1.0f-fbxUV[1]; } } } pRenderable=new CGeometryComponent(); for (int i=0;i<noVerts;i++) { pRenderable->addVertex(pVerts[i]); } for (int i=0;i<noIndices;i++) { pRenderable->addIndex(pIndices[i]); } //pRenderable->create<TexturedLitVertex>(pDevice,noVerts,noIndices,pVerts,(UINT*)pIndices); if (pVerts) { delete [] pVerts; pVerts=NULL; } //} } } lSdkManager->Destroy(); return pRenderable; }
void GeometryLoaderDX11::loadFBXFile( std::string szFilename, std::vector<GeometryPtr>& vGeomVector, std::vector<std::string>& vNames ) { FileSystem fs; szFilename = fs.GetModelsFolderS() + szFilename; pFBXManager = FbxManager::Create(); if( !pFBXManager ) Log::Get().Write( L"CGeometryLoader11.cpp: Error creating FBX Manager!" ); FbxIOSettings* pIOS = FbxIOSettings::Create( pFBXManager, IOSROOT ); pFBXManager->SetIOSettings( pIOS ); FbxString lPath = FbxGetApplicationDirectory(); pFBXManager->LoadPluginsDirectory( lPath.Buffer() ); FbxScene* pScene = FbxScene::Create( pFBXManager, "" ); int /*nFileMajor,*/ nFileMinor, nFileRevision; int nSDKMajor, nSDKMinor, nSDKRevision; int i, /*nAnimationStack,*/ lFileFormat; // bool bStatus; // char szPassword[1024]; FbxManager::GetFileFormatVersion( nSDKMajor, nSDKMinor, nSDKRevision ); FbxImporter* pImporter = FbxImporter::Create( pFBXManager, "" ); if (!pFBXManager->GetIOPluginRegistry()->DetectReaderFileFormat(szFilename.c_str(), lFileFormat) ) { // Unrecognizable file format. Try to fall back to FbxImporter::eFBX_BINARY lFileFormat = pFBXManager->GetIOPluginRegistry()->FindReaderIDByDescription( "FBX binary (*.fbx)" );; } bool ImportStatus = pImporter->Initialize( szFilename.c_str(), lFileFormat, pFBXManager->GetIOSettings() ); pImporter->GetFileVersion( nFileMinor, nFileMinor, nFileRevision ); if( !ImportStatus ) { Log::Get().Write( L"CGeometryLoader11.cpp: FbxImporter Initialize failed!" ); return; } ImportStatus = pImporter->Import( pScene ); if( !ImportStatus ) { Log::Get().Write( L"CGeometryLoader11.cpp: FbxImporter failed to import the file to the scene!" ); return; } FbxAxisSystem SceneAxisSystem = pScene->GetGlobalSettings().GetAxisSystem(); FbxAxisSystem AxisSystem( FbxAxisSystem::eYAxis, FbxAxisSystem::eParityOdd, FbxAxisSystem::eLeftHanded ); if( SceneAxisSystem != AxisSystem ) { AxisSystem.ConvertScene( pScene ); } //FbxSystemUnit SceneSystemUnit = pScene->GetGlobalSettings().GetSystemUnit(); //if( SceneSystemUnit.GetScaleFactor() != 1.0f ) // FbxSystemUnit::cm.ConvertScene( pScene ); FBXTriangulateRecursive( pScene->GetRootNode() ); FbxArray<FbxMesh*> vMeshs; FBXFillMeshArray( pScene, vMeshs ); unsigned short usVertexCount = 0; unsigned short usTriangleCount = 0; unsigned short usGroupCount = 0; unsigned short usMaterialCount = 0; unsigned short usIndicesCount = 0; for( i = 0; i < vMeshs.GetCount(); i++ ) { Log::Get().Write( L"CGeometryLoader11.cpp: Loading File!" ); std::string name = vMeshs[i]->GetNode()->GetName(); vNames.push_back( name ); usVertexCount = vMeshs[i]->GetControlPointsCount(); if( usVertexCount == 0 ) continue; usTriangleCount = vMeshs[i]->GetPolygonVertexCount() / 3; usIndicesCount = vMeshs[i]->GetPolygonVertexCount(); VertexElementDX11* pPositions = new VertexElementDX11( 3, usTriangleCount * 3 ); pPositions->m_SemanticName = VertexElementDX11::PositionSemantic; pPositions->m_uiSemanticIndex = 0; pPositions->m_Format = DXGI_FORMAT_R32G32B32_FLOAT; pPositions->m_uiInputSlot = 0; pPositions->m_uiAlignedByteOffset = 0; pPositions->m_InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; pPositions->m_uiInstanceDataStepRate = 0; VertexElementDX11* pTexCoords = new VertexElementDX11( 2, usTriangleCount * 3 ); pTexCoords->m_SemanticName = VertexElementDX11::TexCoordSemantic; pTexCoords->m_uiSemanticIndex = 0; pTexCoords->m_Format = DXGI_FORMAT_R32G32_FLOAT; pTexCoords->m_uiInputSlot = 0; pTexCoords->m_uiAlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; pTexCoords->m_InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; pTexCoords->m_uiInstanceDataStepRate = 0; VertexElementDX11* pNormals = new VertexElementDX11( 3, usTriangleCount * 3 ); pNormals->m_SemanticName = VertexElementDX11::NormalSemantic; pNormals->m_uiSemanticIndex = 0; pNormals->m_Format = DXGI_FORMAT_R32G32B32_FLOAT; pNormals->m_uiInputSlot = 0; pNormals->m_uiAlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; pNormals->m_InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; pNormals->m_uiInstanceDataStepRate = 0; Vector3f* pPos = pPositions->Get3f(0); Vector3f* pNorm = pNormals->Get3f(0); Vector2f* pTex = pTexCoords->Get2f(0); FbxVector4* pFBXVerts = new FbxVector4[usVertexCount]; memcpy( pFBXVerts, vMeshs[i]->GetControlPoints(), usVertexCount * sizeof(FbxVector4)); TriangleIndices face; GeometryPtr pGeomPointer( new GeometryDX11() ); for( int j = 0; j < usTriangleCount; j++ ) { int nIndex = 0; FbxVector4 FBXNorm( 0, 0, 0, 0 ); FbxVector2 FBXUV( 0, 0 ); face.P1() = nIndex = vMeshs[i]->GetPolygonVertex( j, 0 ); pPos[nIndex].x = (float)pFBXVerts[ nIndex ][0]; pPos[nIndex].y = (float)pFBXVerts[ nIndex ][1]; pPos[nIndex].z = (float)pFBXVerts[ nIndex ][2]; vMeshs[i]->GetPolygonVertexNormal( j, 0, FBXNorm ); pNorm[nIndex].x = (float)FBXNorm[0]; pNorm[nIndex].y = (float)FBXNorm[1]; pNorm[nIndex].z = (float)FBXNorm[2]; vMeshs[i]->GetPolygonVertexUV( j, 0, "map1", FBXUV ); pTex[nIndex].x = (float)FBXUV[0]; pTex[nIndex].y = (float)FBXUV[1]; face.P2() = nIndex = vMeshs[i]->GetPolygonVertex( j, 1 ); pPos[nIndex].x = (float)pFBXVerts[ nIndex ][0]; pPos[nIndex].y = (float)pFBXVerts[ nIndex ][1]; pPos[nIndex].z = (float)pFBXVerts[ nIndex ][2]; vMeshs[i]->GetPolygonVertexNormal( j, 1, FBXNorm ); pNorm[nIndex].x = (float)FBXNorm[0]; pNorm[nIndex].y = (float)FBXNorm[1]; pNorm[nIndex].z = (float)FBXNorm[2]; vMeshs[i]->GetPolygonVertexUV( j, 1, "map1", FBXUV ); pTex[nIndex].x = (float)FBXUV[0]; pTex[nIndex].y = (float)FBXUV[1]; face.P3() = nIndex = vMeshs[i]->GetPolygonVertex( j, 2 ); pPos[nIndex].x = (float)pFBXVerts[ nIndex ][0]; pPos[nIndex].y = (float)pFBXVerts[ nIndex ][1]; pPos[nIndex].z = (float)pFBXVerts[ nIndex ][2]; vMeshs[i]->GetPolygonVertexNormal( j, 2, FBXNorm ); pNorm[nIndex].x = (float)FBXNorm[0]; pNorm[nIndex].y = (float)FBXNorm[1]; pNorm[nIndex].z = (float)FBXNorm[2]; vMeshs[i]->GetPolygonVertexUV( j, 2, "map1", FBXUV ); pTex[nIndex].x = (float)FBXUV[0]; pTex[nIndex].y = (float)FBXUV[1]; pGeomPointer->AddFace( face ); } for( int j = 0; j < usVertexCount; j++ ) { pNorm[j].Normalize(); } pGeomPointer->AddElement( pPositions ); pGeomPointer->AddElement( pNormals ); pGeomPointer->AddElement( pTexCoords ); delete[] pFBXVerts; vGeomVector.push_back( pGeomPointer ); vMeshs[i]->Destroy(); vMeshs[i] = NULL; } pImporter->Destroy(); pImporter = NULL; pScene->Destroy(); pScene = NULL; pIOS->Destroy(); pIOS = NULL; pFBXManager->Destroy(); pFBXManager = NULL; }
boost::shared_ptr<FBXScene> FBXManager::loadScene(const std::string& filename) { PROFILE; FbxImporter* importer = nullptr; FbxScene* scene = nullptr; std::string pathAbs; std::string pathRel; pathRel = m_pFilesystem->resourcePathRel(Filesystem::ResourceType::Fbx, filename); pathAbs = m_pFilesystem->resourcePathAbs(Filesystem::ResourceType::Fbx, filename); if (pathAbs.empty()) { return boost::shared_ptr<FBXScene>(); } LOGI << "Loading FBX file '" << pathRel << "'.."; importer = FbxImporter::Create(m_pFbxManager,""); if(!importer->Initialize(pathAbs.c_str(), -1, m_pFbxManager->GetIOSettings())) { LOGE << "FbxImporter initialization for failed with " << importer->GetStatus().GetErrorString(); return false; } scene = FbxScene::Create(m_pFbxManager, filename.c_str()); if(!scene) { LOGE << "Unable to create a FbxScene"; return boost::shared_ptr<FBXScene>(); } if (!importer->Import(scene)) { LOGE << "Failed to import scene '" << filename << "'"; return boost::shared_ptr<FBXScene>(); } // Convert Axis System if needed FbxAxisSystem sceneAxisSystem = scene->GetGlobalSettings().GetAxisSystem(); FbxAxisSystem axisSystem(FbxAxisSystem::eYAxis, FbxAxisSystem::eParityOdd, FbxAxisSystem::eRightHanded); if(sceneAxisSystem != axisSystem) { LOGW << "Scene needed axis convertion"; axisSystem.ConvertScene(scene); } //// Convert Unit System if needed //FbxSystemUnit sceneSystemUnit = scene->GetGlobalSettings().GetSystemUnit(); //if(sceneSystemUnit.GetScaleFactor() != 1.0) //{ // LOGW << "Scene needed unit convertion"; // FbxSystemUnit::cm.ConvertScene(scene); //} // Convert fbxMesh, NURBS and patch into triangle fbxMesh FbxGeometryConverter geomConverter(m_pFbxManager); geomConverter.Triangulate(scene, true); // Split meshes per material, so that we only have one material per fbxMesh (for VBO support) geomConverter.SplitMeshesPerMaterial(scene, true); importer->Destroy(); return boost::shared_ptr<FBXScene>(new FBXScene(scene, m_pDatabase)); }