1
0
hugo/content/blog/2024-10-02-vrm4u.md
2024-12-21 21:03:10 +09:00

193 lines
8.9 KiB
Markdown

+++
date = "2024-10-02"
lastmod = "2024-10-03"
tags = ["vrm","ue"]
title = "ue5.5と最新のvmc事情"
+++
unreal engine 5.5.0 preview(ue5.5p)がインストールできるようになっています。今回は最新環境のvmc事情を解説します。
## vmcとは
webカメラから表情や動きをキャラクターに反映させるためのものです。vmcはprotocolとclientがあります。大抵はprotocolを指します。webカメラからの読み取りをcaptureといいます。つまり、captureとprotocolとclientを組みわせて動作します。ueで使うには更にvmcを受信してキャラクターに反映させるpluginが必要です。わけがわからないと思いますが、そんな感じです。
- https://github.com/sh-akira/VirtualMotionCapture
- https://github.com/ruyo/VRM4U
- https://github.com/HAL9HARUKU/VMC4UE
- https://github.com/HAL9HARUKU/ueOSC
- https://github.com/HAL9HARUKU/VRMMapExporter
- https://github.com/vrm-c/UniVRM
## vmc4ueをue5.5でbuildしてみよう
> この手順は興味がある人以外は読み飛ばすことを推奨します。表情を動かしたい人はこの方法で問題を解決することができません。
`vmc4ue`はue5.1までしかbuildされていません。そこでue5.5でbuildして使えるようにしてみます。
まずc++でprojectを作成し、patchをsrcに当てて`$project/Plugins/`に入れます。projectをueで開くとbuildされます。正常に終了するとeditorが開きます。
> c++で作成したprojectには$project.slnが作成されますので、それを開いてrebuildしてもいいです。
なお、patchはbuildが通るよう適当に作ったものです。vmcは動きますが、表情は動きませんでした。
```cpp:VMC4UEBlueprintFunctionLibrary.cpp.patch
--- ./VMC4UE/VMC4UE/Source/VMC4UE/Source/VMC4UEBlueprintFunctionLibrary.cpp
+++ ./VMC4UEBlueprintFunctionLibrary.cpp
@@ -119,27 +119,29 @@ UVMC4UEStreamingSkeletalMeshTransform* UVMC4UEBlueprin
{
return nullptr;
}
-
+
+ UVMC4UEStreamingSkeletalMeshTransform* StreamingSkeletalMeshTransform = nullptr;
+
+ // Try to get existing transform
{
- // Get
FRWScopeLock RWScopeLock(OSCManager->RWLock, FRWScopeLockType::SLT_ReadOnly);
- auto StreamingSkeletalMeshTransform = OSCManager->StreamingSkeletalMeshTransformMap.Find(Port);
- if (StreamingSkeletalMeshTransform != nullptr)
+ auto FoundTransform = OSCManager->StreamingSkeletalMeshTransformMap.Find(Port);
+ if (FoundTransform != nullptr)
{
- return *StreamingSkeletalMeshTransform;
+ return *FoundTransform;
}
}
+
+ // Create new transform if not found
{
- // Create
FRWScopeLock RWScopeLock(OSCManager->RWLock, FRWScopeLockType::SLT_Write);
- auto StreamingSkeletalMeshTransform = OSCManager->StreamingSkeletalMeshTransformMap.Find(Port);
- if (StreamingSkeletalMeshTransform != nullptr)
+ auto FoundTransform = OSCManager->StreamingSkeletalMeshTransformMap.Find(Port);
+ if (FoundTransform != nullptr)
{
- return *StreamingSkeletalMeshTransform;
+ return *FoundTransform;
}
- UVMC4UEStreamingSkeletalMeshTransform* NewStreamingSkeletalMeshTransform = NewObject<UVMC4UEStreamingSkeletalMeshTransform>();
- //FRWScopeLock RWScopeLock2(NewStreamingSkeletalMeshTransform->RWLock, FRWScopeLockType::SLT_Write);
+ UVMC4UEStreamingSkeletalMeshTransform* NewStreamingSkeletalMeshTransform = NewObject<UVMC4UEStreamingSkeletalMeshTransform>();
OSCManager->StreamingSkeletalMeshTransformMap.Emplace(Port, NewStreamingSkeletalMeshTransform);
// Bind Port
@@ -149,9 +151,10 @@ UVMC4UEStreamingSkeletalMeshTransform* UVMC4UEBlueprin
OSCManager->OscReceivers.Emplace(OscReceiver);
- return NewStreamingSkeletalMeshTransform;
+ StreamingSkeletalMeshTransform = NewStreamingSkeletalMeshTransform;
}
- return nullptr;
+
+ return StreamingSkeletalMeshTransform;
}
void UVMC4UEBlueprintFunctionLibrary::RefreshConnection(float Seconds)
```
```cpp:VMC4UEBoneMappingAssetFactory.cpp.patch
--- ./VMC4UE/Source/VMC4UEEd/Source/VMC4UEBoneMappingAssetFactory.cpp
+++ ./VMC4UEBoneMappingAssetFactory.cpp
@@ -5,6 +5,8 @@
#include "../../VMC4UE/Include/VMC4UEStreamingData.h"
#include "Dom/JsonObject.h"
#include "JsonObjectConverter.h"
+#include "UObject/ConstructorHelpers.h"
+#include "UObject/UObjectGlobals.h"
UVMC4UEBoneMappingAssetFactory::UVMC4UEBoneMappingAssetFactory(const FObjectInitializer &ObjectInitializer)
: Super(ObjectInitializer)
@@ -26,11 +28,12 @@
return UVMC4UEVRMMapping::StaticClass();
}
+
UObject *UVMC4UEBoneMappingAssetFactory::FactoryCreateText(UClass *InClass, UObject *InParent, FName InName, EObjectFlags Flags, UObject *Context, const TCHAR *Type, const TCHAR *&Buffer, const TCHAR *BuferEnd, FFeedbackContext *Warn)
{
FString TextData = FString(Buffer);
- UVMC4UEVRMMapping *NewAsset = CastChecked<UVMC4UEVRMMapping>(StaticConstructObject_Internal(InClass, InParent, InName, Flags));
+ UVMC4UEVRMMapping* NewAsset = NewObject<UVMC4UEVRMMapping>(InParent, InClass, InName, Flags);
if (!IsValid(NewAsset))
{
return nullptr;
```
```sh
$ git clone https://github.com/HAL9HARUKU/VMC4UE
$ patch -u ./VMC4UE/VMC4UE/Source/VMC4UE/Source/VMC4UEBlueprintFunctionLibrary.cpp < VMC4UEBlueprintFunctionLibrary.cpp.patch
$ patch -u ./VMC4UE/VMC4UE/Source/VMC4UEEd/Source/VMC4UEBoneMappingAssetFactory.cpp < VMC4UEBoneMappingAssetFactory.cpp.patch
```
## vrm4uを5.5向けにbuildしてみる
> この手順は興味がある人以外は読み飛ばすことを推奨します。表情を動かしたい人はこの方法で問題を解決することができません。
vrm4uは既に5.5のbuildを[releases](https://github.com/ruyo/VRM4U/releases/tag/20241002)しています。
ただいくつかの処理が5,4,0向けのようです。それを書き直してbuildしてみます。
```sh
$ git clone https://github.com/ruyo/VRM4U
$ cd VRM4U
$ git reset --hard a261860872936c8654e1705a91cff6f8224dbee5
$ grep -R 5,4,0 ./Source/*|cut -d : -f 1|xargs sed -i '' 's/5,4,0/5,5,0/g'
$ grep -R 5,5,0 .
```
これを先程と同じ手順でue5.5で開いてbuildします。
## vrm4u(vmc)はbuild後にも表情を動かせるのだろうか
わかりません。私の環境下では動きませんでした。他の人も動かない可能性がありますが、issueを読む限り動くようにも思えます。
> この問題は`vrm4u 20241007`で修正されました
issue : https://git.syui.ai/ai/ue/issues/9
それではどうするのか。livelink(face)を使います。ここからは少しめんどくさいことになりますが、かなり多くのアプリが必要です。
- 動き : webcam motion capture(vmc送信) + vseeface(vmc受信/送信) + vrm4u(vmc受信)
- 表情 : iphone + livelink face
まず、`vrm4u`は`webcam motion capture`のvmcを直接受信できません。なので、一旦、vseefaceなどのclientで受信する必要があります。それをvrm4uで受信するportに送信します。なお、`vmc4ue`では直接受信できて動きます。また、xr-animator, vseeface, vmc(client)も受信できて動いています。不思議な現象です。
vrm4u(vmc)はbuild後は表情が動かないので、表情はlivelinkを使用します。これはiphoneに`livelink face`というappがあります。ueでいくつかのpluginを有効にします。
- live link
- apple arkit
- apple arkit face support
`/VRM4U/Util/Actor/latest/BP_LiveLinkFace`をmapにおいて、`live link subject -> iphone`, `target actor sk -> SK_$name`を設定します。
![](/img/ue-2024-10-01-7.36.38.png)
これでbuildすると表情を動かすことができます。
## character(player)にlivelinkを当てるには
character(player)にlivelinkを当てるにはblueprintを編集する必要があります。characterのdirにでも`BP_LiveLinkFace`をcopyして`BP_Player(CBP_Character)`に追加します。
![](/img/ue-2024-10-01-7.36.39.png)
ここで`BP_LiveLinkFace -> livelink subject -> iphone`をセットしておきます。
次に`BP_LiveLinkFace`を以下のような形で`sk_$name`に置き換えます。場所はコメントを参考にしてください。私の場合は見た目をカスタマイズしているので少し複雑です。
<iframe src="https://blueprintue.com/render/pu_xl52s/" scrolling="no" allowfullscreen width="100%" height="400px"></iframe>
https://blueprintue.com/blueprint/pu_xl52s/
## vmcで行くべきか
基本的には依存関係が少なく使うアプリが少ないほうがいいですね。vmcの更新頻度やclient, vrm1のsupport状況を見るとueはlivelink路線のほうがいいかもしれません。
仮に`webcam motion capture -> vrm4u`で表情も体も動かせるならvmcで問題ないですが、表情にlivelinkを使うなら全部統一するのがいいですね。
[mocopi](https://apps.apple.com/jp/app/mocopi/id6444393701)や[iclone](https://www.unrealengine.com/marketplace/ja/product/iclone-unreal-live-link)はlivelinkなのでそちらが使えると思います。