BlueRoseNote/02-Note/DAWA/AI/UE_Cmd_AnimationRetargetingTool.md

6.5 KiB
Raw Blame History

大致步骤

使用UnrealEditor-Cmd执行资源导入、处理、输出功能。

  1. 导入资产 (这段可以参考FBX)
    1. 角色
    2. 动画 FBX
  2. 处理资产
    1. IKRig
    2. RetargetRig
    3. ControlRig?
  3. 输出资产
    1. FBX
    2. 使用MovieRenderQueue 渲染 MP4

短期需求

  1. AI 动捕、或者GPT生成 BVH、FBX。
  2. 特定骨骼结构。
  3. UE骨骼确定。
  4. 可能需要高并发(后面再考虑)
  5. 输出视频。
  6. 工期1~2周。

需要解决的问题是

  • 支持多种格式的文件
  • CustomCommandFunction编写以及生成IKRigIKRetarget资产
  • 输出FBX或者MP4

输出文件

  • *.BVH

生产环境

使用Docker或者其他容器工具制作处理用的镜像之后使用群集系统控制运行

CustomCommandFunction

关检测 UCommandlet

测试方法

D:\UnrealEngine\UE_5.1\Engine\Binaries\Win64\UnrealEditor-Cmd.exe D:\UnrealEngine\Project\AIAutomationTools\AIAutomationTools.uproject -run=AIAnimationAutomationCommandlet

如果带有配置文件

D:\UnrealEngine\UE_5.1\Engine\Binaries\Win64\UnrealEditor-Cmd.exe D:\UnrealEngine\Project\AIAutomationTools\AIAutomationTools.uproject -run=AIAnimationAutomationCommandlet -importsettings=C:\\Users\\BlueRose\\Desktop\\ImportJson.json
{
    "ImportGroups": [
        {
            "GroupName": "Group11",
			//导入文件名
			"Filenames": [
                "C:\\Users\\BlueRose\\Desktop\\untitled2_Anim.FBX"
            ],
            //生成资产的文件夹
            "DestinationPath": "Animation",
            //使用的Factory类名
            "FactoryName": "FbxFactory",
            "bReplaceExisting": 1,
            "bSkipReadOnly": 0,
            //导入动画资产的设置
            "ImportSettings": {
                "OriginalImportType": 2,
                "MeshTypeToImport": 2,
                "Skeleton": "/Game/1/untitled2_Skeleton.untitled2_Skeleton"
            }
        }
    ]
}

其他资料

IKRig & IKRetarget=

Engine\Plugins\Animation\IKRig

  • FAssetTypeActions_AnimationAssetRetarget
  • FAssetTypeActions_IKRigDefinition:UIKRigDefinition
  • FAssetTypeActions_IKRetargeter:UIKRetargeter

Retarger

