目指せ脱HoloLens初心者!その2(SpatialProcessing)

https://torikasyu.com/?p=927
の続きです。
さて、次は別のサンプルを使ってSpatialMappingを更に調べてみます。
HoloToolkit-UnityのHoloToolkit-Testにある、SpatialProcessingシーンを実行してみます。
(HoloToolkit-1.5.7で試していますので、バージョンが違うと多少違うかもしれません)
実行すると、こんな風になります。

通常、SpatialMappingのポリゴンデータは凹凸がありますが、そこに処理を加えることによって、平面が滑らかな板に置き換わっています。
(同じような用途のSpatialUnderstandingプレファブを配置したときには、メッシュのまま滑らかなポリゴンになりますが、その動きともかなり違う感じです。)
平面(Plane)になることにより、そこに対して別のコンポーネントをアタッチしたり、Planeの上に他のGameObjectを置いたりするのがすごく楽になりそうに感じますので、ここを調査してみたいと思います。
サンプルのHierarchyに置いてあるSpatialProcessigには、
SpatialProcessingTest.cs
SurfaceMeshesToPlanes.cs
RemoveSurfaceVerticles.cs
の3つのコンポーネントがアタッチされています。
ではSpatialProcessingTestの中身をざっくりと見ていきましょう。
===
■Start()
SpatialMappingManagerとSurfaceMeshesToPlanesのインスタンスを操作しています。
どちらもHoloToolkit本体にあるクラスですね。
SurfaceMeshesToPlanesでPlaneを生成するのですが、完了時にイベントが発行されるように設定しています。
■Update()
meshesProceedがfalseかつ規定時間を過ぎた場合にPlaneの生成処理処理を行うようにしています。CreatePlanes()関数を呼び出し、その中で、SurfaceMeshesToPlanesのMakePlanes()を呼び出しています。
SurfaceMeshesToPlanesでPlaneが生成完了した際に発生するイベント内では、PlaneのタイプがFloorのものが規定数になっているかをチェックして、規定数に達した場合はRemoveVeriticlesによってもともとのSpatialMappingのポリゴンを削除、規定数に達しない場合はmeshesProceedをfalseにすることによって解析を続ける、という処理になっています。
===
なかなかに複雑な動きですが、ここから下記のことがわかりました。
・SurfaceMeshesToPlanesクラスは、MakePlanes()関数を呼び出すことにより、SpatialMappingからPlaneを生成してくれる。
・生成されたPlaneはFloorなどの種別を持っている(いいですね!使えそうですね)
・RemoveVerticesは、もともとのSpatialMappingの頂点を消してくれる。
これを使って、最小限シンプルな動きを作ってみたいと思います。

いつものようにHoloLensCamera、InputManager、SpatialMapping、BasicCursorを配置後、空のGameObjectを作成し、SurfaceMeshesToPlanes.csと下記のスクリプトをアタッチします。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using HoloToolkit.Unity.SpatialMapping;
public class MySpatialProcess : MonoBehaviour {
	// Use this for initialization
	void Start () {
		SurfaceMeshesToPlanes.Instance.MakePlanesComplete += SurfaceMeshesToPlanes_MakePlanesComplete;
		SurfaceMeshesToPlanes.Instance.MakePlanes ();
	}
	private void SurfaceMeshesToPlanes_MakePlanesComplete(object source, System.EventArgs args)
	{
		List<gameObject> planes = new List<gameObject> ();
		planes = SurfaceMeshesToPlanes.Instance.ActivePlanes;
		foreach (GameObject plane in planes) {
			SurfacePlane surfacePlane = plane.GetComponent<surfacePlane> ();
			if (surfacePlane != null) {
				print (surfacePlane.PlaneType);
				print (surfacePlane.transform.position);
			}
		}
	}
}

内容としては、単純にSpatialMappingからPlaneを生成していて、まだRemoveVerticesは使用していません。
SurfaceMeshesToPlanesにPlane生成完了時のイベントを設定した後にMakePlanes()を呼んでいるだけととてもシンプルです。そして、完了時イベント内では、Planesの情報をprintしていますが、その結果、それぞれ独立したGameObjectとして取得できていて、PlaneTypeにより床なのか壁なのかテーブルなのか、という情報もわかります。(スクリーンショットのログ部分参照)
これで、壁だったら絵画を置いて、天井だったら穴をあけて(キリンの首用)、テーブルだったらUnityちゃんを座らせる、みたいな処理ができるようになりそうです。
SpatialUnderstandingを使うともっと細分化してタイプを取得できるようなのですが、まずは単にSpatialMappingプレファブを置いただけのノンコーディング状態よりも進歩しました!

スポンサーリンク

シェアする

  • このエントリーをはてなブックマークに追加

フォローする

スポンサーリンク