RuntimeMeshComponentについて

# RuntimeMeshComponentとは？
Unreal Engine4にて、動的にサーフェイスメッシュを扱うためには、[ProceduralMeshComponent](https://docs.unrealengine.com/en-US/API/Plugins/ProceduralMeshComponent/index.html)(PMC)があります。RuntimeMeshComponent（RMC）はその代替として開発された、より効率的で多様な機能があって多様なユースケースに対応できるのだそうです。どのくらい優れているかは、以下の指標が端的に示しています。

1. 50-90% Lower memory usage than PMC (PMCよりメモリ効率が良い）
2. 30-100% lower render thread cpu time (PMCよりレンダリング時間が短い）
3. Static draw path for maximum rendering performance (静的なメッシュに対しては、最高のレンダリング性能)
4. Dynamic Draw path for efficient frequent updates. (高頻度で変化する動的なメッシュに対して効果的）

このライブラリはいろんなところで使われているようなのですが、日本語での解説が少なかったり、提供されているC++のサンプルがそのまま動かなかったりという問題があります。ここでは、簡単なサンプルを試すまでの手順を説明したいと思います。なお、UE4のバージョンは4.25、Visual Studio 2019 Communityを使っています。


# インストール
[Gitのページ](https://github.com/TriAxis-Games/RuntimeMeshComponent)でソースコードをダウンロードします。マーケットプレイスにはありません。

適当なプロジェクト(RMCTest)を作り、プロジェクトフォルダの最上位階層に、Pluginsフォルダを作ります。その中に、ソースコードを解凍してできた`RuntimeMeshComponent`フォルダを配置します。UE4の仕様では、Pluginsフォルダの中にある`xxxx.uplugin`という拡張子のファイルを再帰的に探して読み込むようです。うまくいくと、ウィンドウ -> デベロッパーツール -> モジュール
内に当該プラグインが発見できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51703/aebdb2af-cd97-80a8-4b57-b8f3316df11f.png)

# 簡易的なC++サンプル
ブループリントについては、[サンプルプロジェクト](https://github.com/TriAxis-Games/RuntimeMeshComponent-Examples)を見れば分かるので、ここではC++について触れます。バージョンが違うためか、そのままでは動きません。

まずは、`RuntimeMeshActor`を継承した適当なクラスを作ります。インストールが成功していれば候補に出てくるはずです。ここではサンプルに倣って、`ABasicPMCStyleRMC`と名前を付けます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51703/bcc1ad80-b93a-3c58-ff56-54013ca6aca2.png)

続いて、C++のプロジェクトで、当該プラグインを読み込ませるための設定を行います。以下のように、`PublicDependencyModuleNames`に`RuntimeMeshComponent`を追記します。ここまでやって、リビルドしたところで、`RMCTest.uproject`を右クリックして`Generate Visual Studio Project Files`をしておいた方が良いようです。

```RMCTest.Build.cs
using UnrealBuildTool;

public class RMCTest : ModuleRules
{
	public RMCTest(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
	
		PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "RuntimeMeshComponent" });

	}
}

```

続いて、作成したABasicPMCStyleRMCに簡易的なメッシュに色を付けたものを自動生成するコードを追加します。元のサンプルだと、`OnConstruction`を使っていたのですが、どうしても呼ばれなかったので、`BeginPlay`内に生成コードを入れています。結果としては同じになるかと思いますが、もしOnConstructionを使った方がいい場合は誰か教えてください。

ここに書いてあるように、マテリアル情報はきちんとUI上で付与する必要があります。

```BasicPMCStyleRMC.h

#pragma once

#include "CoreMinimal.h"
#include "RuntimeMeshActor.h"
#include "BasicPMCStyleRMC.generated.h"

UCLASS()
class ABasicPMCStyleRMC : public ARuntimeMeshActor
{
	GENERATED_BODY()
	
public:	
	UPROPERTY(EditAnywhere)
	UMaterialInterface* Material;

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;


public:	
	// Sets default values for this actor's properties
	ABasicPMCStyleRMC();
	// Called every frame
	virtual void Tick(float DeltaTime) override;

};
```

続いて、関数の実装部分です。
StaticProviderを作って、そこに頂点やインデックス、マテリアル情報などを設定していくのは、PMCと同じような考え方です。OBJファイルと同じだと思えば、そんなに混乱はないですね。Blueprintでも勿論かけますが、公式サイトではC++での実装を推奨しています。これは単純に速さのためだそうです。

```BasicPMCStyleRMC.cpp
#include "BasicPMCStyleRMC.h"
#include "Providers/RuntimeMeshProviderStatic.h"

// Sets default values
ABasicPMCStyleRMC::ABasicPMCStyleRMC() : Material(nullptr)
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

}


// Called when the game starts or when spawned
void ABasicPMCStyleRMC::BeginPlay()
{
	Super::BeginPlay();
    UE_LOG(LogTemp, Log, TEXT("BeginPlay"));
    URuntimeMeshProviderStatic* StaticProvider = NewObject<URuntimeMeshProviderStatic>(this, TEXT("RuntimeMeshProvider-Static"));

    if (StaticProvider)
    {
        // The static provider should initialize before we use it
        GetRuntimeMeshComponent()->Initialize(StaticProvider);
        UE_LOG(LogTemp, Log, TEXT("TriMat"));


        // This creates 3 positions for a triangle
        TArray<FVector> Positions{ FVector(0, -50, 20), FVector(0, 0, 100), FVector(0, 50, 0) };

        // This creates 3 vertex colors
        TArray<FColor> Colors{ FColor::Blue, FColor::Red, FColor::Green };

        // This indexes our simple triangle
        TArray<int32> Triangles = { 0, 1, 2 };

        TArray<FVector> EmptyNormals;
        TArray<FVector2D> EmptyTexCoords;
        TArray<FRuntimeMeshTangent> EmptyTangents;
        StaticProvider->CreateSectionFromComponents(0, 0, 0, Positions, Triangles, EmptyNormals, EmptyTexCoords, Colors, EmptyTangents, ERuntimeMeshUpdateFrequency::Infrequent, true);
        StaticProvider->SetupMaterialSlot(0, TEXT("TriMat"), Material);

    }
}

// Called every frame
void ABasicPMCStyleRMC::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

```
続いて、マテリアル情報を作ります。`M_Test`という名前で作成しています。ここで重要なのは、ベースカラーとしてVertex Colorを充てることです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51703/ac8e1a14-5611-3e9c-6485-c56364f1e136.png)

次に、作成した`ABasicPMCStyleRMC`をベースにしたブループリントを作ります。`BP_BasicPMCStyleRMC`とでもして、適当なフォルダに作っておきましょう。作成したブループリントのアクターをレベルに配置して、詳細パネルでMaterialを`M_Test`に設定します。これで下の画面のように表示されれば成功です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51703/e6535719-78d4-b8db-e09f-9c9ab25d1b73.png)

# 参考
- [RuntimeMeshComponent](https://runtimemesh.koderz.io/)