【UE5】Geometry Scripting：ブール演算と複数マテリアル

[ThroughBP-Eng]: https://docs.unrealengine.com/5.2/en-US/geometry-scripting-through-blueprints-in-unreal-engine/
[Reference]: https://docs.unrealengine.com/5.2/ja/geometry-scripting-reference-in-unreal-engine/

:::note info
確認したバージョンはUE5.2.1です。
:::

# 参考URL

- [Geometry Scripting入門 - UE公式ドキュメント](https://docs.unrealengine.com/5.2/ja/introduction-to-geometry-scripting-in-unreal-engine/)
    - [ブループリントによるジオメトリスクリプト処理 - UE公式ドキュメント](https://docs.unrealengine.com/5.2/ja/geometry-scripting-through-blueprints-in-unreal-engine/)
    - [Geometry Scriptingのユーザーガイド - UE公式ドキュメント](https://docs.unrealengine.com/5.2/ja/geometry-scripting-users-guide-in-unreal-engine/)
    - [ジオメトリスクリプト処理のリファレンス][Reference]
- [Exploring Geometry Tools in UE5 | Inside Unreal - Youtube](https://youtu.be/apCSgAAkDTU)

# 基本形

公式ドキュメントの「[Geometry Scripting through Blueprints][ThroughBP-Eng]」に従うと、Boxポリゴンから Cylinderポリゴンを引き算したメッシュを作成することができる。
次のGIF動画は、公式ドキュメントと同じやりかたで、Boxポリゴンから Sphereポリゴンを引き算したもの。
![20230823_01_BooleanOperation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/f66d34e3-def6-f28d-7bf4-4e89313f4a0a.gif)

## Blueprintグラフはこんな感じ

Event On Rebuild Generated Meshから、似たような名前の自作関数 Rebuild Generated Meshを呼び出している。Event On Rebuild Generated Meshに直接実装しなかったのは、単なる好みで深い意味はない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/f63f0f63-27d9-0209-b067-cc6e850e292f.png)

:::note warn
Event On Rebuild Generated Meshを使うには、Geometry Scriptプラグインを有効にして、Generated Dynamic Mesh Actorを継承した Blueprintアクタを使う必要がある。
:::

自作関数 Rebuld Generated Meshはこんな感じ：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/6cfdc395-fce3-300a-d944-e2fc02d17939.png)
やっていることは見ての通りだが、大枠は

1. Target Meshに Append Box関数で Box形状のポリゴンを追加。
1. Get Compute Mesh Pool, Request Mesh経由で計算用の内部 Dynamic Meshを作成。これをCompute Meshとする。
1. Compute Meshに Append Sphere Lat Long関数で Sphere形状のポリゴンを追加。
1. Apply Mesh Boolean関数で、Target Mesh (Box)から Compute Mesh (Sphere)の Booleanオペレーションを行う。

…という形。

# Box面と Sphere面それぞれに異なるマテリアルを割り当てたい

ここからは、自分で試行錯誤した内容のメモ。

Boxの面と Sphereで切り取った球面それぞれに異なるマテリアルを割り当てたい。具体的には以下の画像のようにしたい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/573a145c-5f7d-6a53-e0e2-7b5df65c50ce.png)

- もともとのBoxには、Starter Contentの M_Ground_Grassを割り当てている。
- Sphereで切り取った面には、Start Contentの M_Ground_Gravelを割り当てている。
    - 地面のテクスチャの密度が粗かったので、UVにスケールをかけて密度を高くしてある。

## マテリアルの割り当て

[ジオメトリスクリプト処理のリファレンス][Reference]を見てみたところ、面にマテリアルを割り当てるには、Set Material ID For Mesh Selectionを使えば良さそうだ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/3c2ba39e-e520-93aa-1c68-ca43960424dc.png)
２番目の引数に Selectionとあるように、どうやらマテリアルIDを割り当てたい面を選択したものを渡す必要があるようだ。

Boxポリゴンについては、作った直後に「全てを選択」して「マテリアルIDを割り当て」することでうまく行った。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/26d0fe75-a90e-e425-4dec-b4583d7f0047.png)

Sphereで削った面については、Select Mesh Elements Inside Mesh関数で選択した。
この関数は、選択用のメッシュの内部にある面を選択してくれる。つまり、削るのに使った Sphereそのものを使えば、削ってできた面を選択できるということである。
なお、Sphereそのもので選択すると計算誤差で「ぎりぎり含む／含まない」が発生するので、Shell Distanceに1.0を与えて、「1cm大きいメッシュで選択」するようにしている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/6a7dbff0-a0b4-8bf5-fb6d-5e5a9526864c.png)

マテリアルの割り当て自体は Static Mesh Componentなどと同様。Generated Dynamic Mesh Actorがもともと持っている Dynamic Mesh Componentに対して、Set Materialするだけでよい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/b260a76e-33c9-7f87-2e10-e8879bc79611.png)

## UVのスケール

Sphereで削った面のマテリアルのタイリングを細かくするために、UVにスケールをかけている。これは Scale Mesh UVs関数を使う。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/ad07b8ba-a720-f192-0a8b-bb3a5dc1ee70.png)

- Scale Originを中心に拡大縮小してくれる
- Selectionに何も指定しないと、すべてのUVが対象となる

今回は、引き算する前の Sphereに対して、Get UV Set Bounding Boxで UVをすべて含むバウンディングボックスを取得し、そのUVが小さい方のUV座標を中心にスケールをかけた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/72952d9d-fac6-fad3-68b7-e44ce18bd014.png)

## 最終的な Blueprintグラフ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/a1665888-856a-06ee-cb37-ffe4421a7955.png)