遊んで航海記

思いつきで遊んだり、ゲームを作ったり、寝たり

ポジトラのないVRヘッドセットの違和感を軽減しよう

いま周りをぐるりと見渡すと、何が見えるでしょう? 部屋とモニター? うんうん、PCは快適ですね! スマホと電車? どこでもコンピューターと触れ合えるいい時代になりましたよね! ん? xRの現在と輝く未来? 闇と光の話かな?

さて、最後のはともかくとして、実際横に360度、ぐるっとまわるとき、その回転の中心はどこにあったでしょうか。

今回はGear VRやOculus Go、Daydream、Cardboardなど、頭の向きはとれても(※通常は)位置の追跡ができない、ポジショントラッキング機能未搭載のVRデバイス向けのTIPSです。

そして、この記事はOculus Rift Advent Calendar 2017 - Qiitaの2日目の記事でもあります。昨日はのしぷさんのUnity ARKit PluginのFace Trackingを使ってみるで、誰もが美男美女になれる技術の話でしたね!

ポジトラ無しで目を中心にまわる違和感

ポジショントラッキングがないとき、Unityで普通にカメラを配置すると、向きは頭の動きにあわせて変わりますが、位置は3D空間上の1点に固定されています。これを現実で考えると、「目(あるいは眉間)を中心にして頭を動かしているようなもの」です。

実際に現実でやってみてほしいのですが、目や眉間を中心に固定しつつ頭を360度回すのは、結構難しい&マヌケな感じになりますよね。

ポジショントラッキングがないVRデバイスで360度動画や遠方の3Dオブジェクトを見る分にはそれほど違和感ないのですが、近、中距離で立体感あるものを見ると、このVR上の回転軸と現実の頭の回転軸の差から、視界が歪んで見えたり、結構違和感を感じたりしました。

頭の向きから目の自然な位置を推測してみよう

そんなわけで違和感を減らすための実験をしてみましょう。

ポジショントラッキングが無くても、頭の向きはとれますよね。ということは、頭の向きから、目がありそうな位置を逆算すれば、もう少し自然に頭を動かした位置がとれるのではないでしょうか。

実際は首やら腰やら上半身やら足やら、いろいろな部位が動いたうえで頭の向きが変わるわけですが、今回はざっくり首と頭の動きを簡易的に表現してみます。

やってみよう

実験画面はこちら! 灰色の球が頭の半径(目との距離)で、赤い線が頭(目)の向きです。小さめの黄色い球と線が首の根本あたりから頭の中心に伸びてるのも見えますね。

f:id:n_ryota:20171126220535j:plain

f:id:n_ryota:20171126221607j:plain

下を向くとこんな感じ。下向いたとき、頭が前に出ているところに注目です。

f:id:n_ryota:20171126220552j:plain

f:id:n_ryota:20171126221658j:plain

ちなみに、ポジトラのあるVRデバイスアバターに憑依させてキャラを表示する場合にもこの考え方は役に立ちます。カメラの位置はキャラクターの頭の中心ではないので、ポジトラで得られる位置から、キャラクターの頭の本来の中心位置を導くような感じでやると自然さが増します。VR Walkでもこのあたりを意識した設定にしていたり。

脱線しました。話を戻して――逆を向くとこう。

f:id:n_ryota:20171126221008j:plain

f:id:n_ryota:20171126221712j:plain

さて、こんな感じの処理を行うと、ポジショントラッキングがない状態でも、位置が変動するようになります。VRと現実の頭の動きの一致度が上がるので、体感的には歪みや違和感が減ったように感じました。

※ただし、現実の頭の大きさや首の長さ、身体の使い方などには個人差があるので、完璧に一致するわけではありません。自分にあった値をさぐってみたり、作るVRコンテンツの特性にあわせて平均はこのへんかな、といった感じで調整してみてください。

スクリプトの使い方

今回実験用に作ったのは、VRNeck3DoF.csという100行程度のコンポーネントです。

使い方は簡単で、VRNeck3DoFをAddCompornentしたGameObjectを作り、その下にMainCameraを配置するだけでOK。

各パラメータの意味については、ToolTipで表示するようにしてあるので、マウスカーソルをラベルの上にもっていって確認してみてください。

f:id:n_ryota:20171129232122j:plain

Oculus Riftで動作テストしているため、実際の各デバイスで正常動作するかは未確認です。ポジトラあるデバイスでポジトラを無効化するために、親オブジェクトの位置を逆方向に動かすことで位置を停止させるなど、強引なこともしていたり。

VRNeck3DoFのEnable ModifyのチェックボックスをOFFにすると、位置を固定するのみで、頭の回転による補正をおこなわなくなるので、ON/OFFして違いを比べてみるとわかりやすいかもしれないです。また、RiftやVIVEなどポジトラありのデバイスで、VRNeck3DoFのコンポーネントをDisableにして頭を動かしてみた視界との差を比べるのもよいと思います。

コードとデモシーンをまとめたパッケージはこちら。

goo.gl

コンポーネント単体のコードは下記のとおりです。

ポジトラなしのVRデバイスで回転時の違和感を減らすスクリプト

編集後記

長々と記事を書いておいてアレですが、探せばこういうの普通にありそう、というかサンプルでありそうな気もする…。でもせっかくプログラムを書いたので、晒しておきます。検索するキーワードが思い浮かばなくて、コードを書いた方が早かったという。

しかし、なぜいまさらポジトラのないデバイスの話を……なんて思う方もいるかもしれませんが――私はOculus Goがほしい! 手軽に見てもらうには良いデバイスな気がするんですよね。一部開発者には届き始めたみたいです。みんなもサンタさんにお願いしよう!

あと望むことがあるとすれば…

加速度センサーあれば、いろんな補正や応用に使えると思うんですよね。そんなアバウトなやつは下手に使うと酔いをひどくするので避けてるとかもあるかもですが。まぁ、なんにしても、「廉価版の機種にはポジトラなし、そんな時代もあったね…」と早くなるといいですね!

おまけのVR酒場

そういえばこんなのもやったので軽く解説を。

やり方は単純で、カメラからRayを飛ばして、ぶつかった点までの距離で、PostProcessingStackのDepth of Fieldの値をリアルタイムに設定するだけ。フォーカスしたくないものはレイヤー分けしておきましょう。

VRで見る場合には、近い距離のピントとボケ具合のバランスをもうちょっと変えたい気はしました。

気軽にいろんな実験をするのも面白いですね。

さて、明日の記事を書くのは……あなたかも!(まだ明日のアドカレ担当者がいないみたい)

qiita.com