LoginSignup
0
0

More than 1 year has passed since last update.

OpenXR API編

Last updated at Posted at 2022-11-09

C++ で OpenXR アプリを作るメモ。
Quest 向けに GLES3 + NDK を主に。

OpenXRのパターン

Swapchain を作る

  • entry_point(main, android_main)
  • Graphics 初期化(OpenGL コンテキストや D3Dデバイス初期化)
  • XrInstance: インスタンス作成
  • XrSystemID 取得
  • XrSession 作成(Graphicsに依存, XrInstanceに対象のGraphics拡張を入れる必要あり)
  • XrSwapchain 初期化(Graphicsに依存, XrInstanceに対象のGraphics拡張を入れる必要あり)
  • XrInstance: Graphics拡張を指定する
  • XrSystemID: どんなGraphicsに対応しているかの情報を含む
  • XrSession, XrSwapchain: Graphics に依存して生成する

OpenGL, OpenGLES, D3D11, D3D112, Vulkan 等のどれを使うかを最初に決定させるのがシンプル。
XrSystemID の情報を見て複数の Graphics をスイッチすることもできるが自作ではそこまでしなくてよいだろう。

Mainloop

  • Mainloop
    • Platform の EventHandling(Android, glfw...etc)
    • OpenXR の EventHandling(session の active を判定)
    • if XrSession active
      • xrWaitFrame
      • xrBeginFrame
      • EachView(left, right...)
        • xrWaitSwapchainImage
        • xrAcquireSwapchainImage
        • render(OpenGLなど)
        • xrReleaseSwapchainImage
      • xrEndFrame

初期化

  XrInstance m_instance;
  XrSession m_session;
  XrSystemId m_systemId;

XrResult

すべて?の OpenXR 関数は XrResult で成功したかどうか返す。

typedef enum XrResult {
    XR_SUCCESS = 0,
    // 省略
} XrResult;

// error 文字列
  if (XR_FAILED(ret)) {
    char errbuf[XR_MAX_RESULT_STRING_SIZE];
    xrResultToString(m_instance, ret, errbuf);
    // logger
  }

xrInitializeLoaderKHR

        // Initialize the loader for this platform
        PFN_xrInitializeLoaderKHR initializeLoader = nullptr;
        if (XR_SUCCEEDED(
                xrGetInstanceProcAddr(XR_NULL_HANDLE, "xrInitializeLoaderKHR", (PFN_xrVoidFunction*)(&initializeLoader)))) {
            XrLoaderInitInfoAndroidKHR loaderInitInfoAndroid;
            memset(&loaderInitInfoAndroid, 0, sizeof(loaderInitInfoAndroid));
            loaderInitInfoAndroid.type = XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR;
            loaderInitInfoAndroid.next = NULL;
            loaderInitInfoAndroid.applicationVM = app->activity->vm;
            loaderInitInfoAndroid.applicationContext = app->activity->clazz;
            initializeLoader((const XrLoaderInitInfoBaseHeaderKHR*)&loaderInitInfoAndroid);
        }

xrCreateInstance

struct android_app *app;

  XrInstanceCreateInfoAndroidKHR ciAndroid = {
      .type = XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR,
      .applicationVM = app->activity->vm,
      .applicationActivity = app->activity->clazz,
  };
  std::array<const char *, 2> extensions = {
      "XR_KHR_android_create_instance",
      "XR_KHR_opengl_es_enable",
  };
  XrInstanceCreateInfo ci = {
      .type = XR_TYPE_INSTANCE_CREATE_INFO,
      .next = &ciAndroid,
      .applicationInfo =
          {
              .apiVersion = XR_CURRENT_API_VERSION,
          },
      .enabledExtensionCount = (uint32_t)extensions.size(),
      .enabledExtensionNames = extensions.data(),
  };
  strncpy(ci.applicationInfo.applicationName, "OXR_GLES_APP",
          XR_MAX_ENGINE_NAME_SIZE - 1);
  auto xrResult = xrCreateInstance(&ci, &m_instance);

xrGetSystem

  XrSystemGetInfo sysInfo = {
      .type = XR_TYPE_SYSTEM_GET_INFO,
      .formFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY,
  };
  auto xrResult = xrGetSystem(m_instance, &sysInfo, &m_systemId);

Graphics初期化

xrCreateSession

View

Swapchain

以下のような構成になっている。

leftView
  swapchain
    [swapchainImage, swapchainImage, ...]
rightView
  swapchain
    [swapchainImage, swapchainImage, ...]

xrWaitSwapchainImage

xrAcquireSwapchainImage

render

XrSwapchainImage に対して XrView で描画する。

XrView

projection matrix

typedef struct XrFovf {
    float    angleLeft; // 👈 負
    float    angleRight;
    float    angleUp;
    float    angleDown; // 👈 負
} XrFovf;

view matrix

xrReleaseSwapchainImage

Frame

Event

xrWaitFrame, xrBeginFrame

xrLocateViews, xrLocateSpace

xrEndFrame

Space

原点を定義する概念。

XR_REFERENCE_SPACE_TYPE_VIEW

HMD の View を原点とする。HUD など画面に貼る付ける要素に使う

XR_REFERENCE_SPACE_TYPE_LOCAL

seated-scale 向け。初期位置を原点とする。
recentering できる。XrEventDataReferenceSpaceChangePending event

XR_REFERENCE_SPACE_TYPE_STAGE

standing-scale, room-scale 向け。
地面に四角形を配置し、その中心が原点。
ユーザーが事前に設定したもの。
設定が無いときは参照できない。

拡張

拡張の一覧や対応状況がまとめられている

XR_EXT_hand_tracking

参考

openxr を使ったアプリが整理されていて、大変参考になります。
マルチプラットフォームの OpenXR-SDK の hello_xr よりも quest 向けで読み易いのでおすすめ。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0