--- title: FBXAnimation导入逻辑 date: 2023-12-11 11:28:36 excerpt: tags: rating: ⭐ --- # BVHImport插件中的案例 ```c++ UObject* UBVHImportFactory::FactoryCreateFile(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, const FString& FileName, const TCHAR* Parms, FFeedbackContext* Warn, bool& bOutOperationCanceled) { if (!shouldImport) { return nullptr; } bool fileSuccess = BVHFile.ImportData(TCHAR_TO_ANSI(*FileName)); const bool bIsUnattended = (IsAutomatedImport() || FApp::IsUnattended() || IsRunningCommandlet() || GIsRunningUnattendedScript); // Check if it's a re-import if (InParent != nullptr) { UObject* ExistingObject = StaticFindObject(UObject::StaticClass(), InParent, *InName.ToString()); if (ExistingObject) { //reimport逻辑略 } } if (fileSuccess) { UAnimSequence* AnimSequence = NewObject(InParent, InName, Flags & ~EObjectFlags::RF_Transactional); if (Skeleton == NULL) { //创建骨骼资产略 } else { AnimSequence->SetSkeleton(Skeleton);//Skeleton bvhSkel AnimSequence->SetPreviewMesh(PreviewMesh); } ExtractAnimDataFromBVHFile(AnimSequence); return AnimSequence; } return nullptr; } ``` ```c++ void UBVHImportFactory::ExtractAnimDataFromBVHFile(UAnimSequence* AnimSequence) { if (AnimSequence) { // create animation IAnimationDataController& Controller = AnimSequence->GetController(); Controller.OpenBracket(LOCTEXT("ImportBVHAnimation", "Importing BVH Animation")); Controller.ResetModel(); // Write animation data into animation sequence. // Extract transform of hip to create root motion. const FReferenceSkeleton& RefSkeleton = AnimSequence->GetSkeleton()->GetReferenceSkeleton(); const FName RootName = RefSkeleton.GetBoneName(0); const int32 NumOfKeys = BVHFile.Root->FrameOffset.Num(); AnimSequence->ImportFileFramerate = (float)BVHFile.Header.DataRate; AnimSequence->ImportResampleFramerate = BVHFile.Header.DataRate; Controller.SetPlayLength(float(NumOfKeys - 1) / (float)BVHFile.Header.DataRate); Controller.SetFrameRate(FFrameRate(BVHFile.Header.DataRate, 1)); RecursiveReadKeysFromNode(Controller, BVHFile.Root.Get()); Controller.NotifyPopulated(); Controller.CloseBracket(); AnimSequence->AdditiveAnimType = EAdditiveAnimationType::AAT_None; AnimSequence->PostEditChange(); FAssetRegistryModule::AssetCreated(AnimSequence); AnimSequence->MarkPackageDirty(); } } ``` ```c++ void UBVHImportFactory::RecursiveReadKeysFromNode(IAnimationDataController& Controller, FNode* Node) { if (Node) { Controller.AddBoneTrack(Node->Name,false); Controller.SetBoneTrackKeys(Node->Name, Node->FrameOffset, Node->FrameQuat, Node->FrameScale,false); if (Node->Children.Num() > 0) { for (NodePtr Child : Node->Children) { RecursiveReadKeysFromNode(Controller, Child.Get()); } } } } ``` # UE5中使用FBXSDK导入动画逻辑 - UAnimSequence * UEditorEngine::ImportFbxAnimation - UAnimSequence * UnFbx::FFbxImporter::ImportAnimations UE5中FBXSDK相关函数调用方式: - bool FFbxImporter::OpenFile(FString Filename) - bool FFbxImporter::ImportFile(FString Filename, bool bPreventMaterialNameClash /*=false*/) # 参考 1. Interchange\\Runtime\\Source\\Parsers 1. InterchangeFbxParser.Build.cs 2. FbxInclude.h:FBXSDK头文件包含问题。