くすぐり漫画をVR空間で読む

 先日くすぐり漫画を3D仮想劇場で読むで、ミニメロン作の立体視対応くすぐりコミックをソニーのヘッドマウントディスプレイでありますHMZ-T1で読むための方法を紹介しましたが、その中で少しだけ触れたとおり、私の手元にはもう一つ、HMZとは設計思想が全く異なるヘッドマウントディスプレイが存在します。
 それは、OculusVRというベンチャー企業が開発中の、Riftというゲーム用ヘッドセットです。
 これがスペック的にどのような製品なのかについては、既に多くのサイトで紹介されていますので、ここではOculus Rift という名前からこの製品の凄さを改めて考えてみたいと思います。
 Riftという言葉には、英語で「割れ目」「亀裂」等の意味がありますが、例えばFF11に出てくる「Planar Rift」や海外のMMORPGである「Rift」に代表されるとおり、ゲームの世界では主に「空間の裂け目」を意味し、その向こう側は別な世界になっていたりします。
 また、開発元の企業の名前であるOculusは、ラテン語で「目」を意味する言葉でもあります。
 つまり、Oculus Riftという名は、異空間へ繋がる裂け目を目の前に作り出す事を意味しています。
 もちろん、そのような事は現代の科学では不可能な為か、実際の製品としてはまだ販売されておらず、発売時期も未定となっています。
 発売前なのになぜ私の手元にあるかというと、最終製品が普及した未来において、空間に裂け目を発生させる際に時間の流れにまで影響を及ぼし、一部の製品が現在にタイムリープして来たからかもしれません。
 タイムリープの影響からか、製品自体は現代科学で生産できる物へと姿を変えているため、装着者の肉体を別な世界へ送り込む機能は消えてしまっていますが、それでも大抵の人は精神だけは目を通して別な世界へ行けるというわけです。
 そんな凄い物が手に入ったからには、当サイトとしてもぜひ有効な活用方法を検討したいと思うのですが、立体視対応のディスプレイなので、まずはミニメロン作の立体視対応くすぐりコミックを鑑賞するのに使えないか検討してみました。

 Oculus Riftを正常に機能させるためには、それを接続したPCでOculus Riftに対応したソフトを走らせる必要があります。
 Oculus Rift対応のソフトを作る方法としては、Unityというゲームエンジンを使う方法が多くのサイトで紹介されていますが、ただ単に画像を見るためだけのソフトにゲームエンジンというはいかがなものかと思ったので、今回はDirectXを使う方法を選択しました。
 今回の準備として、前回HMZ用のビューアを作っていますので、Oculus SDK付属のドキュメントやサンプルプログラム等を参考に、ヘッドトラッキングや樽歪み表示等、Oculus Rift 対応の為の機能を組み込みました。
 作成したビューワは、皆さんにも以下の手順で動かすことができると思いますので、Oculus RiftとDirectX11対応のPCをお持ちの方は試してみて頂きたいと思います。

