UE4でL-System

#はじめに
YouTubeに
https://www.youtube.com/watch?v=0o7T6Pu0WJs&list=WL&t=205s&index=65
このようなパーフェクトなL-Systemについてのチュートリアルがあったので、自分なりにコメントを追加して解説してみようと思います。

#L-Systemとは
L-Systemについてざっくりと説明します。
L-Systemは、ある文字列を定義した変換規則（ルール）に則り世代を進めどんどん変化させていくことで植物の成長等を表現するアルゴリズムです。
例えば一番最初の世代の文字列を**A**とします。
**Aの変換規則**を**「AB」**、
**Bの変換規則**を**「A」**とします。
変換規則に則り文字Aを変化させると以下のようになります。
第1世代 - A
第2世代 - AB
第3世代 - ABA
第4世代 - ABAAB
第5世代 - ABAABABA

L-Systemのその他の応用例などは[こちら](https://ja.wikipedia.org/wiki/L-system#.E4.BE.8B1.EF.BC.9A.E8.97.BB.E9.A1.9E)から参照してください。

#準備するもの
・**L_System_Tree** - Actor型

・**BranchData** - 構造体 - 内容は以下の通り
![6.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/495b046a-51f2-5130-d3d5-fef2fd94d21c.png)

・**Branch_Mesh** - Static Mesh
Modesの**Geometry**から**Cylinder**をマップ上にドラッグ&ドロップ
![11.png](https://qiita-image-store.s3.amazonaws.com/0/104467/cad7ab58-d4a2-0ad2-b41d-b563d555b04a.png)
詳細パネルでサイズを**(0.25, 0.25, 1.0)**に変更した後に項目**Brush Settings**内にある**Create Static Mesh**をクリックしてスタティックメッシュを作成します。
![13.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/e94fb4df-316d-8273-db8e-6b364bddf137.png)

これで必要最低限のものは揃ったので、次はL_System_Treeアクターに変数を追加していきます。

#L_System_Treeアクター
このアクターはL-Systemアルゴリズムを実行する本体です。
使用する変数群は以下のようになります。
![14_2.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/d7766b40-d08f-3c6b-65e1-f04624ee25a0.png)
変数BranchsはBranchData型の**配列**です。（画像の方ではアンダーバーが付いていますが、これは間違いです。）

一通り変数を追加したら、アクタにコンポーネントを追加します。
![8.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/0184781b-cc40-e06b-0bfd-7c6665939d95.png)
**Turtle** - **Static Mesh Component**
**Spline** - **Spline Component**

##関数「Generate LSystem」
L_System_Treeアクターに新しく関数「Generate LSystem」を追加します。
この関数はL-Systemの各変換ルールを文字列に実際に適用する関数です。
世代数分ループをし、初期文字列からどんどん成長させます。L-Systemを実現する最も重要な関数です。

関数を追加したら以下のローカル変数を追加します。
**Local Strings** - **String型（配列）**
![15.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/97c23e4a-5668-2529-089d-0bb1f70136a3.png)

InputsとOutputsについては何も触る必要はありません。空っぽのままでOKです。

関数の内容は以下の通りです。（画像サイズがかなり大きいです）
![20.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/b7462b0b-3b52-aa7a-0cd6-234e4d821ea0.png)

最も重要といいつつも内容はいたって単純だと思います。
最初のループは**世代数分のループ**です。２つめは変数CurrentStringに格納されている文字列を配列として取り出し、**要素数分（文字数分）のループ**を行っています。
Switch文では取り出した文字ごとに処理を分岐させています。
**文字F**が来た場合はFの変換ルールを適用し、変数NextString（次世代の文字列）へと格納されます。
Gの場合もFと同様です。
FとG以外の文字は**変換ルールはありません**ので、取り出した文字をそのまま変数NextStringへ格納しています。

では、処理が書けたらL_System_Treeアクターの**Construction Script**にGenerate LSystemを呼び出すようにノードを繋げます。
![21.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/a6aa0b9a-2318-95dc-59a5-1af1e2b2176b.png)
繋げたらL_System_Treeアクターをシーン上に配置します。
そうすると詳細パネルに編集可能な変数が表示されるはずなので、以下のように設定します。
![22.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/d3fdedc3-6a2b-2dc7-3ee3-f9644bff5e0b.png)
画像の赤で囲まれた項目のように表示されていなかったら、変数の追加の項目まで戻り**目のアイコン**をONにしてください。
画像のように設定出来たら、**Generations**を１ずつ増やしてみてください。

**Generations 0** ＝ **G**
**Generations 1** ＝ **F−[[G]+G]+F[+FG]−G**
**Generations 2** ＝ **FF[[F−[[G]+G]+F[+FG]−G]+F−[[G]+G]+F[+FG]−G]+FF[+FFF−[[G]+G]+F[+FG]−G]F−[[G]+G]+F[+FG]−G**

というようになればOKです。


##関数「Generate Tree」
この関数では準備段階で追加したStatic MeshのTurtleを操作して、タートルグラフィックス的なものを作ります。（[タートルグラフィックス](https://ja.wikipedia.org/wiki/LOGO#.E3.82.BF.E3.83.BC.E3.83.88.E3.83.AB.E3.81.A8.E3.82.B0.E3.83.A9.E3.83.95.E3.82.A3.E3.83.83.E3.82.AF.E3.82.B9))

関数を追加したら、以下のローカル変数を追加します。
![23.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/1518ecf6-de53-5a7b-97ac-4b09926dfdbf.png)

InputsとOutputsは空っぽです。

処理内容はこちらです。
![24.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/2c8728a6-ea45-59d5-106e-8a2a5c549194.png)
![39.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/ab558233-0a5c-e009-884e-7e69bcd677dc.png)
![26.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/425d2322-fba2-90c6-fe82-d8ebc7e959ec.png)

この処理では各文字（F、+、-、[、]）ごとにTurtleに対する操作を記述しています。
**F** - Turtleを前方に移動し、移動後の位置を記録
**+** - Turtleを**右**にAngle度回転
**-** - Turtleを**左**にAngle度回転
**[** - Turtleのトランスフォーム情報を記録＆ブランチの作成
**]** - Turtleのトランスフォーム情報を復元

##関数「Cast To Vector Array」
この関数は引数でトランスフォーム情報を受け取り、位置を表すVectorを取り出し、配列に格納し直して返す処理をします。ちょっとした便利関数です。

ローカル変数に**Vector型の配列**を追加します。名前は**Local Vectors**とします。
![27.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/eb15367c-8b07-92b2-8b94-94dfdf0c537a.png)
続いてInputsに**Transform型の配列**を追加。名前を**Transforms**にします。
Outputsは**Vector型の配列**で名前を**Vectors**とします。
![28.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/d6ca075a-b68b-a269-6ac4-3a501072335a.png)

処理内容は以下の通りです。
![29.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/a5ac3ef0-75c3-f17e-d022-a46a22f77cbb.png)


##関数「Generate Spline Mesh」
ここではGenerate Tree関数で記録されたTurtleの位置情報を元にSpline Meshを配置していきます。この関数により今まで文字列でしか表現されていなかったL-Systemを目で見える状態にします。

ローカル変数を追加します。
**Float型** - **Local Branch Scale**
**Spline Mesh Component型** - **Local Spline Mesh**
![30.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/e50b3a77-6b97-fbd7-a7d1-26d0a07da353.png)

InputsとOutputsは空っぽでOKです。

処理内容は以下の通りです。
![31.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/bfbd7d2c-96c7-f700-6819-52021cb48911.png)
![32.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/d277cfe5-3bd2-cfb2-c153-7a2c7ac21d54.png)
![33.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/7c573aaa-d347-e0d4-0a5f-40258d46ec8c.png)
![34.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/b40529fd-8c79-a536-6fa8-344446e28417.png)

#最終動作確認
以上でL-Systemアルゴリズムを作成し、実際に描画させるところまで出来ました。
では、Construction Scriptに作成した関数を配置します。
![35.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/cbfcf822-f25c-46b5-86c0-2c978248ff6e.png)

無事にコンパイル出来たら、マップ上にL_System_Treeアクターを配置し、詳細パネルで以下のように編集してください。
![36.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/68fc1c55-3225-7e0e-44f7-2fcc4adeb440.png)

値を設定するとL_System_Treeアクターは以下のように変化するはずです。
![37.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/e506b2e8-07ae-1289-cb68-c28b6ddb7c65.png)

あとは、**Generations**を増やすと木がどんどん成長していきます。
一つ注意点として**Generationsの値を極端に増やさない**でください。
Generationsを**6**にしただけでも４，５分ほどUE4がフリーズ、もしくはクラッシュします。（PCの処理性能にもよると思いますが..）
Generationsが6の場合の文字数をカウントしてみると
![38.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/192bf293-be78-6453-64d9-be38693beae3.png)
このようになりました。

L-Systemの作り方は以上です。お疲れ様でした。

#おまけ
##フラクタルツリー
L_System_Treeアクターの各変数を以下のように設定すると
![40.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/7a01e0f8-a60e-b813-ba30-8309d85380e9.png)
フラクタルツリーと呼ばれる自己相似性を持つ木が生成されます。
![41.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/d61197bf-4b4f-cdc1-1cb3-8cc4243c75f8.png)

##ランダムな回転度数
関数「Generate Tree」内の回転処理部分にて、以下のように度数をランダムする処理を挟むと
![42.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/663ab91f-7d31-33b5-500b-7d0fc9ec96bf.png)
少し現実に近い見た目の木も生成できます。
![43.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/3ebc9337-5d13-ce9d-27c4-34b5e8b322f0.png)


#編集履歴
2017/02/11 関数Generate Tree内のSwitchのー（マイナス）ピンから繋がるノードの処理を修正