定义
看了下网上比较多的是教大家怎么用 『AnimToTexture』这个插件,既有珠玉在前,我就不献木渎之丑。
比较有意思的是在之前的 5.1 版本中该插件还是在 Animation 目录下,但在 5.3 中又到了 Experimental 目录下。
本文将简单的过一遍这个插件里一些代码的实现细节:
文件目录
整个目录分为两个部分 「AnimToTexture」 与 「AnimToTextureEditor」:
Source ├─AnimToTexture └─AnimToTextureEditor
其中前者定义了一些基本的数据结构,而后者定义了编辑器下的资产操作,包括将 SkeletalMesh 转换为 StaticMesh 与将 AnimSequence 烘焙到 Texture 上。
细节实现
在应用中比较需要关注的实际是 「AnimToTextureEditor」 模块下的 AnimToTextureBPLibrary.xxx 文件,该文件定义了大部分蓝图或编辑器下使用的接口操作。实际上是 4 个函数:
AnimationToTexture- 烘焙动画数据到纹理的接口ConvertSkeletalMeshToStaticMesh- 转换骨骼网格体为静态网格体接口SetLightMapIndex- 设置光照贴图的辅助函数接口UpdateMaterialInstanceFromDataAsset- 更新材质实例的参数接口
实际上用起来比较重要的是 1、2 两个,现对它们的实现进行阐述分析:
ConvertSkletalMeshToStaticMesh
该函数首先会生成一个临时的 Actor :
// AnimToTextureBPLibrary.cpp
// UStaticMesh* UAnimTextureBPLibrary::ConvertSkeletalMeshToStaticMesh(...)
// ... 一些 check 检查
AActor* Actor = World->SpawnActor<AActor>();
USkeletalMeshComponent* MeshComponent = NewObject<USkeletalMeshComponent>(Actor);
MeshComponent->RegisterComponent();
MeshComponent->SetSkeletalMesh(SkeletalMesh);
TArray<UMeshComponent*> MeshComponents = { MeshComponent };
并在指定路径上创建一个空的 StaticMesh 资产:
// AnimToTextureBPLibrary.cpp
// UStaticMesh* UAnimTextureBPLibrary::ConvertSkeletalMeshToStaticMesh(...)
// Create New StaticMesh
if (!FPackageName::DoesPackageExist(PackageName))
{
IMeshUtilities& MeshUtilities = FModuleManager::Get().LoadModuleChecked<IMeshUtilities>("MeshUtilities");
OutStaticMesh = MeshUtilities.ConvertMeshesToStaticMesh(MeshComponents, FTransform::Identity, PackageName);
}
// Update Existing StaticMesh
else
{
OutStaticMesh = LoadObject<UStaticMesh>(nullptr, *PackageName);
}
值得注意的 Actor 中并没有值,实际仅创建一个空的资产。
随后生成临时资产存储实际转换的 StaticMesh:
// AnimToTextureBPLibrary.cpp
// UStaticMesh* UAnimTextureBPLibrary::ConvertSkeletalMeshToStaticMesh(...)
// 注意此处的第一个参数
UStaticMesh* TempMesh = MeshUtilities.ConvertMeshesToStaticMesh(MeshComponents, FTransform::Identity, TransientPackage->GetPathName());