2015/06/20

GLFW: Oculus Rift ガイド 日本語訳

GLFW: Oculus Rift ガイド


Oculus Rift guide の日本語訳です.途中.
http://www.glfw.org/docs/latest/rift.html


このガイドは,Oculus PC SDK ドキュメントと GLFWのドキュメントとの間にあるギャップを埋めることを目的にしていて,それらを置き換えるものではありません.ネイティブアクセス(native access)の使用が必要で,LibOVR,プラットフォーム固有API,利用する開発環境に関してある程度慣れ親しんでいることを前提としています.
GLFWはLibOVRを明示的にはサポートしていませんが,テストはされていて,LibOVRとの相互運用についても実施中です(While GLFW has no explicit support for LibOVR, it is tested with and tries to interoperate well with it).

Note
Oculus SDKの開発速度によって,このガイドは次の(GLFWの)リリース前に時代遅れになっていると思います. もしこのドキュメントがローカルにコピーされたものなら,最新の情報をGLFWウェブサイトでチェックしてください.ガイドのこの版は,Oculus SDK のバージョン0.4.4を対象として記述されています.

LibOVRとGLFWヘッダファイルのインクルード

OpneGL LibOVRヘッダとGLFWのネイティブヘッダの両方で,ビルドしようとしているOSが何かを伝えるマクロが必要です.LibOVRは主要なデスクトッププラットフォームだけをサポートしているため,標準的な事前定義マクロで解決できます.

#if defined(_WIN32)
#define GLFW_EXPOSE_NATIVE_WIN32
#define GLFW_EXPOSE_NATIVE_WGL
#define OVR_OS_WIN32
#elif defined(__APPLE__)
#define GLFW_EXPOSE_NATIVE_COCOA
#define GLFW_EXPOSE_NATIVE_NSGL
#define OVR_OS_MAC
#elif defined(__linux__)
#define GLFW_EXPOSE_NATIVE_X11
#define GLFW_EXPOSE_NATIVE_GLX
#define OVR_OS_LINUX
#endif
#include <GLFW/glfw3.h>
#include <GLFW/glfw3native.h>
#include <OVR_CAPI_GL.h>

GLFWとLibOVRのヘッダ両方は,デフォルトで標準のOpenGL  GL/gl.h ヘッダ (OpenGL/gl.h on OS X)のインクルードを試みます.もし異なる標準ヘッダやGL拡張ロードライブラリを使いたい場合は,これらの記述の前にインクルードしてください.

LibOVRとGLFWの初期化

LibOVRはGLFWより前に初期化される必要があります.つまり少なくとも ovr_InitializeovrHmd_CreateovrHmd_ConfigureTracking をglfwInit より前に呼び出すことを意味します.同様に,GLFWより後にLibOVRを終了しければなりません.
これは,ovrHmd_Destroy, ovr_Shutdown を glfwTerminateの後に呼ぶことを意味します.

Direct HMD モード

Direct HMDモードは,新しいアプリケーションで推奨されている表示モードですが,Oculus Riftランタイムは現在(2015年1月時点)Windowsだけがこのモードをサポートしています.Direct HMDモードでは,HMDはGLFWモニターとして検出されません.

ウィンドウとコンテキストの作成

もし、HMDがダイレクトモードならフルスクリーンモードかウィンドウモードのどちらかを使用できますが、フルスクリーンはHMDの解像度をサポートしている場合だけ推奨されます。
LibOVRの制限のため、ウィンドウのクライアントエリアのサイズとHMDの解像度は必ず一致してなければなりません。
もしHMDの解像度が通常のモニタ解像度より大きい場合、

If the resolution of the HMD is much larger than the regular monitor, the window may be resized by the window manager on creation. One way to avoid this is to make it undecorated with the GLFW_DECORATED window hint.

HMDへのウィンドウのアタッチ

Once you have created the window and context, you need to attach the native handle of the GLFW window to the HMD.
ovrHmd_AttachToWindow(hmd, glfwGetWin32Window(window), NULL, NULL);

