// メッシュ情報処理(再帰関数) void GetMeshData(FbxNode *parent, VertexDataArray& outVertexData) { // メッシュだけ処理 int numKids = parent->GetChildCount(); for(int i = 0; i < numKids; i++) { FbxNode *child = parent->GetChild(i); // メッシュを見つけたら if(child->GetMesh()) { FbxMesh* pMesh = child->GetMesh();// static_cast<FbxMesh*>(child->GetNodeAttribute()); printf("メッシュ発見\n"); printf("名前:%s\n", pMesh->GetName()); printf("ポリゴン数:%d\n", pMesh->GetPolygonCount()); printf("マテリアル数:%d\n", pMesh->GetElementMaterialCount()); printf("コントロールポイント数(頂点座標):%d\n", pMesh->GetControlPointsCount()); printf("UV数:%d\n", pMesh->GetTextureUVCount()); FbxArray<FbxVector4> normals; pMesh->GetPolygonVertexNormals(normals); printf("法線数:%d\n", normals.GetCount()); // 頂点情報取得 GetFBXVertexData(pMesh, outVertexData); } // マテリアル int numMat = child->GetMaterialCount(); for(int j = 0; j < numMat; ++j) { FbxSurfaceMaterial* mat = child->GetMaterial(j); if(mat) { GetMatrialData(mat); } } if(numMat == 0) { printf("マテリアルなし\n"); } child->GetChild(0); // 更に子を処理 GetMeshData(child, outVertexData); } }
void FBXSceneEncoder::loadBindShapes(FbxScene* fbxScene) { float m[16]; const int poseCount = fbxScene->GetPoseCount(); for (int i = 0; i < poseCount; ++i) { FbxPose* pose = fbxScene->GetPose(i); assert(pose); if (pose->IsBindPose() && pose->GetCount() > 0) { FbxNode* fbxNode = pose->GetNode(0); if (fbxNode->GetMesh() != NULL) { Node* node = _gamePlayFile.getNode(fbxNode->GetName()); assert(node && node->getModel()); Model* model = node->getModel(); if (model && model->getSkin()) { MeshSkin* skin = model->getSkin(); copyMatrix(pose->GetMatrix(0), m); skin->setBindShape(m); } } } } }
boost::shared_ptr<Job> FBXScene::createJobMesh() { boost::shared_ptr<MeshBuilder> job; FbxNode* node = findNode(FbxNodeAttribute::eMesh); if (node != nullptr) { job.reset(new MeshBuilder(m_pDatabase, "mesh", node->GetMesh())); } return boost::dynamic_pointer_cast<Job>(job); }
FBX::FBX(FbxScene* lScene) { material_library = new MaterialLibrary(""); // This function show how to cycle through scene elements in a linear way. const int lNodeCount = lScene->GetSrcObjectCount<FbxNode>(); FbxStatus lStatus; for (int lIndex=0; lIndex<lNodeCount; lIndex++) { FbxNode *lNode = lScene->GetSrcObject<FbxNode>(lIndex); printf("Node found: %s\n", lNode->GetName()); FbxMesh *lMesh=lNode->GetMesh(); if (lMesh) { TerrainInstance *terrain_instance=buildTerrainInstanceFromFBX(lNode); instances.push_back(terrain_instance); models.push_back(terrain_instance->getModel()); } } scene = lScene; }
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; }
UObject* UFbxFactory::RecursiveImportNode(void* VoidFbxImporter, void* VoidNode, UObject* InParent, FName InName, EObjectFlags Flags, int32& NodeIndex, int32 Total, TArray<UObject*>& OutNewAssets) { UObject* NewObject = NULL; FbxNode* Node = (FbxNode*)VoidNode; if (Node->GetNodeAttribute() && Node->GetNodeAttribute()->GetAttributeType() == FbxNodeAttribute::eLODGroup && Node->GetChildCount() > 0 ) { // import base mesh NewObject = ImportANode(VoidFbxImporter, Node->GetChild(0), InParent, InName, Flags, NodeIndex, Total); if ( NewObject ) { OutNewAssets.Add(NewObject); } bool bImportMeshLODs; if ( ImportUI->MeshTypeToImport == FBXIT_StaticMesh ) { bImportMeshLODs = ImportUI->StaticMeshImportData->bImportMeshLODs; } else if ( ImportUI->MeshTypeToImport == FBXIT_SkeletalMesh ) { bImportMeshLODs = ImportUI->SkeletalMeshImportData->bImportMeshLODs; } else { bImportMeshLODs = false; } if (NewObject && bImportMeshLODs) { // import LOD meshes for (int32 LODIndex = 1; LODIndex < Node->GetChildCount(); LODIndex++) { FbxNode* ChildNode = Node->GetChild(LODIndex); ImportANode(VoidFbxImporter, ChildNode, InParent, InName, Flags, NodeIndex, Total, NewObject, LODIndex); } } } else { if (Node->GetMesh()) { NewObject = ImportANode(VoidFbxImporter, Node, InParent, InName, Flags, NodeIndex, Total); if ( NewObject ) { OutNewAssets.Add(NewObject); } } for (int32 ChildIndex=0; ChildIndex<Node->GetChildCount(); ++ChildIndex) { UObject* SubObject = RecursiveImportNode(VoidFbxImporter,Node->GetChild(ChildIndex),InParent,InName,Flags,NodeIndex,Total,OutNewAssets); if ( SubObject ) { OutNewAssets.Add(SubObject); } if (NewObject==NULL) { NewObject = SubObject; } } } return NewObject; }
Model* FbxModelLoader::LoadModel(const char* fileName) { Model* model = nullptr; if (!m_importer->Initialize(fileName, -1, m_manager->GetIOSettings())) { return nullptr; } FbxScene* lScene = FbxScene::Create(m_manager, "myscene"); m_importer->Import(lScene); FbxNode* lRootNode = lScene->GetRootNode(); if (lRootNode) { if (lRootNode->GetChildCount() > 0) { FbxNode* lNode = lRootNode->GetChild(0); FbxMesh* lMesh = lNode->GetMesh(); if (!lMesh) return nullptr; std::ofstream file; file.open("DataFromFbxVector.txt"); char* buffer = new char[1024]; sprintf_s(buffer, 1024, "Number of children in Root: %d\n\n\n\n", lRootNode->GetChildCount()); file << buffer; if (lMesh->IsTriangleMesh()) file << "It's a triangle mesh!"; else file << "It's NOT a triangle mesh!"; FbxVector4* vertexArray = lMesh->GetControlPoints(); for (int i = 0; i < lMesh->GetControlPointsCount(); i++) { sprintf(buffer, "(%f, %f, %f)\n", vertexArray[i].mData[0], vertexArray[i].mData[1], vertexArray[i].mData[2]); file << buffer; } delete buffer; file.close(); Polygon* polygons = new Polygon[lMesh->GetPolygonCount()]; int polygonCount = lMesh->GetPolygonCount(); int index = 0; buffer = new char[1024]; file.open("DataFromPolygons.txt"); for (int i = 0; i < lMesh->GetPolygonCount(); i++) { index = lMesh->GetPolygonVertex(i, 0); sprintf(buffer, "\n\nPolygon #%d\nPolygon Vertex Index #%d: ", i, index); file << buffer; polygons[i].vertex1.x = (float)vertexArray[index].mData[0]; polygons[i].vertex1.y = (float)vertexArray[index].mData[1]; polygons[i].vertex1.z = (float)vertexArray[index].mData[2]; sprintf(buffer, "(%f, %f, %f)\n", polygons[i].vertex1.x, polygons[i].vertex1.y, polygons[i].vertex1.z); file << buffer; index = lMesh->GetPolygonVertex(i, 1); sprintf(buffer, "Polygon Vertex Index #%d: ", index); file << buffer; polygons[i].vertex2.x = (float)vertexArray[index].mData[0]; polygons[i].vertex2.y = (float)vertexArray[index].mData[1]; polygons[i].vertex2.z = (float)vertexArray[index].mData[2]; sprintf(buffer, "(%f, %f, %f)\n", polygons[i].vertex2.x, polygons[i].vertex2.y, polygons[i].vertex2.z); file << buffer; index = lMesh->GetPolygonVertex(i, 2); sprintf(buffer, "Polygon Vertex Index #%d: ", index); file << buffer; polygons[i].vertex3.x = (float)vertexArray[index].mData[0]; polygons[i].vertex3.y = (float)vertexArray[index].mData[1]; polygons[i].vertex3.z = (float)vertexArray[index].mData[2]; sprintf(buffer, "(%f, %f, %f)\n", polygons[i].vertex3.x, polygons[i].vertex3.y, polygons[i].vertex3.z); file << buffer; } file.close(); delete buffer; model = new Model(); model->Vertices = new DirectX::XMFLOAT3[polygonCount * 3]; model->NumVertices = polygonCount * 3; file.open("DataFromPolygonToModelTransfer.txt"); buffer = new char[1024]; for (int i = 0; i < lMesh->GetPolygonCount() * 3; i += 3) { model->Vertices[i] = polygons[i/3].vertex1; model->Vertices[i+1] = polygons[i/3].vertex2; model->Vertices[i+2] = polygons[i/3].vertex3; sprintf_s(buffer, 1024, "Polygon #%d:\n(%f, %f, %f)\n(%f, %f, %f)\n(%f, %f, %f)\n\n" , i / 3 , model->Vertices[i].x, model->Vertices[i].y, model->Vertices[i].z , model->Vertices[i+1].x, model->Vertices[i+1].y, model->Vertices[i+1].z , model->Vertices[i+2].x, model->Vertices[i+2].y, model->Vertices[i+2].z); file << buffer; } delete buffer; file.close(); // delete [] polygons; } else return nullptr; } else return nullptr; return model; }
bool SceneConverter::convert() { // // Construt the scene // FbxNode *node = m_scene->GetRootNode(); std::list<FbxNode *> nodes; std::map<FbxNode *, SceneNode *> fbxNode2SceneNodes; Scene scene; nodes.push_back(node); SceneNode *sceneNode = makeSceneNode(node); scene.addNode(sceneNode); fbxNode2SceneNodes.insert(std::make_pair(node, sceneNode)); while (!nodes.empty()) { FbxNode *ret = nodes.front(); nodes.pop_front(); for (int i = 0; i < ret->GetChildCount(); i++) { FbxNode *child = ret->GetChild(i); // Only output visible nodes. if (child->GetVisibility() && child->Show.Get()) { SceneNode *sceneNode = makeSceneNode(child); if (sceneNode != NULL) { if (sceneNode->type == "camera") { // The first camera will be the main camera of the scene scene.setCamera(sceneNode); } scene.addNode(sceneNode, fbxNode2SceneNodes[ret]); fbxNode2SceneNodes.insert(std::make_pair(child, sceneNode)); } nodes.push_back(child); } } } // Create a camera if it is not included in FBX. The camera is evaluated // using the bounding box of all visible nodes. if (m_numCameras == 0) { FbxVector4 rootBboxMin; FbxVector4 rootBboxMax; FbxVector4 rootBboxCenter; rootBboxMin = FbxVector4(FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX); rootBboxMax = FbxVector4(-FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX); FbxNode *node = m_scene->GetRootNode(); nodes.push_back(node); while (!nodes.empty()) { FbxNode *ret = nodes.front(); nodes.pop_front(); for (int i = 0; i < ret->GetChildCount(); i++) { FbxNode *child = ret->GetChild(i); nodes.push_back(child); } if (ret->GetChildCount() == 0 && ret->GetVisibility() && ret->Show.Get() && ret->GetMesh() != NULL) { FbxVector4 bboxMin; FbxVector4 bboxMax; FbxVector4 bboxCenter; ret->EvaluateGlobalBoundingBoxMinMaxCenter(bboxMin, bboxMax, bboxCenter); rootBboxMin[0] = std::min(rootBboxMin[0], bboxMin[0]); rootBboxMin[1] = std::min(rootBboxMin[1], bboxMin[1]); rootBboxMin[2] = std::min(rootBboxMin[2], bboxMin[2]); rootBboxMax[0] = std::max(rootBboxMax[0], bboxMax[0]); rootBboxMax[1] = std::max(rootBboxMax[1], bboxMax[1]); rootBboxMax[2] = std::max(rootBboxMax[2], bboxMax[2]); } } rootBboxCenter = (rootBboxMin + rootBboxMax) / 2; FbxVector4 rootBboxSize = rootBboxMax - rootBboxMin; SceneNode *sceneNode = new SceneNode(); sceneNode->type = FbxString("camera"); sceneNode->attributes.push_back(std::make_pair(FbxString("name"), FbxString("camera"))); sceneNode->attributes.push_back(std::make_pair(FbxString("fixed"), FbxString("true"))); double diag = sqrt(rootBboxSize[0] * rootBboxSize[0] + rootBboxSize[1] * rootBboxSize[1] + rootBboxSize[2] * rootBboxSize[2]) * 0.5; double eye = diag / tan(15.0 * FBXSDK_PI_DIV_180); double position[3]; double up[3]; double znear; double zfar; znear = eye - diag - 1.0f; zfar = eye + diag + 1.0f; if (rootBboxSize[0] <= rootBboxSize[1] && rootBboxSize[0] <= rootBboxSize[2]) { position[0] = eye + rootBboxCenter[0]; position[1] = rootBboxCenter[1]; position[2] = rootBboxCenter[2]; up[0] = 0; up[1] = 1; up[2] = 0; } else if (rootBboxSize[1] <= rootBboxSize[0] && rootBboxSize[1] <= rootBboxSize[2]) { position[0] = rootBboxCenter[0]; position[1] = eye + rootBboxCenter[1]; position[2] = rootBboxCenter[2]; up[0] = 0; up[1] = 0; up[2] = 1; } else { position[0] = rootBboxCenter[0]; position[1] = rootBboxCenter[1]; position[2] = eye + rootBboxCenter[2]; up[0] = 0; up[1] = 1; up[2] = 0; } char lookat[1024]; char perspective[1024]; FBXSDK_sprintf(lookat, 1024, "eye:%8.5f,%8.5f,%8.5f,center:%8.5f,%8.5f,%8.5f,up:%8.5f,%8.5f,%8.5f", (float)position[0], (float)position[1], (float)position[2], (float)rootBboxCenter[0], (float)rootBboxCenter[1], (float)rootBboxCenter[2], (float)up[0], (float)up[1], (float)up[2]); sceneNode->attributes.push_back(std::make_pair(FbxString("lookat"), FbxString(lookat))); FBXSDK_sprintf(perspective, 1024, "perspective,fov:%8.5f,aspect:-1,znear:%8.5f,zfar:%8.5f", 30.0f, (float)znear, (float)zfar); sceneNode->attributes.push_back(std::make_pair(FbxString("projection"), FbxString(perspective))); scene.setCamera(sceneNode); scene.addNode(sceneNode, scene.root()); } // // Output the file. // //FbxString outputFilename = FbxPathUtils::GetFileName(m_arguments->FBXFileName.Buffer()).Lower(); //outputFilename.FindAndReplace(".fbx", ".psc"); FbxString outputFilename("scene.psc"); FbxString path = FbxPathUtils::Bind(m_arguments->outputFolder, outputFilename.Buffer()); bool ret = scene.output(path.Buffer()); if (!ret) { FBXSDK_printf("Exporting failed!\n\n"); } return ret; }
void importFBXNode( FbxNode *node, vector<Vector3> &vertices, vector<Color> &colors, vector<Vector2> &uvs, vector<Vector3> &normals, vector<uint32> &elements) { FbxNode *childNode = 0; int numKids = node->GetChildCount(); for ( int i=0 ; i<numKids ; i++) { childNode = node->GetChild(i); FbxMesh *mesh = childNode->GetMesh(); if ( mesh != NULL ) { auto offset = node->GetGeometricTranslation(FbxNode::eSourcePivot); //================= Get Vertices ==================================== int baseline = vertices.size(); int numVerts = mesh->GetControlPointsCount(); for ( int j=0; j<numVerts; j++) { FbxVector4 vert = mesh->GetControlPointAt(j); vertices.push_back( Vector3(vert.mData[0], vert.mData[1], vert.mData[2]) /*+ Vector3(offset.mData[0], offset.mData[1], offset.mData[2])*/); colors.push_back(Vector3(1, 1, 1)); uvs.push_back(Vector2(0, 0)); } //================= Get Indices ==================================== int numIndices=mesh->GetPolygonVertexCount(); int *indicesRaw = mesh->GetPolygonVertices(); for (int j = 0; j < numIndices; j++) { elements.push_back(indicesRaw[j] + baseline); } int cnt = 0; int polygonCount = mesh->GetPolygonCount(); for (int j = 0; j < polygonCount; ++j) { FbxLayerElementArrayTemplate<FbxVector2>* uvVertices= 0; mesh->GetTextureUV(&uvVertices, FbxLayerElement::eTextureDiffuse); for (int k = 0; k < mesh->GetPolygonSize(j); ++k) { FbxVector2 uv = (*uvVertices)[mesh->GetTextureUVIndex(j, k)]; uvs[indicesRaw[cnt] + baseline].x = uv[0]; uvs[indicesRaw[cnt] + baseline].y = uv[1]; cnt++; } } } importFBXNode(childNode, vertices, colors, uvs, normals, elements); } }