0、Oculus Rift をPCに接続し、電源を入れる。マルチディスプレイの設定を複製表示にする。
1、http://www.microsoft.com/ja-jp/dev/express/からVisual Studio Express 2012 for Windows Desktop をインストールする(要ユーザ登録)。既にインストールされている場合はこの作業は不要。
2、https://developer.oculusvr.com/からOculus SDK for Windows (ovr_sdk_win_0.2.5c.zip) をダウンロードし、解凍してできるOculusSDK というフォルダを任意の場所に置く(以下の説明では、Cドライブの直下に置いたと仮定します)。
3、Visual Studio Express 2012 for Windows Desktop を起動する。
4、新しいプロジェクトの作成(ファイルメニュー→新しいプロジェクト→「Win32プロジェクト」を選択し、下の方のボックスに名前と場所を入力→OKボタン→次へボタン→追加のオプションの「空のプロジェクト」をチェック→完了ボタン)
5、ここから今回作成のビューワをダウンロードし、解凍してできるOVRtest1.cpp、test.fx、OVRDist.fxというファイルをプロジェクトフォルダ(プロジェクト作成時に指定したフォルダの下にある、プロジェクト名と同じ名前のフォルダ)に置く。
6、DirectX Tool Kit を http://directxtk.codeplex.com/ からダウンロードし、解凍してできたファイルのうちpch.hとPlatformHelpers.hとWICTextureLoader.cppとWICTextureLoader.hをプロジェクトフォルダに置く。
7、OVRtest1.cppとpch.hとPlatformHelpers.hとWICTextureLoader.cppとWICTextureLoader.hをプロジェクトに追加する(プロジェクトメニュー→既存項目の追加)。
8、右の方にあるソリューションエクスプローラという枠の中の、一番上に表示されているプロジェクト名をクリックして選択状態にし、プロジェクトメニュー→プロパティでプロジェクトのプロパティを表示させる。
9、「構成プロパティ」の中の「VC++ディレクトリ」をクリックする。
10、プロパティページの右側の枠の「インクルードディレクトリ」をクリックする。枠の右端に現れる下向きの矢印のようなマークをクリックし、「編集」を選択して表示されるダイアログボックスの上の枠に C:\OculusSDK\LibOVR\Include と入力し、OKをクリック。
11、プロパティページの右側の枠の「ライブラリディレクトリ」をクリックする。枠の右端に現れる下向きの矢印のようなマークをクリックし、「編集」を選択して表示されるダイアログボックスの上の枠にC:\OculusSDK\LibOVR\Lib\Win32 と入力し、OKをクリック。
12、プロパティページのOKボタンをクリックする。
13、Oculus Riftの電源を入れる。
14、実行(デバッグメニュー→デバッグなしで実行)。
15、フォルダ選択ダイアログが表示されるので、表示するフォルダ(ミニメロンの立体視コミック(体験版でも可)に含まれる、pagesという名前のフォルダ)を選択し、OKをクリック。
16、Oculus Riftを装着する。

 以上の手順により、(ほとんどの方は)作品画像の貼られた板が円周状に並んだVR空間に(精神だけ)入り込む事ができるかと思います。
 右矢印キーでページ送り、左矢印キーでページ戻し、スペースキーでフキダシ有無の切り替え、ESCキーで終了です。
 また、W、S、D、Aキーで前後左右に移動、5、6キーで上下に移動、Rで向きのリセット、Pで場所のリセットができます。
 もちろん頭を回せば、VR空間の中を見回す事ができます。
 なお、動作確認はNVIDIAのグラボを搭載したWindows8PCでしか行っておりませんので、それ以外の環境ではもしかしたらうまく動かないかもしれません。
 また、IMEが全角モードになっていると、W、S、D、A等のキーが正常に働きませんので、あらかじめ半角モードにしておくとよいかと思います。
 人によっては乗り物酔いに似た症状が出る事があるかと思いますので、気分が悪くなったら無理せず元の世界に戻って休憩するのがよろしいかと思います。

 Oculus SDKに付属のドキュメントは英語であり、DirectXでOculus Rift対応のソフトを作る為の日本語の情報はあまり多くありません。
 今後Oculus Riftで何か作ろうと思っている方への参考の為に、以下に、Oculus Rift 対応の為に前回から変更した内容について簡単に説明したいと思います。

・LibOVR の初期化とHMD情報の取得
 Oculus SDK のライブラリであるLibOVRを使う為には、最初にLibOVRの初期化関数(Init関数)を呼び出す必要があります。続いてOculus用デバイスマネジャーを作成し、それを使ってHMDデバイスの作成を行った後、センサーとHMD情報を取得します。また、センサー値の読出しに必要なとなるSensorFusionオブジェクトを生成し、それにセンサーをアタッチします。これにより、ヘッドトラッキングセンサーの値が読み出せるようになります。

