読者です 読者をやめる 読者になる 読者になる

凹みTips

C++、JavaScript、Unity、ガジェット等の Tips について雑多に書いています。

Oculus Rift x Leap Motion を使った指で空間に魔法を描いて発動できる Magic VR を作ってみた

Oculus Unity C# Leap Motion

 

この記事は Oculus Rift Advent Calendar 2014 19日目の記事です。前日は KaleidPlayer の作者の @faifx さんによる「視差無し立体視のススメ - とあるOculusRift使いの備忘秘録」でした。2D の動画/静止画の単眼立体視を行うには、なるべく遠い場所に置くほうが有利で、それが何故かの考察、またそれに加えて平面感を消す手法・知見などがまとめられている素晴らしい内容です!

はじめに

以前、「Oculus Rift と Leap Motion で空中お絵描きアプリを作ってみた - 凹みTips」というエントリを投稿しました。ここでは Leap Motion VR(参照:VR の世界に手を持ち込める Leap Motion VR の仕組みを調べてみた - 凹みTips)を利用して空間に指で線を描けるという簡単なデモの紹介をしています。

指先の軌跡をダイレクトに空間に残せるのは結構面白くて、ゲームや UI への応用と色々なことが出来そうで、アイディアもたくさん思い浮かびます。そのアイディアの中の一つである、「この軌跡で魔法が描けたら良いな、魔方陣グルグルのククリみたいなことしたい」というアイディアを実現するべく、色々と試行錯誤してみました。しばらくウンウンとやってみた結果、何とか魔法が使えるようになり Magic VR というプロジェクト名で現在制作しています。本エントリでは、その内容を紹介させていただければと思います。

本当は年内公開の予定で作ろうと思っていたのですが、しばらく別のことをしていて開発が止まっていたので完成には至っていません...。取り敢えず、10/25 の DCExpo で行われた OcuFes 開発者会の懇親会に持って行ったバージョンよりは認識精度も良くなったので、α版も配布してみようと思います。

デモ

スクリーンショット

空間に線が描けて...、

f:id:hecomi:20141218012019p:plain

図形を描くと描いた軌跡に合わせて魔法陣発動!

f:id:hecomi:20141218012316p:plain

触ると魔法を発動!

f:id:hecomi:20141219234054p:plain

10月末バージョン 動画

12月現在バージョン 動画(作成途中)

魔法陣を自前で描いて描いた図形にフィットするようにしました。

α版

ルール

現在のところ、以下のルールで作成しようと作っています。

  • 人差し指で空間に線を描ける
  • 円・三角、四角・星などの図形を描くと属性の異なる魔法陣を召喚
  • 魔法陣に触れると魔法陣に紐付いた魔法を発動
  • 魔法陣の重ねがけで発動する魔法を重ねがけする魔法陣に応じて強化

スケールしそうなアイディアがあれば是非教えてください!

図形認識の仕組み

どうやって検出しようか最初はうんうん考えました。Leap Motion SDK にも円の認識が入っており、小さく速くくるくるしてスクロールする、といったジェスチャ用には良いのですが、色々な大きさや形・速度で描く魔法陣用には使えないのでやめました。

カメラから平面に軌跡を射影して画像ベースの認識することも考えましたが、処理が重たそうなのと法線情報が失われるのでやめました。

