デモ
「はじめに」が長くなったので、まずは今回取り扱う内容をご覧ください。
はじめに
Senz3D(Creative Interactive Gesture Camera) は、昨年の IFA2013 にて発表されたクリエイティブテクノロジー社製の NUI カメラです。
720p の RGB カメラと共に QVGA の TOF 方式によるデプスカメラを備え、15 cm ~ 1 m と比較的近距離のデプス情報を精度よく捉えることが出来ます。271g とやや重めですが、30 fps / 74°と広角、また左右にマイクを備えたハイスペックなカメラになっています。購入は、Intel のサイトからが安くて早いです。
これを利用した有名なライブラリには Intel の PCSDK(Perceptual Computing SDK)があり、顔認識や手のジェスチャ認識、音声認識といった NUI の機能を提供しています。
余談ですが、PCSDK のカメラ機能や音声認識機能は Senz3D を持っていなくても扱えます。
- Intel Perceptual Computing SDK(Senz 3D) を使ってWindows+Unityでお手軽日本語音声認識 - izm_11's blog
- http://zi-su.blogspot.jp/2014/04/unityperceptualsdk.html
Oculus Rift と組み合わせた先行事例としては、第6回ニコニコ学会βシンポジウムにて @mohammedari さんが点群からメッシュを3次元再構成した手を VR 空間の中にいれるデモをされていました(見に行きたかったです...)。
@mohammedari さんも使われていましたが、MakerBot Thingiverse にて、Oculus Rift 用 Senz3D マウンタの STL データが公開されています。
- 3D Camera mount for Oculus Rift (dev kit) by gillespinault - Thingiverse
- 3D Camera mount for Oculus Rift (dev kit) - updated by gillespinault - Thingiverse
後者が新しい版です。これは、3D センシングのソフトウェア / ハードウェアを手がける SoftKinetic 社の方が作られたモデルです。
Intel の PCSDK に対して、SoftKinetic 社は iisu(The interface is you)という NUI のプラットフォームを持っています。Senz3D は SoftKinetic の DS325 と互換のカメラとのこと*1で、この iisu によるアプリケーションが動作します。
そして、Oculus Rift × Senz3D × iisu のデモが CES 2014 にて披露されていました。
驚くことに、この動画にあがっている Unity によるサンプルプロジェクト一式が Thingiverse にあげられています。
そこで、このサンプルプロジェクトを解読して改造し、VR 内のオブジェクトとインタラクション出来るプロトを作成してみました。導入から解説までを本エントリにまとめたいと思います。
DMM での 3D プリント依頼
まず、Thingiverse でマウンタの STL データをダウンロードします。
次に、これを DMM.make の 3D プリントサービスにアップロードします。
「部品・工具・パーツ」を選択して手順に従ってアップロードします。色々と素材が選べるのですが、私は一番安い石膏を選択しました。値段は 2,247円で送料無料です。5/4 に注文して 5/9 に届きました(早い)。
Senz3D にはカメラ固定具で止められるので Amazon で適当な固定具を仕入れ装着します。
これで Oculus Rift の装着できます。
iisu 3.6 のインストール
次に iisu 3.6 Free をインストールします。
SoftKinetic のユーザ登録が必要です。ダウンロード時にどこからダウンロードすれば良いか分からなくてハマりましたが、小さいフロッピーディスク型(古い)のアイコンをクリックすればダウンロードできます。
後は「here」となっているリンクからアクチベーションキーを取得、インストール時にそれを入力すれば完了です。
Senz3D を接続すると DS325(SoftKinetic の 3D カメラ)として認識され、準備完了です。
これで手を出す準備が整いました。
追記:2014/05/16
iisu Free は3ヶ月試用版のようです
サンプルアプリのインストール
サンプルアプリを動かしてみます。Thingiverse より「UNITY3D-SimpleDemoWith_Sources」および「UNITY3D-CubeDemoWith_Sources」をダウンロードします。
それぞれの Build ディレクトリにサンプルの exe が入っているので実行してみると、冒頭の動画と同じアプリが動作します。キューブをつついたり、グラブアクションによりボールを動かしたりするサンプルと、キューブを3次元のグリッド上に並べられるサンプルになっています。
サンプルアプリの解説
素晴らしいことにこのサンプルは Unity で出来ており、そのプロジェクト一式が Source ディレクトリに入っています(ライセンスは未確認)。仕組みを調べて改造すれば色々と出来そうです。ここでは「UNITY3D-SimpleDemoWith_Sources」について見て行きたいと思います。
全体像
コード及び構造はとてもシンプルになっていて分かりやすいです。
iisu
ディレクトリ下にプラグインが入っており、OVR(Oculus の SDK)も同梱されています。後は標準的なディレクトリ構成になっています。
カメラ画の取得
iisu/Components
下に MonoBehaviour
達が含まれています。IisuFeedbackImage
はデフォルトで無効になってますがチェックを入れてアクティブにすると、OnGUI
でデプス画を描画してくれるようになります。IisuColorImage
をアタッチすればカラー画が表示されます。
手の描画
手の描画のエントリポイントは HandMesh1
および HandMesh2
にアタッチされている Hand
スクリプトです。
private void drawMesh() { HandMeshInfo hmi = iisu.Hands[HandIndex].GetHandMesh(_offset, transform); _mesh.Clear(); if(hmi.Vertices.Length == hmi.Normals.Length) { _mesh.vertices = hmi.Vertices; _mesh.triangles = hmi.Triangles; _mesh.normals = hmi.Normals; } Graphics.DrawMesh(_mesh, v3Zero, Quaternion.identity, HandMaterial, 1); }
iisu/DataProviders
にある機能をまとめた iisu
クラスから手のメッシュデータをもらってきて Graphics.DrawMesh
で描画しています。手の表現を変えたかったらここを色々といじれば良さそうです。
物体に触れていることの認識
まず手を触れると色が変わる接触判定についてです。これは Unity のコライダの OnTriggerStay
を使って判定しています。実は Hand
スクリプト内で、先ほどのメッシュの描画と同じタイミングでメッシュの代表点(Centroids)をコライダ付きのオブジェクトで配置しています。
void Awake() { // ... centroids = new Transform[centroidCount]; for (int i = 0; i < centroidCount; ++i) { GameObject centroid = Instantiate(CentroidPrefab) as GameObject; centroids[i] = centroid.transform; centroids[i].tag = HandIndex.ToString(); } // ... } private void drawCentroids() { centroidPositions = iisu.Hands[HandIndex].Centroids; for (int i = 0; i < centroidPositions.Length; ++i) { centroids[i].position = transform.TransformPoint(centroidPositions[i]); } }
この代表点に使用する GameObject
は public
になっているため、衝突判定を弄りたかったら CentroidPrefab
をインスペクタより指定すれば OK です。イメージをつかみやすくするために、デフォルトで指定されている Prefabs/Centroid
の Mesh Renderer
コンポーネントにチェックを入れてアクティブにしてみます。
GrabSphere
と TouchCube
スクリプトではこの球のコライダとの衝突を OnTriggerStya
で検知しているわけです。
グラブアクションの検知
GrabSphere
を見てみます。
void Update() { if (isTouched) { if (!iisu.Hands[touchingHandIndex].IsOpen) { transform.position = handReferences[touchingHandIndex].TransformPoint(iisu.Hands[touchingHandIndex].CentralGrabber); } // ... } }
iisu
から IisuHand.IsOpen
をもらってきてそれで検知しています。色々なアクションを追加したければここを参考に改造すれば良さそうです。その材料としては、先ほどの IisuHand.GetHandMesh
や IisuHand.Centroids
といった他に、様々な面白い public メンバが公開されています。
HandMeshInfo GetHandMesh(Vector3 offset, Transform reference); int CentroidCount; Vector3[] Centroids; Vector3[] FingerPositions3D; Vector3[] FingerPositions3DCompensated; Vector3 PalmPosition3D; Vector3 PalmNormal3DCompensated; Vector3 HandTipCompensated; Vector3 HandTip; bool IsDetected; int[] FingerStatus; Vector3 UpperGrabber; Vector3 CentralGrabber; Vector3 LowerGrabber; int GestureID;
当たり判定のある手にしてみる
少しだけ改造して手に衝突判定をつけるとこんなことが出来るようになります。色々想像膨らみます。
おわりに
今回は、基本のみの紹介になりましたが、色々なパラメタが取れるので、SAO のように手を振って UI を出して指で選択とか出来そうです。是非皆さんも楽しんでみてください。