・解像度の変更と全画面モードへの移行
 HMDデバイスから取得したHMD情報の中に、解像度が含まれているので、ウィンドウ作成関数の使用時にその情報を使用する事により解像度の設定を行います。
 また、スワップチェインを作成する際に使用するDXGI_SWAP_CHAIN_DESC構造体のWidthメンバとHeightメンバにもこの解像度を設定し、FlagsメンバにDXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCHを設定します。
 スワップチェインの生成後、メンバ関数であるSetFullscreenStateによりフルスクリーンモードにします。この時、解像度も自動的に変更されます。

・樽歪み表示
 Oculus Riftでは、レンズを通して見た時に正常に見える、歪んだ画像を出力する必要があります。
 その為、スワップチェインのバックバッファに直接出力するのではなく、特別に用意したテクスチャに最初に画像を出力し、それを特別に用意した板ポリに貼り付けてバックバッファに出力します。その際、特別に用意したピクセルシェーダーにより画像を樽歪みさせます。
 また、右目用・左目用の画像は、それぞれ左側・右側に少しだけ寄せてやらないと、大抵の人は両目で見た時に正常に見えません。その為、XMMatrixPerspectiveFovLHで生成した射影変換行列にX方向の平行移動行列を掛ける事により右目用・左目用の行列を作り、それらを描画時の射影変換行列として使用します。
 樽歪みピクセルシェーダーとか、それに渡すパラメータの計算とか、右目・左目用射影変換行列の生成などは、SDKのサンプルプログラムやドキュメントを参考にして実装しました。詳しく説明するのは大変なので、興味のある方はソースを見ていただければと思います。

・センサー値の読み出しと表示への反映
 センサーの値はSensorFusionのメンバー関数GetOrientationにより取得する事ができます。
 結果は四元数(クォータニオン)の形で返されるので、四元数オブジェクトのメンバ関数として用意されているGetEulerAngles関数にり、Y・X・Z軸に対する回転角に変換します。
 これらのうち、Y軸の回転角(ヨー)に関しては、初期値からの差分を現在のヨーとし、X・Z軸に対する回転角(それぞれピッチ・ロール)はそのまま頭のピッチ・ロールとします。
 ただし、LibOVRとDirectXとでは、Z軸の向きが逆になっているので、Z座標を変化させる回転であるヨー及びピッチに関しては、正負を逆転させています。
 ヨーのセンサー値をそのまま使わないのは、センサー以外の入力を反映させる為です。
 今回の場合、Rキーを押した時に向いている方向を前向きとしてヨーをリセットしています。
 また、頭を回す事によって周りが見渡せるだけでは面白くないので、キーボードの入力に従い視点の位置を移動させています。
 これらのヨー・ピッチ・ロール及び視点位置を使って視点の姿勢行列を作り、それを使って左右の視点の位置と注視位置を求め、それらをXMMatrixLookAtLH関数に渡す事により、ビュー変換行列を生成します。この時、上向き方向のベクトル(頭の上方向)を同時に渡す必要がありますが、それはについては視点の姿勢行列の2行目に必要な値が入っているので、それを使用しています。
 なお、行列を実現する型とそれに関する関数は、はDirectXとLibOVRの双方で用意されていますが、DirectXの行列が右掛け変換用なのに対し、LibOVRの行列は左掛け変換用となっています。
 行列の掛け算には交換法則が成り立ちませんので、掛ける方向には要注意です。
 また、上記のように変換行列から何か情報を取り出す場合、行を取り出せばよいのか列を取り出せばよいのかも、どちらの行列を使うかで変わってきます。

・最後に
 現在購入する事のできるOculus Riftは正式な製品版ではなく、開発者向けキットという位置づけとなっており、使いこなすにはゲームに関してある程度の知識が必要という事になっています。
 それでは開発者以外の人が買っても全く使えないのかというと、そういうわけではありません。
 既に有志の方々により様々なデモソフトが開発されていますので、VR体験を楽しむのに必ずしも開発者になる必要はないでしょう。
 しかしながら、やはりこのような未来的なガジェットを手に入れたからには、自分だけの新しい使い方を模索してみたくなるものです。
 そうした時、今回のプログラムが少しでも参考になればと思います。


戻る