SceneObject *FBXLoader::Load(const char *filename){ SceneObject *so = NULL; KFbxScene *scene = KFbxScene::Create(manager, ""); KFbxImporter *importer = KFbxImporter::Create(manager, ""); int fileFormat = -1; const bool fileFormatFound = manager->GetIOPluginRegistry()->DetectReaderFileFormat(filename, fileFormat); if (fileFormatFound) { bool initSuccess = importer->Initialize(filename, fileFormat); if (initSuccess) { bool importSuccess = importer->Import(scene); if (importSuccess) { KFbxNode *node = scene->GetRootNode(); so = parseNode(node); } else { stringstream ss; ss<<"ModelLoad import error "<<importer->GetLastErrorString(); ERROR(ss.str()); } } else { stringstream ss; ss<<"ModelLoad init importer error "<<importer->GetLastErrorString(); ERROR(ss.str()); } } importer->Destroy(); scene->Destroy(); return so; }
std::string readFbxAnimation(KFbxNode* pNode, KFbxScene& fbxScene, osg::ref_ptr<osgAnimation::AnimationManagerBase>& pAnimManager, const char* targetName) { std::string result; for (int i = 0; i < fbxScene.GetSrcObjectCount(FBX_TYPE(KFbxAnimStack)); ++i) { KFbxAnimStack* pAnimStack = KFbxCast<KFbxAnimStack>(fbxScene.GetSrcObject(FBX_TYPE(KFbxAnimStack), i)); int nbAnimLayers = pAnimStack->GetMemberCount(FBX_TYPE(KFbxAnimLayer)); const char* pTakeName = pAnimStack->GetName(); if (!pTakeName || !*pTakeName) continue; for (int j = 0; j < nbAnimLayers; j++) { KFbxAnimLayer* pAnimLayer = pAnimStack->GetMember(FBX_TYPE(KFbxAnimLayer), j); if (osgAnimation::Animation* pAnimation = readFbxAnimation( pNode, pAnimLayer, pTakeName, targetName, pAnimManager)) { result = targetName; } } } return result; }
void FBXJSONSerializer::serialize(const std::string& input_filename, const std::string& output_filename) { KFbxSdkManager* manager = KFbxSdkManager::Create(); KFbxIOSettings* ios = KFbxIOSettings::Create(manager, IOSROOT); manager->SetIOSettings(ios); KFbxImporter* importer = KFbxImporter::Create(manager, ""); if(!importer->Initialize(input_filename.c_str(), -1, manager->GetIOSettings())) { std::cerr << "failed to import %s" << input_filename << std::endl; std::cerr << importer->GetLastErrorString() << std::endl; return; } KFbxScene* scene = KFbxScene::Create(manager, "scene"); importer->Import(scene); importer->Destroy(); KFbxNode* root_node = scene->GetRootNode(); KFbxGeometryConverter converter(root_node->GetFbxSdkManager()); Object json_root; Array meshes; this->recurse_over_model(root_node, meshes); json_root["meshes"] = meshes; std::ofstream stream(output_filename.c_str()); Writer::Write(json_root, stream); }
// Load an FBX File into the assets void FBXParser::loadFBX(string const & s, Assets& assets){ cout << "Loading fbx file: " << s << endl; // IO Settings object KFbxIOSettings * ios = KFbxIOSettings::Create(lManager, IOSROOT); lManager->SetIOSettings(ios); // Establish importer KFbxImporter * lImporter = KFbxImporter::Create(lManager, ""); // File to import if(!lImporter->Initialize(s.c_str(), -1, lManager->GetIOSettings())){ cout << "Failed on creating FBX Importer." << endl; cout << " Error: " << lImporter->GetLastErrorString() << endl; exit(1); } // Create the scene KFbxScene * lScene = KFbxScene::Create(lManager, s.c_str()); lSceneList.push_back(lScene); // Import scene lImporter->Import(lScene); KFbxNode * lRootNode = lScene->GetRootNode(); traverseElements(assets, *lRootNode, s); lImporter->Destroy(); cout << " Finished loading fbx file." << endl; }
void readAnimation(KFbxNode* pNode, KFbxScene& fbxScene, const std::string& targetName, osg::ref_ptr<osgAnimation::AnimationManagerBase>& pAnimationManager, KFbxMesh* pMesh, int nBlendShape, int nBlendShapeChannel, int nShape) { for (int i = 0; i < fbxScene.GetSrcObjectCount(FBX_TYPE(KFbxAnimStack)); ++i) { KFbxAnimStack* pAnimStack = KFbxCast<KFbxAnimStack>(fbxScene.GetSrcObject(FBX_TYPE(KFbxAnimStack), i)); int nbAnimLayers = pAnimStack->GetMemberCount(FBX_TYPE(KFbxAnimLayer)); const char* pTakeName = pAnimStack->GetName(); if (!pTakeName || !*pTakeName) continue; for (int j = 0; j < nbAnimLayers; j++) { KFbxAnimLayer* pAnimLayer = pAnimStack->GetMember(FBX_TYPE(KFbxAnimLayer), j); KFbxAnimCurve* pCurve = pMesh->GetShapeChannel(nBlendShape, nBlendShapeChannel, pAnimLayer, false); if (!pCurve) { continue; } int nKeys = pCurve->KeyGetCount(); if (!nKeys) { continue; } osgAnimation::FloatLinearChannel* pChannel = new osgAnimation::FloatLinearChannel; std::vector<osgAnimation::TemplateKeyframe<float> >& keyFrameCntr = *pChannel->getOrCreateSampler()->getOrCreateKeyframeContainer(); for (int k = 0; k < nKeys; ++k) { KFbxAnimCurveKey key = pCurve->KeyGet(k); double fTime = key.GetTime().GetSecondDouble(); float fValue = static_cast<float>(key.GetValue() * 0.01); keyFrameCntr.push_back(osgAnimation::FloatKeyframe(fTime,fValue)); } pChannel->setTargetName(targetName); std::stringstream ss; ss << nShape; pChannel->setName(ss.str()); addChannel(pChannel, pAnimationManager, pTakeName); } } }
void FBXModel::load(const GraphicsDevice& device, const std::string& filename, unsigned keyframes) { if (effect.resource == 0) effect = Effect::createFromFile<FBXEffect>(device, Config::getValue(ConfigKeys::fbxEffectPath)); defaultTexture = Texture::createFromFile(device, defaultTexturePath); vertexDeclaration = device.createVertexDeclaration(FBXInstance::vertexElements); KFbxSdkManager* sdkManager = KFbxSdkManager::Create(); KFbxIOSettings* ios = KFbxIOSettings::Create(sdkManager, IOSROOT); sdkManager->SetIOSettings(ios); // Create an importer using our sdk manager. KFbxImporter* importer = KFbxImporter::Create(sdkManager, ""); importer->Initialize(filename.c_str(), -1, sdkManager->GetIOSettings()); // Create a new scene so it can be populated by the imported file. KFbxScene* scene = KFbxScene::Create(sdkManager, ""); // Import the contents of the file into the scene. importer->Import(scene); KFbxNode* rootBone = 0; KFbxNode* rootNode = scene->GetRootNode(); KFbxAnimStack* animStack = KFbxCast<KFbxAnimStack>(scene->GetSrcObject(FBX_TYPE(KFbxAnimStack), 0)); KFbxAnimLayer* animLayer = 0; if (animStack) { animLayer = animStack->GetMember(FBX_TYPE(KFbxAnimLayer), 0); scene->GetEvaluator()->SetContext(animStack); } loadBones(rootNode, &rootBone, animLayer); loadMeshes(rootNode, device, KFbxGeometryConverter(sdkManager)); if (animLayer) { for (unsigned i = 0; i <= keyframes; ++i) boneMatricesMap[i] = traverseBones(i, rootBone, Matrix::identity, MatrixCollection(bones.size())); } sdkManager->Destroy(); loaded = true; }
int FBXLoader::Import(char* name) { KFbxSdkManager* manage; KFbxIOSettings* ios; KFbxImporter* import; KFbxScene* scene; KFbxNode* root; int i; Node* Father; Scene* sceneM; sceneM = Scene::GetInstance(); i = 0; manage = KFbxSdkManager::Create(); ios = KFbxIOSettings::Create(manage, IOSROOT); manage->SetIOSettings(ios); import = KFbxImporter::Create(manage, ""); if (!import->Initialize(name, -1, manage->GetIOSettings())) { printf("initialize failed\nerror is %s\n",import->GetLastErrorString()); return (42); } scene = KFbxScene::Create(manage, "MY SCENE"); import->Import(scene); import->Destroy(); root = scene->GetRootNode(); if (root) { this->Root = new Node(); this->Root->SetFather(NULL); this->Root->SetName("root"); while (i < root->GetChildCount()) //papa { Father = new Node(); Root->AddChild(Father); this->PrintNode(root->GetChild(i), Father); ++i; } } sceneM->AddRoot(this->Root); manage->Destroy(); return (0); }
// Print Scene void FBXParser::printScene(KFbxScene const &s){ numTabs = 0; cout << "Printing scene..." << endl; KFbxNode * lRootNode = s.GetRootNode(); if(lRootNode){ for(int i=0; i < lRootNode->GetChildCount(); i++){ printNode(*lRootNode->GetChild(i)); } } }
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)); KFbxSdkManager* pSdkManager = KFbxSdkManager::Create(); if (!pSdkManager) { return WriteResult::ERROR_IN_WRITING_FILE; } CleanUpFbx cleanUpFbx(pSdkManager); pSdkManager->SetIOSettings(KFbxIOSettings::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; } } } KFbxScene* pScene = KFbxScene::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); } KFbxExporter* lExporter = KFbxExporter::Create(pSdkManager, ""); pScene->GetGlobalSettings().SetAxisSystem(KFbxAxisSystem::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())) { return std::string(lExporter->GetLastErrorString()); } if (!lExporter->Export(pScene)) { return std::string(lExporter->GetLastErrorString()); } 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; }
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; KFbxSdkManager* pSdkManager = KFbxSdkManager::Create(); if (!pSdkManager) { return ReadResult::ERROR_IN_READING_FILE; } CleanUpFbx cleanUpFbx(pSdkManager); pSdkManager->SetIOSettings(KFbxIOSettings::Create(pSdkManager, IOSROOT)); KFbxScene* pScene = KFbxScene::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 KFbxImporter* lImporter = KFbxImporter::Create(pSdkManager, ""); if (!lImporter->Initialize(utf8filename.c_str(), -1, pSdkManager->GetIOSettings())) { return std::string(lImporter->GetLastErrorString()); } if (!lImporter->IsFBX()) { return ReadResult::ERROR_IN_READING_FILE; } for (int i = 0; i < lImporter->GetTakeCount(); i++) { KFbxTakeInfo* lTakeInfo = lImporter->GetTakeInfo(i); lTakeInfo->mSelect = true; } if (!lImporter->Import(pScene)) { return std::string(lImporter->GetLastErrorString()); } //KFbxAxisSystem::OpenGL.ConvertScene(pScene); // Doesn't work as expected. Still need to transform vertices. if (KFbxNode* pNode = pScene->GetRootNode()) { pScene->SetCurrentTake(pScene->GetCurrentTakeName()); bool useFbxRoot = false; if (options) { std::istringstream iss(options->getOptionString()); std::string opt; while (iss >> opt) { if (opt == "UseFbxRoot") { useFbxRoot = true; } } } osg::ref_ptr<osgAnimation::AnimationManagerBase> pAnimationManager; 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()); std::set<const KFbxNode*> fbxSkeletons; findLinkedFbxSkeletonNodes(pNode, fbxSkeletons); std::map<KFbxNode*, osg::Node*> nodeMap; BindMatrixMap boneBindMatrices; std::map<KFbxNode*, osgAnimation::Skeleton*> skeletonMap; ReadResult res = readFbxNode(*pSdkManager, *pScene, pNode, pAnimationManager, bIsBone, nLightCount, fbxMaterialToOsgStateSet, nodeMap, boneBindMatrices, fbxSkeletons, skeletonMap, *localOptions); if (res.success()) { fbxMaterialToOsgStateSet.checkInvertTransparency(); resolveBindMatrices(*res.getNode(), boneBindMatrices, nodeMap); osg::Node* osgNode = res.getNode(); osgNode->getOrCreateStateSet()->setMode(GL_RESCALE_NORMAL,osg::StateAttribute::ON); osgNode->getOrCreateStateSet()->setMode(GL_NORMALIZE,osg::StateAttribute::ON); if (pAnimationManager.valid()) { if (osgNode->getUpdateCallback()) { osg::Group* osgGroup = new osg::Group; osgGroup->addChild(osgNode); osgNode = osgGroup; } //because the animations may be altered after registering pAnimationManager->buildTargetReference(); osgNode->setUpdateCallback(pAnimationManager.get()); } KFbxAxisSystem fbxAxis = pScene->GetGlobalSettings().GetAxisSystem(); if (fbxAxis != KFbxAxisSystem::OpenGL) { int upSign; KFbxAxisSystem::eUpVector eUp = fbxAxis.GetUpVector(upSign); bool bLeftHanded = fbxAxis.GetCoorSystem() == KFbxAxisSystem::LeftHanded; float fSign = upSign < 0 ? -1.0f : 1.0f; float zScale = bLeftHanded ? -1.0f : 1.0f; osg::Matrix mat; switch (eUp) { case KFbxAxisSystem::XAxis: mat.set(0,fSign,0,0,-fSign,0,0,0,0,0,zScale,0,0,0,0,1); break; case KFbxAxisSystem::YAxis: mat.set(1,0,0,0,0,fSign,0,0,0,0,fSign*zScale,0,0,0,0,1); break; case KFbxAxisSystem::ZAxis: 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; }
KFbxXMatrix FilmboxNode::GetWorldTransform( int frame ) const { KFbxXMatrix value; value.SetIdentity(); if( m_node ) { KFbxScene* scene = m_node->GetScene(); KFbxAnimEvaluator* evaluator = scene->GetEvaluator(); KTime frame_time; if( frame == 0xFFFFFFFF ) { frame_time = KTIME_INFINITE; } else { frame_time.SetTime( 0, 0, 0, frame ); } value = evaluator->GetNodeGlobalTransform( m_node, frame_time ); if( m_type == MCE::FBX::SceneObjectType::CAMERA ) { KFbxNode* fbx_target_node = m_node->GetTarget(); if( fbx_target_node ) { // For target cameras we need to manually replace the rotation to point towards the target KFbxVector4 camera_position = value.GetT(); MCE::FBX::FilmboxNode mce_target_node( fbx_target_node ); KFbxXMatrix target_transform = mce_target_node.GetWorldTransform( frame ); KFbxVector4 target_position = target_transform.GetT(); KFbxVector4 up_vector( 0.0, 1.0, 0.0, 0.0 ); KFbxVector4 look_axis = -( target_position - camera_position ); look_axis.Normalize(); KFbxVector4 right_axis = up_vector.CrossProduct( look_axis ); KFbxVector4 up_axis = look_axis.CrossProduct( right_axis ); KFbxMatrix rotation_matrix; rotation_matrix.SetRow( 0, right_axis ); rotation_matrix.SetRow( 1, up_axis ); rotation_matrix.SetRow( 2, look_axis ); rotation_matrix.SetRow( 3, KFbxVector4( 0.0, 0.0, 0.0, 1.0 ) ); KFbxQuaternion camera_rotation; double determinant; rotation_matrix.GetElements( KFbxVector4(), camera_rotation, KFbxVector4(), KFbxVector4(), determinant ); KFbxVector4 camera_scale( 1.0, 1.0, 1.0, 0.0 ); value.SetTQS( camera_position, camera_rotation, camera_scale ); } else { // Even though the SDK docs say that GetNodeGlobalTransform takes all transforms into account // For cameras it appears that you have to manually apply post-rotation KFbxVector4 post_rotation = m_node->GetPostRotation( KFbxNode::eSOURCE_SET ); KFbxXMatrix fbx_to_mce_camera; fbx_to_mce_camera.SetR( post_rotation ); value *= fbx_to_mce_camera; } } } return value; }
WHITEBOX_BEGIN void CFbxExporter::Export( const String& assetFolder, const String& resourceFolder, const String& filePath ) { String completeFilePath = assetFolder + filePath; WbLog( "Default", "Exporting FBX %s\n", completeFilePath.c_str() ); KFbxSdkManager* pSdkManager = NULL; KFbxScene* pScene = NULL; // Prepare the FBX SDK. InitializeSdkObjects( pSdkManager, pScene ); if ( !LoadScene( pSdkManager, pScene, completeFilePath.c_str() ) || pScene == NULL ) { WbLog( "Default", "FBX loading scene failed !\n" ); } ParseNode( pScene->GetRootNode(), resourceFolder, filePath ); /* TFileHandle file = gSystem->pFileSystem->OpenFile( completeFilePath.c_str(), true, false ); CMeshHelper meshHelper; size_t meshPartCount = 0; size_t vertexCount = 0; char buffer[256]; while( ReadWord( file, buffer ) ) { if ( strcmp( buffer, "#" ) == 0 || strcmp( buffer, "mtllib" ) == 0 ) { SkipLine( file ); } else if ( strcmp( buffer, "g" ) == 0 ) { meshHelper.AddMeshPart(); ++meshPartCount; } else if ( strcmp( buffer, "v" ) == 0 ) { Vec3 pos; if ( ReadWord( file, buffer ) ){ pos.x = ToFloat( buffer ); } if ( ReadWord( file, buffer ) ){ pos.y = ToFloat( buffer ); } if ( ReadWord( file, buffer ) ){ pos.z = ToFloat( buffer ); } meshHelper.AddPosition( pos ); ++vertexCount; } else if ( strcmp( buffer, "vn" ) == 0 ) { Vec3 normal; if ( ReadWord( file, buffer ) ){ normal.x = ToFloat( buffer ); } if ( ReadWord( file, buffer ) ){ normal.y = ToFloat( buffer ); } if ( ReadWord( file, buffer ) ){ normal.z = ToFloat( buffer ); } meshHelper.AddNormal( normal ); } else if ( strcmp( buffer, "vt" ) == 0 ) { Vec2 uv; if ( ReadWord( file, buffer ) ){ uv.x = ToFloat( buffer ); } if ( ReadWord( file, buffer ) ){ uv.y = ToFloat( buffer ); } meshHelper.AddUV0( uv ); } else if ( meshPartCount > 0 && strcmp( buffer, "f" ) == 0 ) { for( int index = 0 ; index < 3 ; ++index ) { if ( ReadWord( file, buffer ) ) { long int face = ToInt( buffer ); uint index; if ( face < 0 ) { index = (uint)(vertexCount + face); } else { index = (uint)(face - 1); } meshHelper.GetMeshPart( meshPartCount - 1 )->AddIndex( index ); } } } else if ( meshPartCount > 0 && strcmp( buffer, "usemtl" ) == 0 ) { if ( ReadWord( file, buffer ) ) { String materialName = resourceFolder + filePath.get_path_base() + buffer + ".mat"; meshHelper.GetMeshPart( meshPartCount - 1 )->SetMaterialName( materialName ); } } } String meshPath = resourceFolder + filePath.get_path_base() + filePath.get_path_name() + ".msh"; gSystem->pFileSystem->CreateFileDir( meshPath ); meshHelper.SaveToFile( meshPath ); gSystem->pFileSystem->CloseFile( file );*/ }
//Read the custom file and reconstruct node hierarchy. bool FBXImporterReader::Read(KFbxDocument* pDocument, KFbxStreamOptions* pStreamOptions) { if (!pDocument) { GetError().SetLastErrorID(eINVALID_DOCUMENT_HANDLE); return false; } KFbxScene* lScene = KFbxCast<KFbxScene>(pDocument); bool lIsAScene = (lScene != NULL); bool lResult = false; if(lIsAScene) { KFbxNode* lRootNode = lScene->GetRootNode(); KFbxNodeAttribute * lRootNodeAttribute = KFbxNull::Create(mManager,""); lRootNode->SetNodeAttribute(lRootNodeAttribute); int lSize; char* lBuffer; if(mFilePointer != NULL) { //To obtain file size fseek (mFilePointer , 0 , SEEK_END); lSize = ftell (mFilePointer); rewind (mFilePointer); //Read file content to a string. lBuffer = (char*) malloc (sizeof(char)*lSize); size_t lRead = fread(lBuffer, 1, lSize, mFilePointer); lBuffer[lRead]='\0'; KString lString(lBuffer); //Parse the string to get name and relation of Nodes. KString lSubString, lChildName, lParentName; KFbxNode* lChildNode; KFbxNode* lParentNode; KFbxNodeAttribute* lChildAttribute; int lEndTokenCount = lString.GetTokenCount("\n"); for (int i = 0; i < lEndTokenCount; i++) { lSubString = lString.GetToken(i, "\n"); KString lNodeString; lChildName = lSubString.GetToken(0, "\""); lParentName = lSubString.GetToken(2, "\""); //Build node hierarchy. if(lParentName == "RootNode") { lChildNode = KFbxNode::Create(mManager,lChildName.Buffer()); lChildAttribute = KFbxNull::Create(mManager,""); lChildNode->SetNodeAttribute(lChildAttribute); lRootNode->AddChild(lChildNode); } else { lChildNode = KFbxNode::Create(mManager,lChildName.Buffer()); lChildAttribute = KFbxNull::Create(mManager,""); lChildNode->SetNodeAttribute(lChildAttribute); lParentNode = lRootNode->FindChild(lParentName.Buffer()); lParentNode->AddChild(lChildNode); } } } lResult = true; } return lResult; }