void FBXConverter::processAnimations( FbxNode* node , std::vector<JointData> &skeleton , std::vector<VertexData> &verts , std::vector<IndexData> &indices ) { FbxMesh* theMesh = node->GetMesh(); FbxAnimStack* animationStack = node->GetScene()->GetSrcObject<FbxAnimStack>(); FbxAnimLayer* animationLayer = animationStack->GetMember<FbxAnimLayer>(); std::vector<FbxTime> frames; for ( int curveNodeIndex = 0; curveNodeIndex < animationLayer->GetMemberCount(); ++curveNodeIndex ) { FbxAnimCurveNode* currentCurve = animationLayer->GetMember<FbxAnimCurveNode>( curveNodeIndex ); for ( unsigned int channelIndex = 0; channelIndex < currentCurve->GetChannelsCount(); ++channelIndex ) { for ( int curve = 0; curve < currentCurve->GetCurveCount( channelIndex ); ++curve ) { FbxAnimCurve* theCurveVictim = currentCurve->GetCurve( channelIndex , curve ); for ( int keyIndex = 0; keyIndex < theCurveVictim->KeyGetCount(); ++keyIndex ) { bool alreadyIn = false; for ( unsigned int frameIndex = 0; frameIndex < frames.size(); ++frameIndex ) { if ( ( unsigned int ) frames[frameIndex].GetFrameCount() == ( unsigned int ) theCurveVictim->KeyGet( keyIndex ).GetTime().GetFrameCount() ) { alreadyIn = true; //std::cout << frames[frameIndex].GetFrameCount() << " " << theCurveVictim->KeyGet( keyIndex ).GetTime().GetFrameCount() << " " << alreadyIn << std::endl; break; } } std::cout << theCurveVictim->KeyGet( keyIndex ).GetTime().GetFrameCount() << " " << alreadyIn << std::endl; if(!alreadyIn) frames.push_back(theCurveVictim->KeyGet( keyIndex ).GetTime()); } } } } std::sort( frames.begin() , frames.end() , frameCompare ); FbxAMatrix geoTransform( node->GetGeometricTranslation( FbxNode::eSourcePivot ) , node->GetGeometricRotation( FbxNode::eSourcePivot ) , node->GetGeometricScaling( FbxNode::eSourcePivot ) ); for ( int i = 0; i < theMesh->GetDeformerCount(); ++i ) { FbxSkin* theSkin = reinterpret_cast< FbxSkin* >( theMesh->GetDeformer( i , FbxDeformer::eSkin ) ); if ( !theSkin ) continue; for ( int j = 0; j < theSkin->GetClusterCount(); ++j ) { FbxCluster* cluster = theSkin->GetCluster( j ); std::string jointName = cluster->GetLink()->GetName(); int currentJointIndex = -1; for ( unsigned int k = 0; k < skeleton.size(); ++k ) { if ( !skeleton[k].name.compare( jointName ) ) { currentJointIndex = k; break; } } if ( currentJointIndex < 0 ) { std::cout << "wrong bone" << std::endl; continue; } FbxAMatrix transformMatrix, transformLinkMatrix, offsetMatrix; cluster->GetTransformMatrix( transformMatrix ); cluster->GetTransformLinkMatrix( transformLinkMatrix ); //offsetMatrix = transformLinkMatrix.Inverse() * transformMatrix * geoTransform; FbxMatrix realMatrix( transformLinkMatrix.Inverse() * transformMatrix ); for ( unsigned int row = 0; row < 4; ++row ) { for ( unsigned int column = 0; column < 4; ++column ) { skeleton[currentJointIndex].offsetMatrix[row][column] = (float)realMatrix.Get( row , column ); } } for ( int k = 0; k < cluster->GetControlPointIndicesCount(); ++k ) { BlendingIndexWeightPair weightPair; weightPair.blendingIndex = currentJointIndex; weightPair.blendingWeight = (float)cluster->GetControlPointWeights()[k]; unsigned int controlPoint = cluster->GetControlPointIndices()[k]; for ( unsigned int z = 0; z < indices.size(); ++z ) { if ( indices[z].oldControlPoint == controlPoint ) { if ( verts[indices[z].index].blendingInfo.size() > 4 ) { std::cout << "Warning: vert has more than 4 bones connected, ignoring additional bone." << std::endl; } //else verts[indices[z].index].blendingInfo.push_back( weightPair ); bool found = false; for ( unsigned int omg = 0; omg < verts[indices[z].index].blendingInfo.size(); ++omg ) { if ( verts[indices[z].index].blendingInfo[omg].blendingIndex == weightPair.blendingIndex ) { found = true; break; } } if ( !found ) verts[indices[z].index].blendingInfo.push_back( weightPair ); } } } for ( unsigned int frameIndex = 0; frameIndex < frames.size(); ++frameIndex ) { FbxVector4 translation = cluster->GetLink()->EvaluateLocalTranslation( frames[frameIndex] ); FbxVector4 rotation = cluster->GetLink()->EvaluateLocalRotation( frames[frameIndex] ); FbxVector4 scale = cluster->GetLink()->EvaluateLocalScaling( frames[frameIndex] ); AnimationData animData; animData.frame = (int)frames[frameIndex].GetFrameCount(); animData.translation = glm::vec3(translation[0],translation[1],translation[2]); animData.rotation = glm::angleAxis( glm::radians( (float)rotation[2] ), glm::vec3(0,0,1)) * glm::angleAxis(glm::radians((float) rotation[1]), glm::vec3(0,1,0)) * glm::angleAxis(glm::radians((float)rotation[0]), glm::vec3(1,0,0)); animData.scale = glm::vec3(scale[0],scale[1],scale[2]); skeleton[currentJointIndex].animation.push_back( animData ); } } } }
void Tools::DisplayAnimation::DisplayChannels( FbxNode* i_node, FbxAnimLayer* i_animLayer, void (*DisplayCurve) (FbxAnimCurve* i_curve), void (*DisplayListCurve) (FbxAnimCurve* i_curve, FbxProperty* i_property), bool isSwitcher ) { FbxAnimCurve *animCurve = NULL; // Display general curves. if (!isSwitcher) { animCurve = i_node->LclTranslation.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_X ); if( animCurve ) { FBXSDK_printf( " TX\n" ); DisplayCommon::DisplayString( " TX" ); DisplayCurve( animCurve ); } animCurve = i_node->LclTranslation.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_Y ); if( animCurve ) { FBXSDK_printf( " TY\n" ); DisplayCommon::DisplayString( " TY" ); DisplayCurve( animCurve ); } animCurve = i_node->LclTranslation.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_Z ); if( animCurve ) { FBXSDK_printf( " TZ\n" ); DisplayCommon::DisplayString( " TZ" ); DisplayCurve( animCurve ); } animCurve = i_node->LclRotation.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_X ); if( animCurve ) { FBXSDK_printf( " RX\n" ); DisplayCommon::DisplayString( " RX" ); DisplayCurve( animCurve ); } animCurve = i_node->LclRotation.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_Y ); if( animCurve ) { FBXSDK_printf( " RY\n" ); DisplayCommon::DisplayString( " RY" ); DisplayCurve( animCurve ); } animCurve = i_node->LclRotation.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_Z ); if( animCurve ) { FBXSDK_printf( " RZ\n" ); DisplayCommon::DisplayString( " RZ" ); DisplayCurve( animCurve ); } animCurve = i_node->LclScaling.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_X ); if( animCurve ) { FBXSDK_printf( " SX\n" ); DisplayCommon::DisplayString( " SX" ); DisplayCurve( animCurve ); } animCurve = i_node->LclScaling.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_Y ); if( animCurve ) { FBXSDK_printf( " SY\n" ); DisplayCommon::DisplayString( " SY" ); DisplayCurve( animCurve ); } animCurve = i_node->LclScaling.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_Z ); if( animCurve ) { FBXSDK_printf( " SZ\n" ); DisplayCommon::DisplayString( " SZ" ); DisplayCurve( animCurve ); } } // Display curves specific to a light or marker. FbxNodeAttribute *nodeAttribute = i_node->GetNodeAttribute(); if( nodeAttribute ) { animCurve = nodeAttribute->Color.GetCurve( i_animLayer, FBXSDK_CURVENODE_COLOR_RED ); if( animCurve ) { FBXSDK_printf( " Red\n" ); DisplayCommon::DisplayString( " Red" ); DisplayCurve( animCurve ); } animCurve = nodeAttribute->Color.GetCurve( i_animLayer, FBXSDK_CURVENODE_COLOR_GREEN ); if( animCurve ) { FBXSDK_printf( " Green\n" ); DisplayCommon::DisplayString( " Green" ); DisplayCurve( animCurve ); } animCurve = nodeAttribute->Color.GetCurve( i_animLayer, FBXSDK_CURVENODE_COLOR_BLUE ); if( animCurve ) { FBXSDK_printf( " Blue\n" ); DisplayCommon::DisplayString( " Blue" ); DisplayCurve( animCurve ); } // Display curves specific to a light. FbxLight *light = i_node->GetLight(); if( light ) { animCurve = light->Intensity.GetCurve( i_animLayer ); if( animCurve ) { FBXSDK_printf( " Intensity\n" ); DisplayCommon::DisplayString( " Intensity" ); DisplayCurve( animCurve ); } animCurve = light->OuterAngle.GetCurve( i_animLayer ); if( animCurve ) { FBXSDK_printf( " Outer Angle\n" ); DisplayCommon::DisplayString( " Outer Angle" ); DisplayCurve( animCurve ); } animCurve = light->Fog.GetCurve( i_animLayer ); if( animCurve ) { FBXSDK_printf( " Fog\n" ); DisplayCommon::DisplayString( " Fog" ); DisplayCurve( animCurve ); } } // Display curves specific to a camera. FbxCamera *camera = i_node->GetCamera(); if( camera ) { animCurve = camera->FieldOfView.GetCurve( i_animLayer ); if( animCurve ) { FBXSDK_printf( " Field of View\n" ); DisplayCommon::DisplayString( " Field of View" ); DisplayCurve( animCurve ); } animCurve = camera->FieldOfViewX.GetCurve( i_animLayer ); if( animCurve ) { FBXSDK_printf( " Field of View X\n" ); DisplayCommon::DisplayString( " Field of View X" ); DisplayCurve( animCurve ); } animCurve = camera->FieldOfViewY.GetCurve( i_animLayer ); if( animCurve ) { FBXSDK_printf( " Field of View Y\n" ); DisplayCommon::DisplayString( " Field of View Y" ); DisplayCurve( animCurve ); } animCurve = camera->OpticalCenterX.GetCurve( i_animLayer ); if( animCurve ) { FBXSDK_printf( " Optical Center X\n" ); DisplayCommon::DisplayString( " Optical Center X" ); DisplayCurve( animCurve ); } animCurve = camera->OpticalCenterY.GetCurve( i_animLayer ); if( animCurve ) { FBXSDK_printf( " Optical Center Y\n" ); DisplayCommon::DisplayString( " Optical Center Y" ); DisplayCurve( animCurve ); } animCurve = camera->Roll.GetCurve( i_animLayer ); if( animCurve ) { FBXSDK_printf( " Roll\n" ); DisplayCommon::DisplayString( " Roll" ); DisplayCurve( animCurve ); } } // Display curves specific to a geometry. if (nodeAttribute->GetAttributeType() == FbxNodeAttribute::eMesh || nodeAttribute->GetAttributeType() == FbxNodeAttribute::eNurbs || nodeAttribute->GetAttributeType() == FbxNodeAttribute::ePatch) { FbxGeometry *geometry = (FbxGeometry*) nodeAttribute; int blendShapeDeformerCount = geometry->GetDeformerCount( FbxDeformer::eBlendShape ); for( int blendShapeIndex = 0; blendShapeIndex<blendShapeDeformerCount; blendShapeIndex++ ) { FbxBlendShape *blendShape = (FbxBlendShape*)geometry->GetDeformer( blendShapeIndex, FbxDeformer::eBlendShape ); int blendShapeChannelCount = blendShape->GetBlendShapeChannelCount(); for( int channelIndex = 0; channelIndex<blendShapeChannelCount; channelIndex++ ) { FbxBlendShapeChannel *channel = blendShape->GetBlendShapeChannel( channelIndex ); const char *channelName = channel->GetName(); animCurve = geometry->GetShapeChannel( blendShapeIndex, channelIndex, i_animLayer, true ); if( animCurve ) { FBXSDK_printf( " Shape %s\n", channelName ); DisplayCommon::DisplayString( " Shape ", channelName ); DisplayCurve( animCurve ); } } } } } // Display curves specific to properties FbxProperty lProperty = i_node->GetFirstProperty(); while( lProperty.IsValid() ) { if( lProperty.GetFlag(FbxPropertyAttr::eUserDefined) ) { FbxString lFbxFCurveNodeName = lProperty.GetName(); FbxAnimCurveNode* curveNode = lProperty.GetCurveNode( i_animLayer ); if( !curveNode ) { lProperty = i_node->GetNextProperty( lProperty ); continue; } FbxDataType dataType = lProperty.GetPropertyDataType(); if( dataType.GetType() == eFbxBool || dataType.GetType() == eFbxDouble || dataType.GetType() == eFbxFloat || dataType.GetType() == eFbxInt ) { FbxString message; message = " Property "; message += lProperty.GetName(); if( lProperty.GetLabel().GetLen() > 0 ) { message += " (Label: "; message += lProperty.GetLabel(); message += ")"; }; DisplayCommon::DisplayString( message ); for( int c = 0; c < curveNode->GetCurveCount(0U); c++ ) { animCurve = curveNode->GetCurve( 0U, c ); if( animCurve ) DisplayCurve( animCurve ); } } else if( dataType.GetType() == eFbxDouble3 || dataType.GetType() == eFbxDouble4 || dataType.Is(FbxColor3DT) || dataType.Is(FbxColor4DT) ) { char* componentName1 = (dataType.Is(FbxColor3DT) ||dataType.Is(FbxColor4DT)) ? (char*)FBXSDK_CURVENODE_COLOR_RED : (char*)"X"; char* componentName2 = (dataType.Is(FbxColor3DT) ||dataType.Is(FbxColor4DT)) ? (char*)FBXSDK_CURVENODE_COLOR_GREEN : (char*)"Y"; char* componentName3 = (dataType.Is(FbxColor3DT) ||dataType.Is(FbxColor4DT)) ? (char*)FBXSDK_CURVENODE_COLOR_BLUE : (char*)"Z"; FbxString message; message = " Property "; message += lProperty.GetName(); if( lProperty.GetLabel().GetLen() > 0 ) { message += " (Label: "; message += lProperty.GetLabel(); message += ")"; } DisplayCommon::DisplayString( message ); for( int c = 0; c < curveNode->GetCurveCount(0U); c++ ) { animCurve = curveNode->GetCurve( 0U, c ); if( animCurve ) { DisplayCommon::DisplayString( " Component ", componentName1 ); DisplayCurve( animCurve ); } } for( int c = 0; c < curveNode->GetCurveCount(1U); c++ ) { animCurve = curveNode->GetCurve(1U, c); if( animCurve ) { DisplayCommon::DisplayString( " Component ", componentName2 ); DisplayCurve( animCurve ); } } for( int c = 0; c < curveNode->GetCurveCount(2U); c++ ) { animCurve = curveNode->GetCurve( 2U, c ); if( animCurve ) { DisplayCommon::DisplayString( " Component ", componentName3 ); DisplayCurve( animCurve ); } } } else if( dataType.GetType() == eFbxEnum ) { FbxString message; message = " Property "; message += lProperty.GetName(); if( lProperty.GetLabel().GetLen() > 0 ) { message += " (Label: "; message += lProperty.GetLabel(); message += ")"; }; DisplayCommon::DisplayString( message ); for( int c = 0; c < curveNode->GetCurveCount(0U); c++ ) { animCurve = curveNode->GetCurve( 0U, c ); if( animCurve ) DisplayListCurve( animCurve, &lProperty ); } } } lProperty = i_node->GetNextProperty( lProperty ); } // while }
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; }