HoloLens のカメラ画像を使って Spatial Mapping にテクスチャをつける ~その2~
こんにちは、たるこすです。
ついに、HoloLens の Spatial Mapping で作られるメッシュにカメラ画像から作ったテクスチャを張り付けることができました。
中身について簡単に解説します。
Spatial Mapping の作成
Spatial Mapping は HoloToolkit に含まれているプレハブを配置するだけで作成されますが、さらに SpatialUnderstanding を使うことによって綺麗な Mesh を作成することができます。
まず、シーンに SpatialMapping と SpatialUnderstanding を配置します。
SpatialMapping の Draw Visual Meshes のチェックを外します。
SpatialUnderstanding の Mesh Material を SpatialUnderstandingSurface に設定します。
これで、以下のような Mesh が作成されます。
カメラ画像の取得
Spatial Mapping の Mesh 作成が終わったら、Mesh の更新を止めてテクスチャの貼り付けを行います。
Spatial Mapping が Air-Tap されると、カメラ画像を取得してテクスチャを作成します。この時、画像に加えて世界座標系(アプリでの座標系)からカメラ座標系への変換行列と、カメラ座標系からカメラ画像の射影行列を保存しておきます。
Mesh の頂点とテクスチャの対応づけ
Spatial Mapping の Mesh の頂点それぞれに対して、撮影された画像から作られたテクスチャに対する uv座標をチェックしていきます。頂点の座標からカメラ座標系の座標に変換し、さらにテクスチャのuv座標への対応を計算し、値を保存します。もちろん、頂点の位置が画像の範囲外である場合もあるので、その時は範囲外とわかる値を入れておきます。
複数のカメラ画像(テクスチャ)が作成されるので、それらすべてに対して上の処理を行います。さらに、それらテクスチャのうちどれを使うのが良さそうかというスコアを算出し、一番良いスコアのテクスチャ番号も保存します。
現在のスコアの算出方法は、テクスチャの中央に近いかどうかを見ているのですが、撮影された位置が近いかどうかも基準に入れるといいような気がします。
シェーダーでのテクスチャの描画
ここまでで、Mesh の各頂点に対して、それぞれのテクスチャのどこに対応するのかというuv座標と一番良さそうなテクスチャ番号が求まっています。あとは、シェーダーにこれらの情報を渡し、テクスチャを使って描画していきます。
ただし、各頂点についてテクスチャ番号を求めたものの、描画する際には三角形のポリゴンの面をどのテクスチャで描画するかを決めなければいけません。面を構成する3点が同じテクスチャ番号を指定していれば問題ないですが、ばらばらである可能性もあります。
そこで、面を構成する3点が持っているテクスチャ番号は候補として考え、それぞれに対してそのテクスチャが3点ともに利用できるかをチェックします。3点すべてに対してそのテクスチャが範囲外でなければ、それを描画に使います。
簡単な中身の解説は以上です。
使用上の注意
手元で試してみたい場合には、以下のリポジトリからコードを git clone するかダウンロードして、Unity で開いてビルドしてください。
Visual Studio でビルドする際に Assembly-CSharp のプロパティで「アンセーフコードの許可」にチェックを入れる必要があるので注意してください。
また、突然アプリケーションが落ちることがあります。せっかく作成していたマップが消えてしまうので、ご注意ください。セーブ・ロード機能も今のところはありません。
アプリが落ちる原因がまだわかっていないので、もしわかる方がいればぜひ教えてください。
今後のアップデート(やるかどうかは未定)
セーブ・ロード機能をつけて、ちょっとどこかへ出かけたときに空間を記録できるようになればいいなぁと思っています。(Tango を使えばいいような気もしますが...)
あとは、別の HoloLens や VR機器と同期させて空間転送・空間共有ができると面白そうです。