/** The runtime processor that converts an input pose from a source skeleton into an output pose on a target skeleton.  
 * To use: 
 * 1. Initialize a processor with a Source/Target skeletal mesh and a UIKRetargeter asset. 
 * 2. Call RunRetargeter and pass in a source pose as an array of global-space transforms
 * 3. RunRetargeter returns an array of global space transforms for the target skeleton. 
 /

UEditorUtilityLibrary

Python参考 Plugins\MovieScene\MovieRenderPipeline\Content\Python

渲染影片(旧版)

MovieRenderPipelineCommandLine

"D:\Program Files\UE_4.24\Engine\Binaries\Win64\UE4Editor.exe" 
D:\Projects\UnrealProjects\renderMovieTest\renderMovieTest.uproject 
/Game/maps/shot0010 
-MovieSceneCaptureType="/Script/MovieSceneCapture.AutomatedLevelSequenceCapture" 
-LevelSequence="/Game/Sequences/Shot0010" 
-MovieFolder="D:\Projects\UnrealProjects\renderMovieTest\outputs" 
-NoLoadingScreen -game

void FMovieRenderPipelineCoreModule::StartupModule() 处理CommandLine变量

// Look to see if they supplied arguments on the command line indicating they wish to render a movie.  
if (IsTryingToRenderMovieFromCommandLine(SequenceAssetValue, SettingsAssetValue, MoviePipelineLocalExecutorClassType, MoviePipelineClassType))  
{  
	UE_LOG(LogMovieRenderPipeline, Log, TEXT("Detected that the user intends to render a movie. Waiting until engine loop init is complete to ensure "));  
	// Register a hook to wait until the engine has finished loading to increase the likelihood that the desired classes are loaded.  
	FCoreUObjectDelegates::PostLoadMapWithWorld.AddRaw(this, &FMovieRenderPipelineCoreModule::OnMapLoadFinished);  
}

通过委托调用渲染最终到void FMovieRenderPipelineCoreModule::InitializeCommandLineMovieRender()

void FMovieRenderPipelineCoreModule::InitializeCommandLineMovieRender()  
{  
	#if WITH_EDITOR  
	//const bool bIsGameMode = !GEditor;  
	//if (!bIsGameMode)  
	//{  
	// UE_LOG(LogMovieRenderPipeline, Fatal, TEXT("Command Line Renders must be performed in -game mode, otherwise use the editor ui/python and PIE. Add -game to your command line arguments."));  
	// FPlatformMisc::RequestExitWithStatus(false, MoviePipelineErrorCodes::Critical);  
	// return;  
	//}  
	#endif  
	  
	// Attempt to convert their command line arguments into the required objects.  
	UMoviePipelineExecutorBase* ExecutorBase = nullptr;  
	UMoviePipelineQueue* Queue = nullptr;  
	  
	uint8 ReturnCode = ParseMovieRenderData(SequenceAssetValue, SettingsAssetValue, MoviePipelineLocalExecutorClassType, MoviePipelineClassType,  
	/*Out*/ Queue, /*Out*/ ExecutorBase);  
	if (!ensureMsgf(ExecutorBase, TEXT("There was a failure parsing the command line and a movie render cannot be started. Check the log for more details.")))  
	{  
	// Take the failure return code from the detection of our command line arguments.  
	FPlatformMisc::RequestExitWithStatus(/*Force*/ false, /*ReturnCode*/ ReturnCode);  
	return;  
	}  
	else  
	{  
	UE_LOG(LogMovieRenderPipeline, Log, TEXT("Successfully detected and loaded required movie arguments. Rendering will begin once the map is loaded."));  
	if (Queue)  
	{  
	UE_LOG(LogMovieRenderPipeline, Log, TEXT("NumJobs: %d ExecutorClass: %s"), Queue->GetJobs().Num(), *ExecutorBase->GetClass()->GetName());  
	}  
	else  
	{  
	UE_LOG(LogMovieRenderPipeline, Log, TEXT("ExecutorClass: %s"), *ExecutorBase->GetClass()->GetName());  
	}  
	  
	}  
	  
	// We add the Executor to the root set. It will own all of the configuration data so this keeps it nicely in memory until finished,  
	// and means we only have to add/remove one thing from the root set, everything else uses normal outer ownership.  
	ExecutorBase->AddToRoot();  
	ExecutorBase->OnExecutorFinished().AddRaw(this, &FMovieRenderPipelineCoreModule::OnCommandLineMovieRenderCompleted);  
	ExecutorBase->OnExecutorErrored().AddRaw(this, &FMovieRenderPipelineCoreModule::OnCommandLineMovieRenderErrored);  
	  
	ExecutorBase->Execute(Queue);  
}

多线程

https://blog.csdn.net/j756915370/article/details/122752719

Runtime\Core\Public\Async\

  • FFutureState
  • FTaskGraphImplementation

2.6 TaskGraph 系统中的 Wait

在 TaskGraph 中,无论是 Event->Wait() 还是 FTaskGraphInterface::Get().WaitUntilTaskCompletes() ,最终都是调用到 FTaskGraphImplementation::WaitUntilTasksComplete 中的。