拡張デスクトップ(Extend Desktop) モード

拡張デスクトップモードは旧来の表示モードですが,OS XやLinux上では,技術的な理由でDirect HMDモードをサポートされていないため,このモードだけが利用可能です(2015年1月時点).Windows機でも同様に.

GLFWでHMDを検出する

HMDが拡張デスクトップモードになっている場合,どちらのGLFWモニタがHMDと一致しているかを推定して,そのモニタにフルスクリーンウィンドウを作成します.
Windowsでは,GLFWモニタのネイティブデバイス名は,検出されたHDMのディスプレイデバイス名と対応しています(ovrHmdDescのDisplayDeviceNameメンバに保持されています).
OSX上では,GLFWモニタのネイティブディスプレイIDが検出されたHMDのディスプレイIDに対応しています(ofovrHmdDescのDisplayIdメンバに保持されています).

執筆時点(2015年1月)で,Oculus SDKはどちらのモニタがHMDなのかをちゃんとした方法で検出する方法はサポートしていませんが,
HMDが適切にセットアップと回転されている限り,LibOVRによって提供されるスクリーン位置と解像度を通じて発見することができます.
この方法はHMDをミラリングしている他のモニタを見つけてしまうかもしれませんが,もしそのビデオモードを変更使用としている場合にだけ問題となります.

int i, count;
GLFWmonitor** monitors = glfwGetMonitors(&count);
for (i = 0; i < count; i++)
{
#if defined(_WIN32)
if (strcmp(glfwGetWin32Monitor(monitors[i]), hmd->DisplayDeviceName) == 0)
return monitors[i];
#elif defined(__APPLE__)
if (glfwGetCocoaMonitor(monitors[i]) == hmd->DisplayId)
return monitors[i];
#elif defined(__linux__)
int xpos, ypos;
const GLFWvidmode* mode = glfwGetVideoMode(monitors[i]);
glfwGetMonitorPos(monitors[i], &xpos, &ypos);
if (hmd->WindowsPos.x == xpos &&
hmd->WindowsPos.y == ypos &&
hmd->Resolution.w == mode->width &&
hmd->Resolution.h == mode->height)
{
return monitors[i];
}
#endif
}

ウィンドウとコンテキストの作成

検出されたモニタ上に通常のフルスクリーンウィンドウとして,ウィンドウが作成されます.HMDが正しいビデオモードに既に設定されている場合には,windowed full screenウィンドウを作成することは通常良いアイディアです.しかし,拡張デスクトップモードは通常のモニタとして振る舞い,いくつかのサポートされているビデオモードの受付け可能です.
もし他のモニタだがHDMをミラリングしていて,異なるビデオモードをリクエストしている場合,すべてのミラリング設定されているモニタは新しいビデオモードになります.

HMDへのレンダリング

SDK歪曲レンダリング

もしSDK歪曲(ディストーション)レンダリングを使おうとするなら,レンダラを設定するためにGLFWからいくつかの情報を取り出す必要があります.
GLFWから情報を埋める必要のある ovrGLConfig ユニオンの一部を示します.
他のフィールドも ovrHmd_ConfigureRenderingのために設定する必要があることに注意してください.
SDKディストーションレンダリングを設定する前に,あなたのコンテキストをカレントにしてください.

int width, height;
union ovrGLConfig config;
glfwGetFramebufferSize(window, &width, &height);
config.OGL.Header.BackBufferSize.w = width;
config.OGL.Header.BackBufferSize.h = height;
#if defined(_WIN32)
config.OGL.Window = glfwGetWin32Window(window);
#elif defined(__APPLE__)
#elif defined(__linux__)
config.OGL.Disp = glfwGetX11Display();
#endif

SDKディストーションレンダリングを使う場合,ovrHmd_EndFrameによってHMDが更新されたときに,自分でバッファスワップをしてはいけません.

クライアント歪曲レンダリング

クライアント側で歪曲レンダリングするときは,HMDのコンテンツを完全な制御下におき,通常のレンダリングとバッファスワップを実施します.