OpenXRシーンの概要
健康と安全に関する推奨事項: 複合現実エクスペリエンスを構築する際、快適かつ安全なエクスペリエンスをユーザーに提供するため、開発者が自分のコンテンツを評価することを強くおすすめします。アプリの設計と開発を始める前に、
健康と安全および
設計に関する各ガイドラインをお読みください。
シーンを使えば、豊富なインタラクション機能を備え、環境を認識する複雑なエクスペリエンスを、ユーザーの物理環境に短時間で構築できます。
パススルーや
空間アンカーとシーンの機能を組み合わせて使用すれば、複合現実エクスペリエンスを構築し、ソーシャルなつながり、エンターテイメント、生産性などの新たな可能性を生み出すことができます。
シーンには、スペースの設定とシーンモデルという2つの重要な概念があります。
スペースの設定は、ユーザーが歩き回ったりシーンをキャプチャしたりして、シーンモデルを生成できるようにするためのシステムフローです。ユーザーにはキャプチャエクスペリエンスに対する完全なコントロールが与えられており、環境について何をシェアするかを決定できます。アプリで、ユーザーのスペースのシーンモデルが存在するかどうかをチェックするためにシステムに問い合わせたり、必要に応じてスペースの設定を呼び出したりすることができます。
シーンモデルは、現実の物理世界についての単一かつ最新の総合的表現であり、容易にインデックスを作成したりクエリを実行したりできます。シーンモデルは、ユーザーの空間を幾何学的および意味的に表現します。それにより、ルーム規模での複合現実エクスペリエンスを構築できます。例えば、ユーザーの壁にバーチャルスクリーンを付けるとか、リアルなオクルージョンにより仮想キャラクターが床の上を動き回るようにするなどです。さらに、物理世界の物体をバーチャルリアリティの中に取り入れることもできます。例えば、ユーザーが自分の現実の机やソファを仮想ワールドの中に見ながら、快適にプレイしたり操作したりできます。
シーンモデルの基本要素はシーンアンカーです。各アンカーには幾何学コンポーネントと意味ラベルが付けられています。例えば、システムはユーザーのリビングルームを、意味ラベルが付けられている個々のアンカー(床、天井、壁、机、ソファなど)を中心に編成します。各アンカーには、シンプルな幾何学表現、2D境界線、または3Dバウンディングボックスも関連付けられています。
シーンモデルは、オペレーティングシステムにより管理され、維持されます。すべてのアプリはシーンモデルにアクセスできます。シーンモデルを利用すれば、ユーザーの周囲の環境を把握して、その環境の中に仮想コンテンツをブレンドすることが簡単に実現できます。
スペースの設定を利用することにより、ユーザーは単一のルームではなく複数のルーム(スペース)をスキャンし、維持することができます。ユーザーは、前のルームを消さずに新しいルームをスキャンできます。OSは最大15のルームを維持し、ユーザーの現在位置によっては、ルームの一部または全部の位置を確認できる可能性があります。
あらゆるプラットフォーム(OpenXR、Unity、Unreal)向けのSDKが、複数のルームをサポートするように設計されています。
- シーン機能はMeta Quest 2、Meta Quest Pro、Meta Quest 3のオペレーティングソフトウェアバージョン40以降でサポートされています。ヘッドセットがインターネットに接続されていること、最新バージョンがインストールされていることを確認します。最新バージョンかどうか確認するには、Meta Questヘッドセットで、[Quick Settings (クイック設定)] > [About (情報)]に移動し、最新バージョンを確認します。先頭が40以上の数字でなければなりません。
Androidマニフェストで、次の要素を追加してシーンと空間アンカーの機能を有効にします。
<uses-permission android:name="com.oculus.permission.USE_ANCHOR_API" />
その後、シーンと空間アンカーに固有の拡張機能ヘッダーをソースコードに含める必要があります。コードに次のヘッダー#includeを設定します。
#include <openxr/openxr.h>
FB OpenXR拡張機能からシーンを使用するには、前のコードブロックで拡張機能ヘッダーを列挙することによりOpenXRインスタンスを作成する必要があります。OpenXRインスタンスの作成に関する詳細は、
インスタンスとセッションの作成をご覧ください。以下はその例です。
const char* const requiredExtensionNames[] = {
XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME,
XR_EXT_PERFORMANCE_SETTINGS_EXTENSION_NAME,
XR_KHR_ANDROID_THREAD_SETTINGS_EXTENSION_NAME,
XR_FB_SPATIAL_ENTITY_EXTENSION_NAME,
XR_FB_SPATIAL_ENTITY_QUERY_EXTENSION_NAME,
XR_FB_SPATIAL_ENTITY_STORAGE_EXTENSION_NAME,
XR_FB_SPATIAL_ENTITY_CONTAINER_EXTENSION_NAME
XR_FB_SCENE_EXTENSION_NAME,
XR_FB_SCENE_CAPTURE_EXTENSION_NAME
};
const uint32_t numRequiredExtensions =
sizeof(requiredExtensionNames) / sizeof(requiredExtensionNames[0]);
このサンプルコードはインスタンスを作成します。
XrInstanceCreateInfo instanceCreateInfo = {XR_TYPE_INSTANCE_CREATE_INFO};
instanceCreateInfo.createFlags = 0;
instanceCreateInfo.applicationInfo = appInfo;
instanceCreateInfo.enabledApiLayerCount = 0;
instanceCreateInfo.enabledApiLayerNames = NULL;
instanceCreateInfo.enabledExtensionCount = numRequiredExtensions;
instanceCreateInfo.enabledExtensionNames = requiredExtensionNames;
XrResult initResult;
OXR(initResult = xrCreateInstance(&instanceCreateInfo, &instance));
if (initResult != XR_SUCCESS) {
ALOGE("Failed to create XR instance: %d.", initResult);
exit(1);
}
このサンプルコードはOpenXRセッションを作成します(VulkanではなくOpenGLESを使用していることにご注意ください)。
XrGraphicsBindingOpenGLESAndroidKHR graphicsBindingAndroidGLES = {XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR};
graphicsBindingAndroidGLES.display = app.Egl.Display;
graphicsBindingAndroidGLES.config = app.Egl.Config;
graphicsBindingAndroidGLES.context = app.Egl.Context;
XrSessionCreateInfo sessionCreateInfo = {XR_TYPE_SESSION_CREATE_INFO};
sessionCreateInfo.next = &graphicsBindingAndroidGLES;
sessionCreateInfo.createFlags = 0;
sessionCreateInfo.systemId = app.SystemId;
OXR(initResult = xrCreateSession(instance, &sessionCreateInfo, &app.Session));
if (initResult != XR_SUCCESS) {
ALOGE("Failed to create XR session: %d.", initResult);
exit(1);
}
詳細については、添付のXrSceneModelサンプルアプリのandroid_main関数をご覧ください。
上記の拡張ヘッダーで定義されている関数を使用するには、関数ポインターをその実装と接続する必要があります。以下はその例です。
OXR(xrGetInstanceProcAddr(
instance,
"xrEnumerateSpaceSupportedComponentsFB",
(PFN_xrVoidFunction*)(&app.FunPtrs.xrEnumerateSpaceSupportedComponentsFB)));
OXR(xrGetInstanceProcAddr(
instance,
"xrGetSpaceComponentStatusFB",
(PFN_xrVoidFunction*)(&app.FunPtrs.xrGetSpaceComponentStatusFB)));
OXR(xrGetInstanceProcAddr(
instance,
"xrSetSpaceComponentStatusFB",
(PFN_xrVoidFunction*)(&app.FunPtrs.xrSetSpaceComponentStatusFB)));
OXR(xrGetInstanceProcAddr(
instance,
"xrGetSpaceUuidFB",
(PFN_xrVoidFunction*)(&app.FunPtrs.xrGetSpaceUuidFB)));
OXR(xrGetInstanceProcAddr(
instance,
"xrQuerySpacesFB",
(PFN_xrVoidFunction*)(&app.FunPtrs.xrQuerySpacesFB)));
OXR(xrGetInstanceProcAddr(
instance,
"xrRetrieveSpaceQueryResultsFB",
(PFN_xrVoidFunction*)(&app.FunPtrs.xrRetrieveSpaceQueryResultsFB)));
OXR(xrGetInstanceProcAddr(
instance,
"xrGetSpaceBoundingBox2DFB",
(PFN_xrVoidFunction*)(&app.FunPtrs.xrGetSpaceBoundingBox2DFB)));
OXR(xrGetInstanceProcAddr(
instance,
"xrGetSpaceBoundingBox3DFB",
(PFN_xrVoidFunction*)(&app.FunPtrs.xrGetSpaceBoundingBox3DFB)));
OXR(xrGetInstanceProcAddr(
instance,
"xrGetSpaceSemanticLabelsFB",
(PFN_xrVoidFunction*)(&app.FunPtrs.xrGetSpaceSemanticLabelsFB)));
OXR(xrGetInstanceProcAddr(
instance,
"xrGetSpaceBoundary2DFB",
(PFN_xrVoidFunction*)(&app.FunPtrs.xrGetSpaceBoundary2DFB)));
OXR(xrGetInstanceProcAddr(
instance,
"xrGetSpaceRoomLayoutFB",
(PFN_xrVoidFunction*)(&app.FunPtrs.xrGetSpaceRoomLayoutFB)));
OXR(xrGetInstanceProcAddr(
instance,
"xrGetSpaceContainerFB",
(PFN_xrVoidFunction*)(&app.FunPtrs.xrGetSpaceContainerFB)));
OXR(xrGetInstanceProcAddr(
instance,
"xrRequestSceneCaptureFB",
(PFN_xrVoidFunction*)(&app.FunPtrs.xrRequestSceneCaptureFB)));
この例では、アプリタイプはovrAppです。これは、添付のXrSceneModelサンプルアプリで定義されている構造体です。サンプルアプリのFunPtrsフィールドは、次のように定義された構造体です。
struct ovrExtensionFunctionPointers {
PFN_xrEnumerateSpaceSupportedComponentsFB xrEnumerateSpaceSupportedComponentsFB = nullptr;
PFN_xrGetSpaceComponentStatusFB xrGetSpaceComponentStatusFB = nullptr;
PFN_xrSetSpaceComponentStatusFB xrSetSpaceComponentStatusFB
= nullptr;
PFN_xrGetSpaceUuidFB xrGetSpaceUuidFB = nullptr;
PFN_xrQuerySpacesFB xrQuerySpacesFB = nullptr;
PFN_xrRetrieveSpaceQueryResultsFB xrRetrieveSpaceQueryResultsFB = nullptr;
PFN_xrGetSpaceBoundingBox2DFB xrGetSpaceBoundingBox2DFB = nullptr;
PFN_xrGetSpaceBoundingBox3DFB xrGetSpaceBoundingBox3DFB = nullptr;
PFN_xrGetSpaceSemanticLabelsFB xrGetSpaceSemanticLabelsFB = nullptr;
PFN_xrGetSpaceBoundary2DFB xrGetSpaceBoundary2DFB = nullptr;
PFN_xrGetSpaceRoomLayoutFB xrGetSpaceRoomLayoutFB = nullptr;
PFN_xrGetSpaceContainerFB xrGetSpaceContainerFB = nullptr;
PFN_xrRequestSceneCaptureFB xrRequestSceneCaptureFB = nullptr;
};