そこで色々と調べたり考えた結果、Leap Motion によって軌跡が綺麗に取れていることから、素直にこの時系列に並んだ点群の位置関係を元に計算する方式に決めて検討したところ、比較的すぐに出来て、高校数学程度で検出可能になりました。認識部分の全体のコード(Unity/C#)はこちらになります。

コード自体は Leap Motion に依存しない形で書いていますので、他でも流用できると思います。もう少し整理したらサンプルプロジェクトとともに github の方へ上げます。

それではコードを簡単に解説します。図形は主に円認識と多角形認識に分かれていますので分けて説明します。

円の認識

円の認識はとても簡単でそこそこロバストです。円は中心からの距離が一定となる図形なので、これを利用します。まず軌跡の平均点を中心と仮定し、そこから各軌跡上の点への距離の平均を半径と仮定、その半径と実際の距離の誤差の絶対値の総和が閾値以下だった場合に、現在の点が始点と近ければ円として認識しています。

f:id:hecomi:20141217225640p:plain

認識した後に魔法陣を描画する位置はこの平均点で、また隣接する3点からなる外積の平均を取れば法線がとれるので姿勢も分かります。コードで書くとこんな感じです。

アイディア自体は以下の stackoverflow の質問を参考にしました。

正多角形の認識

正多角形については、円よりも苦労したのですが、頂点をベースに認識する方式にしました。まず何らかの方法で頂点を認識し、その隣り合う頂点を結ぶ線を辺として、隣り合う辺のなす角度たちがその図形の角度の許容範囲内(正三角形なら 60 ± 15°など)であり、かつ最初の頂点と最後の頂点が近ければ正多角形と認識する、という方式です。

f:id:hecomi:20141218001555p:plain

で、どうやって頂点の認識をしているかというところですが、今のところ停止点の検出と鋭角の認識のハイブリッドにしています。

停止点は一定時間の間の移動距離が閾値以下だった場合に検出されたとします。主にジェスチャの開始点や終了点のために使いますが、認識しない時に各頂点でしばらく待っていることで、より高確率で魔法を出すことができます。

f:id:hecomi:20141218001547p:plain

本当は距離の絶対値を積分するべきですがサボったのでコードはこんな感じです。

鋭角認識については、実際の頂点部分は 3 点よりも多い点で形成されるため、過去の数点を使って認識してあげなければなりません。つまり加速度変化を見る方式では、スレッショルドを超えたことを認知は出来ますが、それが何度なのかは認識できません。そこで数点飛ばしの 3 点を前後に振って見て、最も鋭角なところが閾値以下だったら鋭角な頂点として認識する形にしています(下図左)。

f:id:hecomi:20141219014926p:plain

ただし、上図右のように早く図形を描いた時は鋭角の位置を誤認識してしまうこともあるので、ここらは要改良です。コードはこんな感じです。

エフェクトでの工夫

自分の行動に対して色々なフィードバックがあると、精度を上げるためのヒントになったり学習の加速につながると考え、いくつかエフェクトを入れてみようと試行錯誤しています。

軌跡に応じたサウンドフィードバック

Unity のオーディオの再生・エフェクト・解析周りについてまとめてみた - 凹みTips でも書いた Unity の OnAudioFilterRead() を利用して、指の速度に応じた音を生成して鳴らしています。まだあまり良いアルゴリズムは思いついていなくて、今は単純に周波数だけ変えて鳴らしています。

頂点認識の表現/効果音

アルゴリズムでは頂点認識は多角形認識に必須なので、このタイミングで認識した空間上の頂点から白いパーティクルを出すとともにシュッという SE を鳴らしています。ただ、これは現状問題点があり、多角形認識が頂点を描いてから数点後に認識するため、頂点を描いた瞬間に SE が鳴らせず、逆に遅延による違和感を感じてしまいます。加速度変化のタイミングで鳴らす、といった方式へ変更したほうが良いかもしれないと思っています。

このあたり認識精度や気持ちよさにより直結しそうに思われるので、もっと時間をかけて掘ってみようと思います。

おわりに

VR 内における汎用的な UI を考えるのはとても難しく、技術的な課題も多いです。しかしながら便利かは分からないけれど気持ちのよい UI、ゲームとして楽しい UI として考えると色々なアイディアが湧いてきます。魔法という題材は便利で、認識に練習が必要だとしても、練習次第で再現性があるものにすることが出来れば、楽しく遊べるものにすることが出来ると思います。

ゲームとしての完成はもう少し先になりそうですが、コツコツと進めていきたいと思いますので、何かフィードバックなどありましたら Twitter などでご連絡ください。

明日は @shigekzishihara 先生のVRで感性評価の記事です!楽しみです。