UE4で科学可視化やってみよう

# はじめに
## この記事について
この記事は[Unreal Engine 4 Advent Calendar 2015](http://qiita.com/advent-calendar/2015/ue4) の14日目の記事です。
昨日の記事はhima_zinnさんの[Unreal Engine 4.10.1でLeap Motionを使う](http://hima-zinn.hatenablog.com/entry/2015/12/13/000000_1)でした。明日の記事はnano06126728
さんの[ビヘイビアツリーを使ってみよう！](http://qiita.com/nano06126728/items/195bdd48582c63db5543)です。

UE4で科学可視化をやってみようという内容の記事です。UE4のノンゲーム利用案件と言えるでしょうか。
この記事の対象は、研究者で、自身のデータを使って一般公開向けに少し綺麗な絵を出したいんだけどと思っている人とか、CAVEとかの大掛かりなVRは高すぎて手がでないけど流行りのHMDでVRやってみたいと思ってる人、になると思います。が、ゲーム方面にも全く利のないこともないとは思います。
UE4アドベントカレンダーなのですが、半分くらい別ツールの説明になってしまっています。また余計な話もちょいちょい入ってしまっています。

この記事中でのUE4のトピックは「ジオメトリキャッシュ的なものよるアニメーションをゴリ押しで再生してみました」です。
(UE4をバリバリ使っている人たちからするとショボい内容かなとは思いますが！ハードルは下げていく所存デス)
応用するとたとえば、DCCツールなどの流体シミュレーション(もちろんもっと精度のいい本格的な流体シミュレーションのデータでも構いませんが)で作った海のアニメーションをUE4で再生することができたりします。（ゲームに使うには重いかもしれませんケド）

こんな感じになりました。(クリックするとYouTubeへ飛びます)
[![最終結果動画](http://img.youtube.com/vi/NqJF146tXAI/0.jpg)](http://www.youtube.com/watch?v=NqJF146tXAI)

ジオメトリキャッシュとはなんぞやというのは[こちらの記事](http://pc.watch.impress.co.jp/docs/topic/feature/20150529_704317.html)の最後のあたりで少し解説されています。科学可視化の世界ではフリップブックアニメーション（ジオメトリ）などの機能名で実装されていたりします。時系列データ間のポリゴンに相関がないので、なるべく速く、なるべくインタラクティブ性を落とさないようにアニメーションするには基本的にはジオメトリキャッシュしか手段がありません。ゲームの文脈でアニメーションというと移動回転拡縮、ボーンアニメーションや頂点モーフなんかを思い浮かべますが、それらをすべて頂点にBake（ベイク、焼き付け）してしまったアニメーションと考えると理解しやすい人もいるかもしれません。データ量は膨大なものになります。



## さて、科学可視化とはなんぞや
科学的に得られたデータを科学的に可視化することです。単に可視化というと、取り調べの可視化とか情報可視化と混同してしまってややこしいので、科学可視化と呼んでいます。英語ではScientific Visualizationといいます。

科学可視化の中でも今回はスーパーコンピュータなどで計算するような科学計算、科学シミュレーションで得られたデータの可視化を想定しています。その中でも特にシミュレーション空間が三次元のデータを対象にしたいと思います。ボリュームデータと呼んだりもします。データ化さえされていれば観察や観測から得られた三次元の実験データも同様に処理できると思います。(CTやMRIの医療画像や、3Dスライス画像を撮影できる顕微鏡で撮った画像、レーダー観測で得られた雨雲や雨粒のデータなど)

## スパコンシミュレーションデータの可視化フロー
スパコンなどで計算されたデータを普通はどのように処理しているのかというのは、少し古いですが[このPDF](http://www.godac.jamstec.go.jp/catalog/data/doc_catalog/media/JAM_RandD13_03.pdf)によくまとめられています。
このPDFの2.1にデータフローモデルという項があります。得られた生データをフィルタリング(加工や抽出など)して、マッピング(可視化処理)して、レンダリングするという流れです。可視化処理というのはデータから等値面を生成したり、流線を生成したりスライス面を生成したりすることです。なんとなく「可視化処理」と聞くとレンダリングまで含みそうですが、狭い意味での「可視化処理」というのはポリゴン(ジオメトリデータ)などを生成したり物理量を色に割り当て(←ある数値を決まった規則で別の数値に置き換えることをまさにマッピングといいますが)をしたりする段階のことであって、そのポリゴンをレンダリングするかどうかは関係ありません。しかしレンダリングをしないと「視る」ことができないので、結局はレンダリングをすることになります。

大雑把な感覚で例外もありますが、生データからフィルタリング、マッピング、レンダリングの工程を経ることによってデータ量は桁違いに落ちていきます。例えば、テラバイト級の生データがフィルタリングやマッピングによってギガバイト級になり、最終的には二次元の絵にレンダリングされるのでメガバイト級のデータになります。時系列データだとすると生データはそのステップ数倍になり、最終的には高々数ギガバイト程度の動画になるといったイメージでしょうか。(ただ、今回用意したサンプルはマッピング段階ではそんなにデータ量落ちません。生データ25MBが4MB～24MBになる程度です。)

たいていの場合、(科学)可視化ソフトと呼ばれるものを使って上記の処理を行います。上記の3つの過程をワンストップで行うことができます。ただし、研究に使われるものなのでよっぽど気をつけないと簡素な絵になりがちです。というよりは、簡素でないと困る、というのが本当のところです。しかし、この簡素な絵だけを一般に見せた時にインパクトを与えられるかというと必ずしもそうではありません。よほど目を引く題材でもない限り難しいのではないでしょうか。それは研究の本質ではないと言われればそのとおりなのですが。。。

## UE4は可視化ソフトではありません
ところで、「UE4で」というタイトルですが、UE4は当然のごとく可視化ソフトではなく、ゲームエンジンです。可視化処理の機能は持っていません。では何ができるかというと、レンダリングができます。それもかなりリアリスティックな絵をリアルタイムにレンダリングすることができます。プラグインを作ってマッピングも実行時にさせることはできそうですが、時間があればやってみることにして今回はUE4にレンダリングさせることに的を絞りたいと思います。

インタラクティブ性には段階が2つあります。ウォークスルーやフライスルーできる段階と、これに加えてVR空間にあるものに干渉(可視化で言えば何かパラメータを変更したりなど)できる段階です。今回はそのうち1段階目だけ実現するということになります。

(2段階目は既存の可視化処理ライブラリ(例えばVTK)を引っ張ってきて、生成されたジオメトリをProcedualMeshComponentにつっこむととりあえずはいけそうな気がします。)
レンダリングさえしっかりしていれば「一般公開イベントに行ったけどしょっぼいCG見せられただけだった」みたいなことをブログに書かれずに済むかもしれません。(経験者は語る)

## 綺麗な絵を作りたいだけならUE4でなくてもいいのでは？
もっともな意見ですが、ここではVR化も踏まえてリアルタイム性も重視したいと思います。

実際レンダリングには、レイトレーシングレンダラーのPOV-Rayあたりがよく使われているようです。
私は普段BlenderのCyclesレンダーでやっていたりします。最近はBlenderレンダーも悪くないなと思っていますがもっぱらCyclesです。BlenderゲームエンジンはQuadBufferStereoにネイティブ対応している点はたいへん素晴らしいのですが、それ以外は少し扱いづらい気がしました。UE4もQuadBufferStereoにネイティブ対応してくれると、科学可視化関連で使われることが多くなるのではと思っています。プラグイン作って実現した、という報告が[フォーラム](https://forums.unrealengine.com/showthread.php?57519-Unreal-Engine-on-a-multi-projector-wall-display)にあるにはあります。
POV-Rayはカメラパスの設定が非常に難しいので、Blenderでカメラパスだけを作ってPOV-Ray向けにエクスポートしてレンダリングはPOV-Rayでといったハイブリッド的な使い方をしているといったことも聞いたことがあります。最近話題の[UT-Heart](https://www.youtube.com/watch?v=tBdFv28EEq0)(の映像制作)はMayaを使っているそうです。

## 簡素な絵でないと困るのではなかったか？
データを色にマッピングする場合、色が変わってしまうライティング、シェーディング(陰影付け)すら行なわないこともあるくらい繊細な問題ですが、それはそれこれはこれ、です。どんな絵を作るかというのは目的、主に誰に見せるかによって変えるべきであると考えています。

ゲームエンジンに載せるには膨大すぎるポリゴンが生成されることもあり、普段の可視化処理では1fpsでもでれば良い方だよ、なこともある世界ですが、少なくとも30fps(VR化の際には要求fpsを満たすように)程度は出せるように涙をのんで適宜リダクションを行うことにします。この辺りの、最適化やデータリダクションの認識に、古くからの産業/学術VRコンテンツ開発者と最近のコンシューマVRコンテンツ開発者とのあいだで違いが生じているなぁとは思います。中で使ってる分、というよりは開発者が唯一のユーザーである限りはCADデータを1ポリゴンもカリングせずに出して10fps、とかでも構わないとは思うんですよね。


# 可視化処理をする
UE4に可視化処理機能がないということは、何か肩代わりをしてくれるソフトを探す必要があります。今回はオープンソースソフトの汎用可視化ソフトである[ParaView](http://www.paraview.org/)を使いたいと思います。

## データ形式
最終的にUE4のスタティックメッシュとしてインポートをしたいので、その前段階でFBX(かOBJ)形式に変換しなければいけません。ParaViewはFBXエクスポータを持っていないので、形式変換のためだけに間にBlenderを挟みます。データのリダクションを行う場合はBlenderのDecimateモディファイヤなどを使います。

- ParaViewで可視化処理を行い、そのジオメトリデータをX3D形式でエクスポートする
- BlenderでX3Dデータをインポートし、モディファイヤなどを使いつつ、FBX形式でエクスポートする
- UE4でFBXデータをインポートする

ジオメトリアニメーション(ジオメトリキャッシュ)を格納できる形式としてAlembicというものがあります。しかし今のところ知る限り有名なところでは、Mayaでのみエクスポートが可能、CryEngineでのみインポート可能のようです。したがって今回は上記のようにゴリ押しします。(書き上げ後追記：3DSMAXも対応しているらしい。また、Unityでの対応が発表されました。[参考リンク](http://www.4gamer.net/games/210/G021014/20151204090/))

## 生データの用意
今回はサンプルとしてABC流(ABC Flow)と呼ばれるデータを用意しました。[ダウンロード(約60MB)](https://www.dropbox.com/s/ugqou04z7kp5ka8/ABCflowAnim10.zip?dl=0)。データの形式はVTK(ascii,legacy)です。
ABC流は、
`v = (B*cos(y) + C*sin(z), C*cos(z) + A*sin(x), A*cos(x) + B*sin(y))`
で表される三次元の速度の流れ場です。A:B:C=1:1:1とすることが多く、x,y,zは座標です。空間のサイズは100x100x100です。
ちなみに三次元空間で、温度のようにある1点において1つのパラメータしか持たないものをスカラーデータ、速度のようにある1点において3つのパラメータを持つものをベクトルデータといいます。
今回はA、B、Cの値を変化させて作成した時系列データを10ステップ分用意しました。本来は100ステップあるデータなのですがダウンロードサイズが大きくなりすぎるので、10ステップごとのデータだけ抜き出しました。ですのでアニメーションを再生してもカクカクとした感じになります。

## ParaViewで可視化処理
ParaViewで可視化処理を行います。今回はとりあえず等値面と流線を作りたいと思います。等値面はIsoSurfaceやContour、流線はStreamLineと言います。
ParaViewをインストールしていない方は[ダウンロード](http://www.paraview.org/download/)＆インストールしてください。今回ParaViewのバージョンは4.4.0を使います。

### 生データ(VTK形式)の読み込み
先ほどダウンロードしたzipファイルを展開してください。
ParaViewを起動し、左上のあたりのOpenアイコンをクリックします。![スクリーンショット 2015-11-18 19.19.27.png](https://qiita-image-store.s3.amazonaws.com/0/34714/2b6fcecd-e9b3-16a8-8344-0215ebae3841.png)

連番ファイルは自動的に1つの時系列データとして扱われます。データを選択してOKボタンをクリックします。(ファイル名の左の三角を押すと展開され、個別のファイルを選択することもできます。)
![スクリーンショット 2015-11-18 19.19.41.png](https://qiita-image-store.s3.amazonaws.com/0/34714/ade42367-fd00-6ff7-ae13-3fae9dae9f6e.png)

するとPipeline Browserにデータが追加されます。デフォルトでは自動で適用されないので、左の真ん中辺りにあるApplyボタンをクリックします。
![スクリーンショット 2015-11-18 19.19.49.png](https://qiita-image-store.s3.amazonaws.com/0/34714/453b6b95-68f5-8a90-d519-50722e3b49fb.png)

すると、右側の画面にデータ範囲を示す枠が表示されます。
![スクリーンショット 2015-11-18 19.19.55.png](https://qiita-image-store.s3.amazonaws.com/0/34714/7b2bcc9b-e4d1-3a1d-e9e9-abfcfac4ccb1.png)

### 等値面を生成する

次に左上にある電卓のようなCalculatorアイコンをクリックします。
![スクリーンショット 2015-11-18 19.20.04.png](https://qiita-image-store.s3.amazonaws.com/0/34714/180e6b27-cb94-acaf-c2ce-b0a94e567011.png)

左側の真ん中より少し下のあたりのテキストボックスにmag(volume_vectors)と入力します。マウスで該当するボタンをクリックして入力することもできます。volume_vectorsはVectorsというプルダウンメニューの中にあります。
![スクリーンショット 2015-11-18 19.21.12.png](https://qiita-image-store.s3.amazonaws.com/0/34714/84b03177-71b9-e330-7185-3a121d5b9954.png)

次に、上の真ん中辺りのLast Frameボタンをクリックして、最後のタイムステップを表示させます。その右横の数字が9になればOKです。
![スクリーンショット 2015-11-18 19.21.27.png](https://qiita-image-store.s3.amazonaws.com/0/34714/820f7d7a-c2d9-2b0b-e602-0ae1bf04bcbf.png)

左上にあるContourボタンをクリックします。
![スクリーンショット 2015-11-18 19.21.32.png](https://qiita-image-store.s3.amazonaws.com/0/34714/d7d353db-6662-06de-89b5-35fe4b7a724a.png)

すると、volume_vectorsのマグニチュードを計算した値の中から、3.000～の値の場所にポリゴンが生成されました。これが等値面です。（もしデータ空間が二次元だった場合、それは等値線-Isolineと呼ばれるものになります。地図に書かれている「等高線」はその一種です。）
![スクリーンショット 2015-11-18 19.22.20.png](https://qiita-image-store.s3.amazonaws.com/0/34714/9db22a15-1c19-0355-8f05-c7dc5d4e73bb.png)

Vallue Rangeをこのように変更し、Coloringをvolume_vectors Magnitudeに変更するとこのようになります。数値を入れる欄の右側にある＋ボタンーボタンの下にあるボタンをクリックすると最小値と最大値の間の値を好きな分割数で割ることができます。
![スクリーンショット 2015-11-19 00.30.02.png](https://qiita-image-store.s3.amazonaws.com/0/34714/01d36a43-d0b2-f20a-56ab-c2395a77bba5.png)

### 流線を生成する

Pipeline Browserのdata_*をクリックして選択します。その後、上のあたりにあるStream Tracerアイコンをクリックします。
![スクリーンショット 2015-11-18 19.24.07.png](https://qiita-image-store.s3.amazonaws.com/0/34714/620b1711-edee-ad67-c6ee-d20c21f6b127.png)

すると白い線が現れます。これが流線です。
![スクリーンショット 2015-11-18 19.24.26.png](https://qiita-image-store.s3.amazonaws.com/0/34714/bd84163a-0f24-51fe-b779-ca81f287a14a.png)

PipeLine BrowserのContour1の横にある目をクリックすると等値面を一時的に不可視にすることができます。
![スクリーンショット 2015-11-18 19.24.35.png](https://qiita-image-store.s3.amazonaws.com/0/34714/33cd4f94-b875-7504-9d90-5f1b04eea5c3.png)

線では味気がないのでチューブにします。上部のメニューからFilters->Alphabetical->Tubeを順にクリックしていきます。
![スクリーンショット 2015-11-18 19.24.56.png](https://qiita-image-store.s3.amazonaws.com/0/34714/35cc1ac1-ccd5-1deb-9976-f20bdda589b4.png)

するとチューブになります。左の下のあたりにあるRadiusを0.3くらいにすると細くなり、ちょうどいい感じになります。
![スクリーンショット 2015-11-18 19.25.23.png](https://qiita-image-store.s3.amazonaws.com/0/34714/56efaae3-2110-cb04-e9c9-9eaa5a81e473.png)

ColoringをVorticityに変更してみましょう。Vorticityは渦度という意味で、渦の強さを示すパラメータです。渦の中心あたりが真っ赤になっており、渦が強いことがわかります。
![スクリーンショット 2015-11-18 19.25.49.png](https://qiita-image-store.s3.amazonaws.com/0/34714/3c6b71db-fbde-fcec-8529-867892f4869d.png)

### ParaViewでの可視化まとめ

この段階から少し透明度の変更やカメラワークなどを追加すると次のようなムービーを作ることができます。カメラワークは一応、カメラの移動パスと注視点、カメラの上方向を決めることができます。

(クリックするとYouTubeへ飛びます)
[![ParaView動画](http://img.youtube.com/vi/iVW0nZFEZZk/0.jpg)](http://www.youtube.com/watch?v=iVW0nZFEZZk)

上記過程でContour1を不可視にした場合は、もう一度目をクリックして見える状態に戻してください。

### ジオメトリデータをエクスポートする
ParaViewには、ある時間ステップのジオメトリデータをエクスポートする機能はあるのですが、時系列のジオメトリデータを全て自動的にエクスポートする機能がありません。そこでPythonを使って自動化します。
上部メニューのTools->Python Shellを順にクリックしていきます。
するとPython Shellというウィンドウが出現します。
![スクリーンショット 2015-11-18 19.26.46.png](https://qiita-image-store.s3.amazonaws.com/0/34714/04fa77a3-0150-8367-4d1b-c090f799b873.png)

そのShellに以下のPythonスクリプトを1行ずつコピペして実行するか、[ダウンロード](https://www.dropbox.com/s/w0z989bcsexxf49/paraview-x3d-exporter.py?dl=0)してRun Scriptボタンから選択、実行します。(コピペの場合は全行を一度にコピペしてもうまく動きません。)すると指定ディレクトリにx3d形式のジオメトリデータがエクスポートされます。

```py3:paraview-x3d-exporter.py
Start = 0
End = 10
savedir = 'T:/ABCflowAnim10/x3d/'  #<-ここはあなたの環境に合わせて必ず変更してください。最後にスラッシュが必要です。また、保存先のディレクトリは自動生成されません。存在しないディレクトリを指定した場合エラーになります。
animationScene1 = GetAnimationScene()
renderView1 = GetActiveViewOrCreate('RenderView')
animationScene1.PlayMode = 'Snap To TimeSteps'
animationScene1.AnimationTime=Start
for time in range(Start, End): #この次の3行は行頭にタブ(インデント)が必要です。
    timeStr = '%04d' % time
    ExportView(savedir+timeStr+'.x3d', view=renderView1)
    animationScene1.GoToNext() #ここまでコピペ実行したらもう一度エンターキーを押します。するとfor文の内容が実行を開始します。
```

指定したディレクトリにエクスポートされていることを確認します。0000.x3dが異様に大きいですね。。。流線のみで等値面が全く無い時間ステップなのでサイズが最も小さくないとおかしいのですが。。。
![スクリーンショット 2015-11-18 19.43.40.png](https://qiita-image-store.s3.amazonaws.com/0/34714/09b1b9fc-b161-e6c4-f092-9a9faf212b0b.png)



これでParaViewでの操作は終わりです。

### ParaViewあれこれ

ちなみに、ParaViewは可視化処理そのものもPythonスクリプトで制御できます。定形処理であれば完全に自動化が可能です。GUIとPythonの対応関係はTools->Start Traceを使うと見ることができます。Start Traceを実行したあと、上記の可視化処理を行い、Stop TraceするとPythonスクリプトが別ウィンドウに表示されますので保存してください。

ParaView、よく使われているソフトのわりにバグが多い印象です。画像やジオメトリデータを書き出している際、何かの拍子に壊れたデータが吐き出されたりします。。。
また今回、色についてはデフォルトの赤白青のグラデーションを使いましたが、たくさんのプリセットから選ぶことができます。そのプリセットを選んでいるとこれまた何かの拍子に色が反映されなくなったりします。つらいです。。。

## Blenderでデータ整形と形式変換
ここからはBlenderの出番です。
Blenderをインストールしていない方は[ダウンロード](http://www.blender.org/download/)＆インストールしてください。今回Blenderのバージョンは2.76bを使います。

### 変換用blendファイル
変換のためのPythonスクリプトを内包したblendファイルを用意しました。[ダウンロード(約400KB)](https://www.dropbox.com/s/c3q3k6jmg6d6sxe/X3D2FBX.blend?dl=0)。
[2.8系用ダウンロード(約400KB)](https://www.dropbox.com/s/3bhsnhoqztov3lo/X3D2FBX_28.blend?dl=0)

### 変換
ダブルクリックして開くとこのようなウィンドウが出ます。
x3dファイルがあるディレクトリとfbxをエクスポートするディレクトリを指定します。
また、何番から何番までを変換するか指定します。(0番が異様に大きいのでデフォルトでは1番から9番までを変換するように指定しています。)
ParaViewでPythonを使用した時と同様エラー処理は入っていませんので気をつけてください。ファイルパスの最後にスラッシュを忘れないように、など。同名のファイルは上書きされます。真ん中の下あたりにある、Run Scriptボタンをクリックすると変換が開始されます。
![スクリーンショット 2015-11-19 09.48.11.png](https://qiita-image-store.s3.amazonaws.com/0/34714/12a96e24-4459-3af8-4f76-d544db3aa9d8.png)
データのスケールを変更したりポリゴン数削減(Decimate)などもここでやってしまいます。
ParaView上では100x100x100の大きさでした。Blender上でも100x100x100です。これをこのままエクスポートしてUE4へ持って行くと10000x10000x10000の大きさになってしまいます。スケール変換はBlenderでエクスポートする前かその時、UE4でインポートする時かその後、の好きなタイミングで実行することが可能ですがどのタイミングが適切かというのは各々のやり方に依存すると思います。スケルタルメッシュではないのであまり気にしなくても良いような気もします。スケルタルメッシュをBlenderからUE4に持って行く際の重要な情報は[こちら](http://rarihoma.xvs.jp/2015/03/14/1/)によくまとめられています。

### Blenderあれこれ

ちなみにBlenderもPythonで制御することが可能で、いろんなことが自動化できます。ツールチップにPythonの関数が併記されているのでどの機能がどんな関数名なのかがほぼ一目瞭然です。ほぼと言ったのはそうではないことがあるからで、ここでは詳しく書きませんが、プルダウンリストなどの場合、そのパラメータを設定する関数ではなくGUIに関する関数名が表示されたりします。また、引数に関しては表示されないので、同じ動作をさせようとするとGUIの方では暗黙的に渡している引数を、スクリプト上では明示的に指定してやる必要があったりもします。

UE4にはこういった「制作作業そのものを自動化できるスクリプト環境」というのはないですよね？おそらく、ゲームなど1つのものを作りこむことが主な用途なので、定形処理を自動化したいという要求があまりないのだろうな～と思っています。もしあったら吸いません。まあなくてもメッシュのインポートは一括でできますし、パラメータも表で一括変更できるのでそんなに手間ではないのかもしれません。

私の場合、普段はここからBlenderとCyclesレンダーとPythonスクリプトを使って映像制作をしています。全天周画像も簡単に作れますので興味のある方はしらべてみると楽しいと思います。が、綺麗にレンダリングしようとするといかんせん時間がかかるかかる。。。

# UE4
下準備が終わり、ついにUE4のパートまでやってきました。
一応説明すると、UE4は登録が必要ですが、基本的に無料で使えます。特に今回は用途が可視化、ビジュアリゼーション、いわゆるノンゲームなので完全に無料(のはず)です。インストールがまだの場合は、[ダウンロード](https://www.unrealengine.com/ja/what-is-unreal-engine-4)＆インストールしてください。
今回UE4のバージョンは4.10.0を使います。

やりたいのは、ジオメトリキャッシュ的なデータをUE4上で再生することです。これをできることに言い換えていくと、

 * ジオメトリキャッシュ的なデータをUE4上で再生する。
 * 連番のオブジェクトを高速に切り替えて表示する。
 * 連番のオブジェクトを最初は全て不可視にしておいて、個々のオブジェクトが表示されるべきタイミングで可視に切り替え、しかるべき時間経過後また不可視にする。

こうなりました。スマートではない気がするけれどこれなら実装はできそうです。

## UE4の起動とプロジェクト作成
(いちおうせつめいします)
EpicGamesLauncherを起動してログインします。
するとランチャーが起動します。4.10.0をダウンロード＆インストールし、4.10.0のLaunchボタンをクリックします。
![スクリーンショット 2015-11-19 22.15.43.png](https://qiita-image-store.s3.amazonaws.com/0/34714/8fd859b7-8a1d-556e-0757-16a487f4f04e.png)

スプラッシュスクリーンが表示され、起動します。
![スクリーンショット 2015-11-19 22.16.01.png](https://qiita-image-store.s3.amazonaws.com/0/34714/ba028810-2901-3dd5-5178-be84e7d6025a.png)

NewProjectタブ、Blueprintタブ、Blankテンプレートを選択します。
保存場所にはそこそこ容量のある場所を選んでください。その隣のボックスにプロジェクト名を入力して、CreateProjectボタンをクリックするとプロジェクトが作成されます。
![スクリーンショット 2015-11-19 22.16.22.png](https://qiita-image-store.s3.amazonaws.com/0/34714/e7dd7e3b-727e-488c-12ad-ae6dbc119ba8.png)

少しするとこの画面が表示されます。この画面をレベルエディタと呼びます。
![スクリーンショット 2015-11-19 22.25.40.png](https://qiita-image-store.s3.amazonaws.com/0/34714/9fa887c7-95b5-660f-1430-4442792c711e.png)

## FBXファイルのインポートとマテリアル設定

ContentBrowserのImportボタンを押してfbxファイルを全て選択して開くボタンを押すか、エクスプローラ(Windows)でfbxファイルをすべて選択してContentBrowserにドラッグアンドドロップします。
![スクリーンショット 2015-11-19 22.27.05.png](https://qiita-image-store.s3.amazonaws.com/0/34714/91e0ec1e-f672-4232-bd1e-46cf04340f19.png)

少しすると、インポート設定の画面が現れます。
設定は画像と同じようにしてください。特にGenerate Lightmap UVsのチェックは外すようにしてください。インポートにものすごく長い時間がかかってしまいます。
ImportAllボタンをクリックすると同じ設定で一括インポートされます。
![スクリーンショット 2015-11-19 22.27.40.png](https://qiita-image-store.s3.amazonaws.com/0/34714/fb26a362-c8ed-a123-b3ac-d42ad45717a2.png)

インポート中はこんな画面です。
![スクリーンショット 2015-11-20 01.20.03.png](https://qiita-image-store.s3.amazonaws.com/0/34714/f028509f-bf57-d8dd-4019-db365bcc9129.png)

無事インポートされました。この中からVertexColorというマテリアルをダブルクリックしてください。VertexColorと名前がついていますが、まだマテリアルの中身が全く設定されていませんのでこれから編集をします。
![スクリーンショット 2015-11-20 01.21.14.png](https://qiita-image-store.s3.amazonaws.com/0/34714/21d951d9-a9a2-e5c4-86ca-326b074f13c3.png)

マテリアルエディタが表示されます。2つのノードが重なっているためドラッグしてずらします。
![スクリーンショット 2015-11-20 01.22.11.png](https://qiita-image-store.s3.amazonaws.com/0/34714/e8cbb72b-01e5-26fb-09c1-5c0f6460608b.png)

今回は頂点カラーを使って色を付けたいので、そのように編集していきます。右クリックしてvertexと入力するとVertexColorというノードが候補に表示されるのでクリックします。
![スクリーンショット 2015-11-20 01.25.25.png](https://qiita-image-store.s3.amazonaws.com/0/34714/201e6ecb-c1cd-c693-256a-546ec568faae.png)

ノードが作成されました。
![スクリーンショット 2015-11-20 01.27.04.png](https://qiita-image-store.s3.amazonaws.com/0/34714/8a23f3b3-e336-0e69-687d-26c5a51c179b.png)

Vertex Colorノードの白いピンから右のノードのBase Colorピンまでドラッグアンドドロップして線を引きます。
![スクリーンショット 2015-11-20 01.27.39.png](https://qiita-image-store.s3.amazonaws.com/0/34714/630b8ae4-a1aa-dd29-3cb2-4013aa4ec8f7.png)

次に左のDetailsタブのMaterialの項目の中の、Two Sidedにチェックを入れます。こうすることでポリゴンを裏から見た場合でもカリングされずに表示されるようになります。そして、左上にあるApplyアイコンをクリックして適用します。
![スクリーンショット 2015-11-20 01.31.20.png](https://qiita-image-store.s3.amazonaws.com/0/34714/909c256c-0825-aab6-5a61-4158da8159d2.png)

レベルエディタに戻って、サムネイルが更新されると、色が付いているのがわかります。
![スクリーンショット 2015-11-20 01.41.22.png](https://qiita-image-store.s3.amazonaws.com/0/34714/9dfb6de3-6fa1-56e5-b051-d5ee4f2ab083.png)

試しに0009をContentBrowserから上の画面の中の市松模様の床の上ににドラッグアンドドロップしてみましょう。すると画面が真っ暗になってしまいました。右クリックをしながらWASDキーでフライスルーすることができますので移動して、配置したオブジェクトを探してみましょう。
![スクリーンショット 2015-11-20 01.49.57.png](https://qiita-image-store.s3.amazonaws.com/0/34714/29f7dff6-c602-eb71-4711-ca2317c5c59f.png)

実は、左後ろのあたりにオブジェクトが配置されています。しかし全体的に暗めですね。これを解決するために、左上のModesタブの中のLightsをクリックしてください。その中からSky Lightをドラッグアンドドロップしてください。
![スクリーンショット 2015-11-20 01.53.55.png](https://qiita-image-store.s3.amazonaws.com/0/34714/757f2595-53be-a5bc-94bb-ab1949abf6ff.png)

すると良い感じの明るさになりました。
![スクリーンショット 2015-11-20 01.56.00.png](https://qiita-image-store.s3.amazonaws.com/0/34714/0933b4ee-e254-0a0f-d4de-f7050926d5c3.png)

少しこのままフライスルーしてみます。あー。いいですね。陰だけじゃなくて影がついてるのがいいですね。リアリスティック！セルフシャドウ！グローバルイルミネーション力を感じます。
![スクリーンショット 2015-11-20 02.10.50.png](https://qiita-image-store.s3.amazonaws.com/0/34714/9cd6fa46-e26d-8b7a-cadc-5708f19c6784.png)

## ブループリント

堪能したところで、次はアニメーション再生の部分を作ることにします。

右上のあたりにあるWorld Outlinerから一度0009を削除します。右クリックメニュー->Edit->Deleteで消せます。

ContentBrowserのAddNew->BlueprintClass->Pawnと順にクリックしていきます。NewBrueprintというファイルが生成されるので、ダブルクリックします。

左上のComponentsのあたりにContentBrowserから0001～0009をドラッグアンドドロップします。そこで0001～0009が選択されたままの状態で、右側のDetailsのTagsの＋ボタンを押して追加されるテキストボックスの中にABCFLOWと入力します。そのずっと下のあたりにあるRenderingのVisibleのチェックを外します。
![スクリーンショット 2015-11-22 16.25.30.png](https://qiita-image-store.s3.amazonaws.com/0/34714/08a3a352-3aa7-3e0a-b4d9-9c3dedde3596.png)


左上の+Add Componentの中からCubeをクリックしてください。Cubeが選択されたまま、右のTransformに
Location: -5000, -5000, 5000
Scale: 100, 100, 100
と入力します。このキューブはレベルエディット中に表示するためのものです。右側のCollisionのCollesionPresetをNoCollisionに変更します。
![スクリーンショット 2015-11-22 16.25.33.png](https://qiita-image-store.s3.amazonaws.com/0/34714/ecfd1420-7f89-8e05-d4ed-ff6014fc2fa4.png)

真ん中の画面をEventGraphに切り替えて、ブループリントを組んでいきます。最終的にこんな形になります。順に説明していきます。
![スクリーンショット 2015-11-22 19.34.33.png](https://qiita-image-store.s3.amazonaws.com/0/34714/dacf1a1f-8c82-8f2b-c54a-e903e42834f6.png)

必要な変数を追加します。左の真ん中辺りにVariablesという項があるので＋ボタンを押して変数を追加します。
Frames: StaticMesh componentのReferenceの配列:ソート済みのコンポーネントを格納する配列
Index:Integer:再生位置
TickCount:Integer:アニメーション再生速度の調整用


初期化の処理1です。ゲームが始まってすぐ、ブループリントのコンポーネントの中からタグ付けされたものだけを取り出します。この時、取り出したコンポーネントが順番に並んでいるとは限らないので、次でソートしながら配列に格納します。さらに、ゲームが始まったらキューブを不可視に設定します。
![スクリーンショット 2015-11-22 19.36.13.png](https://qiita-image-store.s3.amazonaws.com/0/34714/46be85cc-bc17-4325-ac24-6ac8de5c9b2c.png)

昇順ソートをします。タグ付けされたコンポーネントを1つ取り出して、既にFrames配列に格納されているコンポーネントと名前を比較します。比較して、取り出したコンポーネントがFrames配列から取り出したコンポーネントよりも大きくなった時点でその位置に挿入します。(ただしこの図のブループリントは、処理の都合上、降順ソートの判定法で見つけたコンポーネントの前に挿入することで結果的に昇順ソートになっています)
![スクリーンショット 2015-11-22 19.51.41.png](https://qiita-image-store.s3.amazonaws.com/0/34714/acddafd7-23be-e47c-1d49-4e572bf0cd7f.png)

次はゲーム中の処理です。ここではTickが何回発生したらアニメーションを進めるかを設定します。可変フレームレートに対応させるにはDeltaSecondsを使って処理しなければなりませんが、今回は割愛します。
![スクリーンショット 2015-11-22 19.51.48.png](https://qiita-image-store.s3.amazonaws.com/0/34714/16a4afff-348d-8e34-756b-496288040a40.png)

ここではIndexに応じて可視不可視を切り替えます。
![スクリーンショット 2015-11-22 19.51.55.png](https://qiita-image-store.s3.amazonaws.com/0/34714/da651438-0dec-5dd2-57aa-fff725d472b3.png)

デバッグ用に今何番のオブジェクトを表示しているかを出力するようにしています。
![スクリーンショット 2015-11-22 19.52.03.png](https://qiita-image-store.s3.amazonaws.com/0/34714/08bd4655-6c31-1d29-60cb-730129381123.png)

ブループリントを組み終わったので、レベルエディタに戻って、作成したブループリントをドラッグアンドドロップでレベルに配置してみます。(実験しながら作ったので画像では3つ配置されていますが、1つだけ置けばOKです。)
![スクリーンショット 2015-11-23 06.44.02.png](https://qiita-image-store.s3.amazonaws.com/0/34714/1a175f09-1c90-1021-0d93-f016804f9199.png)

Playを押すとゲームが始まり、再生が開始されます。やったぜ。
![スクリーンショット 2015-11-23 06.46.24.png](https://qiita-image-store.s3.amazonaws.com/0/34714/960ab6d7-0597-9066-623c-212b11b2a0fd.png)

OculusRiftなどつないでVR PreviewするとそのままVR化できます。簡単ですね。フレームレートが上がらないようであればBlenderのスクリプトを調整してDecimateしましょう。

# まとめ

最後にもう一度、最初にお見せしたムービーをはっつけ。(クリックするとYouTubeへ飛びます)
[![最終結果動画](http://img.youtube.com/vi/NqJF146tXAI/0.jpg)](http://www.youtube.com/watch?v=NqJF146tXAI)

以上、UE4で科学可視化をやってみよう(あんまりやってない)でした。UE4でジオメトリキャッシュ的なことをやってみたというのが観測範囲上では見当たらなかったので書いてみました。今回そんなに大きいデータではなかったというのもありますが、いい感じに高速にアニメーションさせることができて良かったです。

この状態から、再生停止/逆再生/スピード調整のUIとか、演出(宇宙なら宇宙っぽくとか、実験室風にするとか)、説明を入れるとか、マテリアルを頑張るとかをしないと、せいぜい、影がついたとか、ゲームパッドを使えるようになったとか、データの中に没入しやすくなったとか、流行りのVRHMDに出しやすくなったとかその程度のメリットしかありません。
ただ、以上のようにわりと簡単にできるので、データを見せるだけなら普段の可視化ワークフローの中に組み入れるのも簡単だと思います。


余談ですが、動画中のBlender流体シミュレーションのシミュレーションサイズは100なので形状がかなりカクカクしています。300くらいにするとだいぶ綺麗になります。(計算にメモリもストレージも時間も必要ですが)

ちなみにこの動画で使っているデータのオブジェクト数は、

 - 10フレーム飛ばしのデータ：9
 - 100フレームのデータ：100
 - Blenderの流体シミュレーションデータ：48

で、FBXにして1つ約4MB程度の大きさです。
この時点でメモリ消費量が15GB程度になっているのでモバイル化は頭をひねる必要がありそうです。一番簡単なのは全球動画にしてしまうことですかね。

備考：今回のPC環境
CPU：Intel Core i7 4770K
メモリ：32GB
GPU：NVIDIA GeForce GTX 770 (VRAM 2GB)


追記：
書き上げてから公開まで3週間以上空いてしまったのでその間にちょっと他の例も作ってみました。(クリックするとYouTubeへ飛びます)
[ここ](https://docs.unrealengine.com/latest/JPN/Engine/Rendering/Materials/HowTo/Transparency/index.html)を参考に液体を水っぽいマテリアルに。240フレーム。Blenderでの流体シミュレーション。シミューレーションサイズ100。
[![最終結果動画](http://img.youtube.com/vi/NXjdRmht0yA/0.jpg)](http://www.youtube.com/watch?v=NXjdRmht0yA)

さらに追記：
160フレーム。Blenderでの流体シミュレーション。シミューレーションサイズ300。(クリックするとYouTubeへ飛びます)
[![最終結果動画](http://img.youtube.com/vi/Zw4ZOSX5xGQ/0.jpg)](http://www.youtube.com/watch?v=Zw4ZOSX5xGQ)