Microsoft のRoomAlive Toolkit for Unity使ってみた

#概要
RoomAliveとはMicrosoftが開発した、プロジェクションマッピングとkinectを利用して部屋の中に仮想空間を投影して、仮想空間の中でゲームをプレイする感を味わう為のツール群です。

また、RoomAlive Toolkit for UnityとしてUnityでRoomAliveを利用したゲームを開発できるプラグインが公開されていて、今回はこれを使ってみた際に参考にしたサイトとか、自分が理解できた範囲のRoomAliveの仕組みを解説していきたいと思います。

## 動作環境
- Windows10
- [RoomAliveTookKit](https://github.com/Microsoft/RoomAliveToolkit)
- Unity2017.1.1
- VisualStudio2015 (ツールのビルドに必要。)
- KinectV2 x1つ
- 適当なプロジェクタ x 1つ

## RoomAlive
下の動画を見ると、RoomAliveでどのような事が出来るか分かります。
https://www.youtube.com/watch?v=cMzM0LqIOg4

部屋に仮想空間を投影してその中でゲームできます。自分はプロジェクタ一台でしか試してないので部屋の一角のみの体験となりましたが、プロジェクター３台まで接続する事が出来るらしいので、資金に余裕があれば部屋全体に投影する事もできます。

## RoomAliveにおけるプロジェクションマッピングの方法
自分がプロジェクションマッピングの事を調べるにあたって参考にしたのが、keijiroさんの[Unity によるプロジェクションマッピング入門](https://github.com/keijiro/unity-pm-tutorial)です。この記事が探した中では一番分かりやすくて自分的にしっくりきました。
内容をかいつまんでいうと、「Unityの中で仮想シーンを対象物にプロジェクターで投影(projecterコンポーネントを使う)してから、実世界の中でその結果をプロジェクターで対象物に投影する」です。keijiroさんの記事中の方法では、仮想シーンを構築する為に、現実世界のパラメータ(対象物とプロジェクタの位置関係、プロジェクタのFOV)を手動で計測して仮想シーンで利用しています。

RoomAliveはまさに記事と考え方は同じような手法でプロジェクションマッピングをしています。

![roomAliveProjection.png](https://qiita-image-store.s3.amazonaws.com/0/116884/986d020b-2a3c-0398-bdb5-ae12194eff57.png)

さらに、上記のリンク先では手動でのパラメータ計測をしてますが、RoomAliveToolkitを用いるとこの手作業をほぼ完全に自動化して、プロジェクションマッピングに必要な仮想シーンを構築するところが凄いところです。

## RoomAliveToolkit
RoomAliveToolkitは具体的には、プロジェクタで投影したテストパターンをKinectで解析する事でプロジェクタのFOVと位置を、Kinectで撮った深度から投影物の3Dモデルを自動生成して仮想シーンを構築する為のツール群です。パラメータを構築して仮想シーンを構築するまでをキャリブレーションと呼びます。

RoomAliveToolkitで提供されているツールは公式のgithubのページにあるプロジェクトをビルドして作成します。わざわざビルドしなくてはならないのでクソめんどくさいです。。
https://github.com/Microsoft/RoomAliveToolkit/tree/master/ProCamCalibration

セットアップの方法に関しては、下記のページが詳しいです。
[yさんのまったりブログ ](http://hiroyky.blogspot.jp/2015/05/kinect-v2roomalive.html)

注意点としては、プロジェクタに壁の一面のみを映してもキャリブレーションできません。必ず壁の2面を映す必要があります(壁と天井、壁と地面など)。部屋の角が含まれていると一番都合がよいです。キャリブレーション結果をUnityに反映すると、下記のようにプロジェクタとKinectと壁の情報が構築されます。原点はKinectの位置になります。この位置関係と、プロジェクタの投影範囲等(FOV)がリアル空間のそれと完全に一致していればキャリブレーション成功です。

また、部屋を真っ暗にしたほうがキャリブレーションは成功しやすい気もします。

![roomaliveCalibResultzu.PNG](https://qiita-image-store.s3.amazonaws.com/0/116884/fe8cb0c4-1398-25fb-9160-d13e7a63eb5b.png)

## RoomAliveToolkitForUnity
RoomAliveToolkitForUnityはUnityでRoomAliveを利用したゲームを作る為のプラグインです。やっていることを箇条書きすると下記のようになります。

- RookAliveTookKitで生成したキャリブレーション結果と3DモデルをLoadして仮想シーンを構築
- 仮想シーンの中で、Kinectで捉えたプレイヤーの頭の位置の視点からの映像を仮想プロジェクターで仮想シーン中の対象物に投影
- 投影された映像を実際のプロジェクターから投影する。
- 別アプリのRoomAliveKinectServerからTCPソケット経由で得たkinectの深度、カラー情報から、Unity内にリアルタイムにメッシュを生成したり、スケルトンを表示したりする。メッシュとスケルトンは、RoomAlive中でkinectのカメラ座標に変換されて表示されています。
- RoomAliveKinectServerで取得したデータを録画して後で再生することもできます。

Unityでのセットアップ方法は公式githubのreadmeを見ながらやれば出来ると思います。
https://github.com/Microsoft/RoomAliveToolkit/tree/master/RoomAliveToolkitForUnity

RoomAliveKinectServerからはリアルタイムに深度情報を取得できますが、ただ取得しているわけではなく深度情報をUnity座標系に変換し、カラー情報ものっかったメッシュで表示することが出来ます。また、この深度情報はバックグラウンド情報を差っ引く事もできるので、周りの静的な深度(壁とか動かないもの)を差っ引いた対象物のみの深度情報を取得することも可能です。下の図ではパイプ椅子の深度からメッシュが動的に生成されたものを表示しています。（正確にはメッシュを動的に生成しているのではなく、内部のサーフェースシェーダーで深度情報を元に頂点座標を椅子の形状に変形している）

スケルトン情報も取得できるので、これを利用すれば人体をコントローラー代わりにしたゲーム等がつくれそうです。

![roomaliveKinectZu.PNG](https://qiita-image-store.s3.amazonaws.com/0/116884/3fcc98b2-bd4e-92ba-6bcb-b2d148cc944d.png)

## 終わりに
今回の記事ではRoomAlive Toolkit for Unityを調べるにあたって参考にした文献の紹介や、簡単な仕組みの紹介をしました。次回の記事ではRoomAlive Toolkit for Unityを利用して作ったサンプルゲームの解説をしながら実際の使い方の紹介をしたいと思います。