HoloLensは「Spatial Mapping」とよばれる周辺の凹凸を判別する機能を持っています。これによって現実空間にあたり判定をつけ、落下してくる仮想のオブジェクトを現実空間に配置できます。Unityで開発する場合、この凹凸情報はMeshデータとして保持しています。
この情報は奥行きを持っているので、下図のようなCubeが机の奥にある場合、底面が見えなくなります。
ここではワイヤーフレームでメッシュを描画していますが、これだといまいち現実感がないので、描画をしないで奥行き感をだしてみましょう。
落ちたCubeが机の奥にある感じがわかります(そんな感じで想像してみてくださいw)
先に書いた通り、Unity上ではあたり判定付きのメッシュとして持っているので、落下させるほうは普通にRigibody(重力)をつけてあげればOKです。
なお、このサンプルプロジェクトはこちらにおいてあります。
内部で使用しているHologramsのアセットはHolograms 101Eから取得したものです。
全体の動画は次のようになっています。
Spatial Mapping
Spatial Mappingを使う
Spatial Mappingを使うにはHologramsにあるSpatial Mappingプレハブを配置するだけです。
メッシュを描画する場合には「Draw Material」に描画用のマテリアルを設定し、「Draw Virtual Meshes」にチェックをいれます。
マテリアルはいくつかありますが、メッシュを書く場合には「Wireframe」を、メッシュを書かない場合には「Occlusion」を指定します。先ほどの画像は「Wireframe」と「Occlusion」をジェスチャーで入れ替えています。
Spatial MappingにはUWPの機能許可が必要なので、Build SettingsのCapabilitiesから「SpatialPerception」にチェックをいれます。
これでメッシュが描画されます。
落下物の設定
落下物はここではCubeを使っています。落ちるようにRigibody(重力)をつけています。スクリプトを一つつけていますが、これはYがある一定以下になったら自分を削除するものです。メッシュが生成されるまでに数秒かかるので、それまでCubeは延々と落ちてしまうので。
一つ気を付けることとして、ユニティちゃんのような3Dモデルを配置した場合、そのままだと着地して転んでしまいますRigibodyのConsraintsのFreeze Rotationにチェックをいれることで、転ばなくなります。
以上でCubeがメッシュ上に落ちるようになります。
メッシュ生成状態の取得
メッシュが作れるようになると、メッシュ認識前の数秒をどうするかという悩みが出てきます。メッシュの生成が判別できれば。。。ということでスクリプトを修正します。
SpatialMapping.csにメッシュ生成のコードが入っており、覗いてみるとDictionary<int, GameObject> surfaces;という変数にメッシュが格納されることがわかります。
Unityのメッシュは64k頂点までという制約があるので、頂点数が増えた場合には複数のメッシュを組み立てます。
ということで、surfacesにメッシュが入るので、surfacesの数が0であればメッシュ未生成状態、それ以外は生成された状態となります。
gist8d2a46e0c7713d9b74aff37550b939dd
これをUIに表示すると次のようになります。この表示はメッシュが生成されると消えるようになっています。
表示方法を切り替える
最後にWireframeとOcclusionの切り替えをしてみます。マテリアルはSpatialMappingプレハブのDrawMaterialに設定すればよいですが、これはメッシュが新規に作成された時に設定するものです。生成中のメッシュの描画方法を変える場合にはsurfacesのメッシュすべてに対してマテリアルを再設定します。
gistcd04c870cce5a35dca3a5d3ab7404f57
呼び出し側は次のようになっています。
gist3868ac5ecc4dd3069c071d1d04a19785
こんな感じで設定します。
Cubeの作成
Cubeは顔の正面1.5m先の1m上から、1秒ごとに落としています。