three.jsとOculusRiftを使ってのVR化

OculusRiftDK2を触る機会があったので、以前作ったJS-RacingをOculusRift用に改良しました。

20150616_img


視聴方法

OculusRiftのセットアップ

何はともあれOculusRiftDK2をセットアップする必要があります。詳しくは説明しませんが、以下のサイトが分かりやすいかもしれません。

デバイスを繋ぐだけというわけに行かないので少し面倒かもしれませんが、汎用性を考えるとしょうがないのかもしれません。VRコンテンツを楽しむだけの場合はOculusRuntimeだけでSDKは必要ありません。

ChromiumのWebVRBuildsをインストール

OculusRift用のエフェクトがかかっていれば、そのコンテンツをOculusRiftで見るだけで、立体的に表示されると思います。通常のデスクトップアプリケーションの場合はこのままでいいのですが、JS-RacingはWebコンテンツなので、ブラウザではOculusRiftにアクセスしてトラッキング情報を取得する事が出来ません。ブラウザからOculusRiftのトラッキング情報にアクセスするには、いくつか方法がありますが決定的なものがないのが現状です。

調べてみるとvr.jsがよく使われているようなので使ってみました。vr.jsはブラウザのプラグインとして提供されているため手軽に導入出来るかと思います。ただし、vr.jsはNPAPIを使用して作成されており、ChromeやFirefoxはNPAPIの拡張機能のサポートを廃止する予定ですので、残念ながら将来的な事を考えると選択肢から外れる事でしょう。

今回はWebVRという、ブラウザでVRデバイス(OculusRift)を使うためのJavaScriptAPIを使って、トラッキング情報を反映させました。ただしWebVRは現状では通常のブラウザには実装されていないので、利用する事は出来ません。Chromium(※GoogleChromeの元となっているブラウザ)のWebVRBuildsをインストールして、ChromiumからWebVRを利用する事が出来ます。これによって、視野にトラッキング情報が反映されるようになります。(※うまく機能しない場合はアドレスバーに「chrome://flags/#enable-webvr」と入力して、WebVRが有効になっているか確認してください。)

将来的に多くのブラウザでWebVRの様なJavaScriptAPIが利用出来るようになれば、VRコンテンツがより身近なものになりますね。


開発方法

three.jsを使っていれば、コンテンツのVR化は非常に簡単に実現可能です。ステップとしては、

  1. OculusRift用にエフェクトをかける
  2. OculusRiftのトラッキング情報をCameraに反映する

だけです。この記事を書いている時点での最新はr71です。

OculusRift用にエフェクトをかける

three.jsにVR実装のサンプルがあるので、そちらの方が分かりやすいので、そちらで簡単に流れを説明します。

まずはVREffect.jsモジュールをthree.jsとは別途に読み込む必要があります。

143行目〜

vrEffect = new THREE.VREffect(renderer, VREffectLoaded);
function VREffectLoaded(error) {
    if (error) {
        fullScreenButton.innerHTML = error;
        fullScreenButton.classList.add('error');
    }
}

レンダラーを引数にして、THREE.VREffectをnewしてVRエフェクト用インスタンスを作成します。

169行目〜

function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    vrEffect.setSize( window.innerWidth, window.innerHeight );
}

Windowサイズをセットする場合は、VRエフェクト用インスタンスのsetSize()メソッドを利用します。

198行目〜

function render() {

    〜省略〜

    vrEffect.render( scene, camera );
}

レンダラーをアップデートする場合は、レンダラーではなく、VRエフェクト用インスタンスのrender()メソッドでアップデートをかけます。

OculusRiftのトラッキング情報をCameraに反映する

次にOculusRiftのトラッキング情報を、WebVRを使って取得するためのVRControls.jsモジュールを読み込みます。

127行目〜

vrControls = new THREE.VRControls(camera);
mouseControls = new THREE.MouseControls(camera);
headControls = vrControls;

カメラを引数にして、THREE.VRControlsをnewしてVRトラッキング用インスタンスを作成します。

235行目〜

headControls.update();
vrEffect.render( scene, camera );

VRトラッキング用インスタンスのupdate()メソッドを実行してから、VRエフェクト用インスタンスのrender()メソッドでアップデートをかけます。基本的にはこれだけで、OculusRiftのトラッキング情報をカメラに反映させる事が出来ます。


まとめ

思っていたよりも簡単にthree.jsコンテンツをVR化出来ましたが、NPAPIの拡張機能のサポートを廃止する事WebVRが現状のブラウザにまだ実装されていない事等を考えると、現状では実用化といった段階ではないです。そもそもがOculusRiftを持っている前提となるので、イベント等で、実行環境(PCとデバイス)をこちら側でセッティング出来る状況では有効な手段かもしれません。

JS-RacingをVR化するにあたって、一番問題となったのがUIの部分です。JS-Racingではラップタイム表示やコースレコードの保存といった機能をHTMLに頼っていますので、VRコンテンツに対応するためには、UIも含めてthree.jsで表現する必要があります。VRコンテンツ上では、UIをマウスで操作出来るわけではないので、それに変わる別の操作方法を考えなくてはいけません。通常のモニタとVRデバイスの両方に対応させるためには、別々のUIになる事を念頭に、設計していく必要があるかと思います。