UnrealEngineへの取り込み
CriLipsMake2の、Mpeg4-Visemesアニメーションカーブファイル(.csv)の出力結果をUnrealEngineへ取り込む方法について説明します。
DataTableアセットとして取り込む
SDKに含まれるサンプルプロジェクトで利用している方法です。CSVをそのまま取り扱うので、解析済みデータの差し替えなどが楽に行えます。
CSVに記載されている値をそのままキャラクターモデルに割り当てます。

まず、Source/RealLipsync/Public/SmpUtils.hで LipsMP4Viseme 型としてデータテーブルの定義を行います。
今回は音素の列だけ取り込み対象とします。
USTRUCT(BlueprintType, Category = "Sample")
struct REALLIPSYNC_API FLipsMP4Viseme
: public FTableRowBase
{
GENERATED_BODY()
public:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Sample")
float Sil = 0.0f;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Sample")
float PP = 0.0f;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Sample")
float FF = 0.0f;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Sample")
float TH = 0.0f;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Sample")
float DD = 0.0f;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Sample")
float KK = 0.0f;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Sample")
float CH = 0.0f;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Sample")
float SS = 0.0f;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Sample")
float NN = 0.0f;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Sample")
float RR = 0.0f;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Sample")
float AA = 0.0f;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Sample")
float E = 0.0f;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Sample")
float IH = 0.0f;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Sample")
float OH = 0.0f;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Sample")
float OU = 0.0f;
};
CriLipsMake2が出力したCSVファイルをLipsMP4Visemeとしてプロジェクトへインポートします。

BluePrintで扱うために、Source/RealLipsync/Private/SmpUtils.cppで再生中の時刻にあう行を探す GetDataTableValue() を実装します。
FLipsMP4Viseme USmpUtils::GetDataTableValue(UDataTable* InDataTable, float InTime)
{
check(IsValid(InDataTable));
if (InTime < 0.0f)
{
return FLipsMP4Viseme();
}
TArray<TPair<float, FName>> TimeNamePairs;
for (const auto& Name : InDataTable->GetRowNames())
{
float Time = FCString::Atof(*Name.ToString());
TimeNamePairs.Add(TPair<float, FName>(Time, Name));
}
TimeNamePairs.Sort([](const TPair<float, FName>& A, const TPair<float, FName>& B) {
return A.Key < B.Key;
});
for (int32 i = 0; i < TimeNamePairs.Num(); ++i)
{
if (InTime <= TimeNamePairs[i].Key)
{
return *InDataTable->FindRow<FLipsMP4Viseme>(TimeNamePairs[i].Value, FString());
}
}
if (TimeNamePairs.Num() > 0)
{
return *InDataTable->FindRow<FLipsMP4Viseme>(TimeNamePairs.Last().Value, FString());
}
return FLipsMP4Viseme();
}
ModelBPにて、再生中の音声から取得したデータテーブル内容をキャラクターの音素モーフターゲットに割り当てます。
