メインコンテンツまでスキップ

UnrealEngineへの取り込み

CriLipsMake2の、Mpeg4-Visemesアニメーションカーブファイル(.csv)の出力結果をUnrealEngineへ取り込む方法について説明します。

DataTableアセットとして取り込む

SDKに含まれるサンプルプロジェクトで利用している方法です。CSVをそのまま取り扱うので、解析済みデータの差し替えなどが楽に行えます。

CSVに記載されている値をそのままキャラクターモデルに割り当てます。 datatable_asset

まず、Source/RealLipsync/Public/SmpUtils.hLipsMP4Viseme 型としてデータテーブルの定義を行います。
今回は音素の列だけ取り込み対象とします。

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としてプロジェクトへインポートします。 datatable

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にて、再生中の音声から取得したデータテーブル内容をキャラクターの音素モーフターゲットに割り当てます。 modelbp