WebXR の形状と参照空間
==============

基本的なレベルでは、拡張現実または仮想現実のコンテキストでの WebXR プレゼンテーションのシーンのレンダリングは WebGL を使用して実行されるため、 2 つの API は同じ設計言語の多くを共有します。ただし、XR ヘッドセットなどの機器を使用して真の三次元でシーンを提示する機能を提供するために、WebXR には理解する必要がある追加の概念があります。

この記事では、 WebXR が WebGL の形状を拡張する方法と、オブジェクトの位置と方向（物理的および仮想的）が空間、特に参照空間を使用して相互にどのように記述されるかを紹介します。

WebXR での空間追跡 (en-US)の記事は、ユーザーの頭の物理的な位置と向きだけでなく、手などの潜在的に身体の他の部分がデジタル世界にマッピングされ、物理オブジェクトと仮想オブジェクトの両方が動き回るときに追跡されるかをカバーするため、ここで提供される情報に基づいて、シーンを適切にレンダリングして合成できるようにします。

### 三次元形状の基礎

ここでは、仮想空間内のオブジェクトの位置、方向、動きを計算するために使用される必要な数学演算に加えて、シーンの人間のビューアーを混合物の中に統合する必要性について説明しますが、形状やシーンの三次元表現を管理するための行列とベクトルは、この記事で達成できることの範囲をはるかに超えています。 ウェブの行列計算で個々の演算について詳しく知ることができます。

単位
--

WebXR で使用される 三次元空間の形状の詳細について説明する前に、三次元の世界に適用される測定単位を理解しておくと役に立ちます。

#### 長さと距離

WebGL はすべての距離と長さを**メートル** (meters) で測定します。 WebXR はこの標準を継承しています。 また、世界は幅 2 メートル、高さ 2 メートル、奥行き 2 メートルの立方体であるという事実も継承しています。 3 つの軸のそれぞれの最小値は -1.0、最大値は 1.0 で、立方体の中心は (0, 0, 0) にあります。

![X、Y、Z 座標軸のそれぞれの最小値が -1、最大値が 1 である WebXR 空間を示す図。](/ja/docs/Web/API/WebXR_Device_API/Geometry/defaultspacedimensions.svg)

この 8 立方メートルの空間は、コードのために宇宙全体を囲んでいます。 描画するすべてのものは、コード内で明示的に、または変換を使用してすべての頂点の座標を調整することにより、この空間に収まるように座標をマッピングする必要があります。 もちろん、最も効率的な方法は、WebGL と同じ座標系を使用するようにオブジェクトとコードを設計することです。

WebGL の座標と長さは、レンダリング時にシーンがレンダリングされているビューポートの大きさに自動的に変換されます。

#### 角度

角度は **ラジアン** (radians) を使用して指定します。 度をラジアンに変換するには、度の値に `π/180` を掛けるだけです。 次のコードスニペットは、 2 つの単純な関数、`degreesToRadians()` と `radiansToDegrees()` を示しています。 これらは、角度を測定するために2つの単位間で相互に変換します。


```js
const RADIANS\_PER\_DEGREE = Math.PI / 180.0;

let degreesToRadians = (deg) => deg \* RADIANS\_PER\_DEGREE;
let radiansToDegrees = (rad) => rad / RADIANS\_PER\_DEGREE;
```


#### 時刻と持続時間

**メモ:** セキュリティ上の理由から、`DOMHighResTimeStamp` は通常、フィンガープリントやタイミングベースの攻撃で使用されないようにするために、クロックに少しの不正確さを導入します。

WebXR のすべての時刻と持続時間は、 `DOMHighResTimeStamp` 型を使用して測定します。 これは、開始時刻を基準にミリ秒単位で時刻を指定する倍精度浮動小数点値です。 値は浮動小数点数であるため、プラットフォームとハードウェアによっては、ミリ秒レベルよりも正確である場合があります。

時刻は主に、シーンの前のアニメーションフレームが描画されてからの経過時間を決定するために使用します。 そのため、時刻は通常、ディスプレイのリフレッシュレートに同調し、パフォーマンスの問題によりフレームレートを制限する必要がある場合は、その一部に同調します。 これは、60 FPS のフレームレートを想定して、時刻は通常 1/60 秒の間隔で進むことを意味します。 計算すると、これは各フレームが 16.6667 ミリ秒間隔で理想的にレンダリングされることを意味することがわかります。

### 行列を使用した形状操作

以下に、三次元シーンのレンダリング時に実行する必要がある3つの主要な変換に行列を使用する方法など、三次元形状に関連する行列数学のガイドを提供します。

* **平行移動** (translation) は、仮想空間を介して点の位置をずらすための行列の使用です。この動きは、オブジェクトの軸のいずれか、またはそれらの任意の組み合わせに沿ったものにすることができます。
* **回転** (rotation) は、オブジェクトの座標系の原点を中心に点を回転させる行列の応用です。
* **拡大縮小** (scaling) とは、行列を使用してオブジェクトの大きさを変更することです。

変換が点に適用されると言うとき、その延長線上で考えると、点の*集まり*に適用できることに注意してください。 オブジェクトは空間内のいくつかの点で構成されるいくつかのポリゴンで表されるため、オブジェクトを構成するすべての点に同じ変換を適用すると、オブジェクト全体に同じ変換が適用されます。 ベクトルは座標値を使用して記述され、ベクトルの方向と大きさを定義するため、変換をベクトルに適用することもできます。

空間の原点について
---------

XR で表現されたシーンは、仮想であれ拡張であれ、 1 から数十フレームの参照情報を合成したものです。位置と方向のデータを WebXR システムと直接交換する必要があるシーン内の各オブジェクトは、シーン内の他のオブジェクトが理解できるように、必要に応じて理解および適応できる方法でその情報を報告できる必要があります。

拡張現実 (AR) では、これは、仮想オブジェクトを現実の世界に挿入する必要があるためです。 仮想オブジェクトを正しく配置するだけでなく、ユーザーの視点が変化しても、仮想オブジェクトが自分でさまよっているように見えないようにします。 仮想現実 (VR) では、ユーザーの動きと仮想ディスプレイの映像が一致するような空間演出をすることで、違和感やズレを防ぐことが重要です。

したがって、それは空間感覚を作り出すことがすべてです。 XR 開発者の観点から見ると、ステージの設計はユーザーにとって最も重要な部分です。 建築家やセットデザイナーのように、あなたは物理的な環境を通して気分や体験を生み出す力を持っています。 その空間をどのように構築するかは、ユーザーがどのように対話して探索できるかに依存し、影響を与えます。

**メモ:** 空間には通常、前景、中距離、背景の要素があります。 適切なバランスは、ユニークな存在感を生み出し、ユーザーを導くことができます。 前景には、直接対話できるオブジェクトとインターフェイスが含まれています。 中距離には、ある程度対話できるオブジェクト、またはより密接に調査して関与するために近づくことができるオブジェクトが含まれます。 一方、背景は通常、少なくともユーザーが中距離または前景の範囲に移動して近づくことができない限り、ほとんどまたは完全に非対話です。

WebXR では、（シーンが起こる座標空間など）**空間** (space) の基本的な概念は、`XRSpace` (en-US) のインスタンスによって表されます。 この空間は、ユーザーの環境内のオブジェクトと（光源やカメラなど）他のエンティティの相対位置と動きを決定するために使用します。

三次元空間内の点は、前述のとおり、 3 つの成分で構成され、それぞれが 3 つの軸の 1 つに沿った点の距離を識別します。

これは空間の**ネイティブの原点** (native origin) であり、ユーザーの環境内の特定の物理的な場所に対応しています。 各空間には、XR 機器の追跡システムによって追跡される独自のネイティブの原点があります。 これは、空間のローカル座標系の原点である**実質的な原点** (effective origin) とは異なる場合があります。

座標系の方向性を次の図に示します。

![WebGL および WebXR で使用される座標系を示す図。](/ja/docs/Web/API/WebXR_Device_API/Geometry/webgl_coordinates.svg)

**原点オフセット** (origin offset) と呼ばれる `XRRigidTransform` を使用して、点を空間自体の実質的な座標系から XR 機器のネイティブ座標系に変換します。 通常、 2 つの原点は空間が最初に確立されるときに位置合わせされるため、原点オフセットは最初は単純に恒等変換です。 ただし、位置合わせの変化は時間とともに蓄積されるため、補正するために原点オフセットが変化する場合があります。

原点に対する空間内の点の位置は、上の図に示す 3 つの空間軸のそれぞれに沿った点の距離を決定することによって決定されます。 空間の原点は、空間の中心にあり、各軸に沿ってゼロの位置にある点 (0, 0, 0) です。 具体的には、初期の開始条件の下で、空間に対する閲覧者の既定の向きを使用します。

* **x 軸** (x-axis) は原点から離れて左から右に水平方向に伸び、 +1.0 の x 座標は世界の右端にあります。 x の負の値は、原点から左に向かって伸び、空間の左端で -1.0 の値に達します。
* **y 軸** (y-axis) は正で、原点から画面の上部に向かって上向きに伸び、世界空間の上部で +1.0 に達します。 0 未満の y の値は原点の下にあり、画面の下部に向かって伸び、世界空間の下部で -1.0 に達します。
* **z 軸** (z-axis) は原点から画面の外側に伸び、その方向でユーザーに最も近い点で +1.0 に達します。 z の負の値は、ユーザーから離れて画面内に伸び、世界で最も離れた点の z は -1.0 になります。

すべてのオブジェクトは、最も単純なレベルでは、三次元空間内の点とオフセット変換によって定義される一連のポリゴンであり、オブジェクトを移動および回転して空間内の目的の点に配置する方法を示します。 オフセット変換が単位行列の場合、オブジェクトは原点に配置されます。

ただし、空間追跡やシーン形状に役立つためには、XR 機器の知覚位置を空間の座標系と相関させる必要があります。 そこで参照スペースの出番です。

参照空間
----

さまざまな XR ハードウェアが利用可能であり、多くの開発者からさまざまなフォーム係数で提供されるため、開発者が使用している追跡技術と直接通信する必要があることを期待することは非現実的であり、拡張性がありません。 代わりに、WebXR 機器 API は、開発者がユーザーエクスペリエンスを計画し、それらのニーズを最もよく表す適切な参照空間を要求するように設計されています。 これは、ユーザーエージェントに対してこれらのニーズに一致する **`XRReferenceSpace`** を要求することによって行われます。

`XRReferenceSpace` オブジェクトは、 1 つの座標系の基準系を別の座標系の基準系に適合させる手段として機能します。 ヘッドセットを装着した後、あなたの周りの仮想世界が、あなたの位置が (0, 0, 0) である座標系を持っていると考えてください。 つまり、あなたはすべての中心にいます。 それは力強さを感じませんか？ ヘッドセットに向かって 真正面が -Z 軸で、+Z が後ろにあります。 X は右が正、左が負です。 Y は下に行くと負、上に行くと正になります。 これは、XRシステムの使用開始時の空間におけるヘッドセットの位置を示し、原点 (0, 0, 0) は基本的には鼻筋に配置されています。 この空間が**世界空間** (world space) です。

次に、左手にある XR コントローラーについて考えます。 動きとその向きを報告する機能がありますが、ヘッドセットの位置や、より重要なことに、その座標系については何も知りません。 ただし、コントローラーにはその位置をアプリに報告する方法が必要です。 したがって、独自の座標系があります。 これは、入力イベントが発生したときにアプリに提供される参照空間です。 この参照空間は、コントローラーの座標をヘッドセットの座標にマップする方法を内部的に認識しているため、WebXR は座標を相互に変換できます。

`XRReferenceSpace` を作成すると、モーションとオリエンテーションの追跡を一定レベル保証し、 `XRViewerPose` (en-US)を取得する機構を提供します。この空間がユーザーのヘッドセット、観察者のヘッドセット、仮想カメラなどのビューアを表す場合、ワールド空間に対する位置と向きを表す行列を取得することができます。

これはすべてブラウザーの処理責任であり、基盤となる各参照空間の能力に関係なく、一貫した振る舞いを提供します。 個々の XR 機器がどれほど強力であったりシンプルであっても、WebXR を使用して記述されたコードは、利用可能なハードウェアの制限内で機能します。

選択する参照空間の種類に関係なく、その型は `XRReferenceSpace` または `XRReferenceSpace` から派生した型です。現在利用可能な参照空間型を以下に示します。

`bounded-floor`

`XRBoundedReferenceSpace` で、 `local` 型と同様ですが、返されたオブジェクトの `boundsGeometry` によって指定された所定の境界の外にユーザーが移動することは想定されていません。

`local`

`XRReferenceSpace` で、セッションが作成された時の閲覧者の位置の近くに原点を持つ追跡空間です。正確な位置はプラットフォームと実装に依存します。ユーザーは開始位置からあまり動くことはないと思われますので、追跡はこの用途に最適化されています。 6 つの自由度 (6DoF) 追跡機能を持つ機器の場合、`local`参照空間は、環境に対して原点を安定に保とうとします。

`local-floor`

`local` 型に似た `XRReferenceSpace` で、開始位置が閲覧者が安全に立てる場所に置かれ、 y 軸の値が床面を 0 とすることを除きます。その床レベルが分からない場合、ユーザーエージェントは床レベルを推定します。推定された床レベルが 0 でない場合、ブラウザーはフィンガープリントを避けるような方法でそれを（おそらく最も近いセンチメートルに）丸めることが期待されています。

`unbounded`

`XRReferenceSpace` で、原点から非常に長い距離を自由に移動することができる追跡空間です。閲覧者は全く追跡されません。追跡はユーザーの現在位置の安定性のために最適化されており、ネイティブの原点はその必要性に応じてドリフトすることができます。

`viewer`

`XRReferenceSpace` で、閲覧者の位置と向きを原点として追跡する追跡空間です。これはユーザーが物理的に移動できる環境で使用され、没入型、インライン型問わず `XRSession` (en-US) の全てのインスタンスで対応していますが、インラインセッションで最も有用です。これは、閲覧者と入力の間の距離を決定するとき、またはオフセット空間を扱うときに特に便利です。それ以外では、通常、他の参照空間型のいずれかがより頻繁に使用されます。

このガイドの残りの部分では、アプリのニーズに適した参照空間を選択する方法について説明します。

参照空間を使用した空間関係の定義
----------------

環境に対するオブジェクトの位置と方向を参照したり、環境自体を制約したりするために一般的に使用される方法がいくつかあります。 そのために、WebXR は、**参照空間** (reference space) と呼ばれる標準空間のセットを定義します。 それぞれの標準空間は、ローカル空間の基準系の座標系を、それが存在する空間の座標系に関連付けるさまざまな手法をに対応しています。

ただし、使用している参照空間の型に関係なく、同じ関数を使用して座標を空間から親空間に変換できます。

参照空間型の選択
--------

まず、使用する参照型を決定するプロセスの最も簡単なステップを説明しましょう。 使用する可能性が最も高い参照空間は、`local`、`local-floor`、`unbounded`、`bounded-floor` です。

#### 床レベルの参照空間

名前に `-floor` が含まれている参照空間型は、対応する非床空間と同じように機能しますが、ビューアーが地面またはその近く（常に上）の安全な場所に自動的に配置されるようにします。 これは、他に床が確立されていない限り、`y` 座標が常に 0 である平面です。 これらの空間型は、部屋の床が平らでない場合や、地上の高さが変化する床の場合、アバターの垂直位置の変更をに対応しないため、実行*できません*。

#### 主な参照空間型

`viewer` 参照空間は、ビューアーの空間内の位置に対応します。 `XRFrame` (en-US) メソッド `getViewerPose()` (en-US) によって返される `XRViewerPose` (en-US) によって使用されます。 それ以外の場合、通常は直接使用されません。 唯一の実質的な例外は、ウェブコンテンツ内で XR シーンをインラインで実行するときに `viewer` 参照空間を使用する可能性が高いことです。

`local` 参照空間は、通常、シングルルームなどの比較的小さなエリアを記述するために使用されます。 没入型セッションモード（`immersive-vr` または `immersive-ar`）を使用している場合は常に使用できるだけでなく、新しいセッションを要求するときに常にオプション機能に含まれます。 したがって、`navigator.xr.requestSession()` (en-US) によって作成されたすべてのセッションは、`local` 参照空間型をに対応します。

複数の部屋が含まれる可能性のある大きな領域を表すには、ビューアーの動きに制約を指定しない `unbounded` 参照空間型を使用できます。 ユーザーが特定の領域に移動できないようにする場合は、自分で処理する必要があります。

`bounded-floor` 参照空間型には、対応する床に制限されない型はありません。 ユーザーの XR ハードウェアが現実世界の空間内を移動することを許可し、それが可能である場合、`bounded-floor` 参照空間を使用すると、通過が許可され安全な領域の境界を明確に定義できるため便利です。 制限付き参照空間の使用の詳細については、制限付き参照空間の使用 (en-US)の記事を参照してください。

参照空間を使用してオブジェクトの位置と方向を記述することにより、WebXR は、基盤となる XR ハードウェアに関係なく、これらの記述に使用するデータの形式を標準化できます。 参照空間の構成は、空間のコンテンツを正しくレンダリングするために必要なビュー行列とオブジェクトポーズを提供します。

### 参照空間の確立

最上位の空間（`XRSession` (en-US) のメソッド `requestReferenceSpace()` を呼び出すことによって取得される空間）は、世界空間全体に使用される座標系を表します。 すべては基本的にこの座標系に関連付けられ、ユーザーの機器の位置と仮想世界の間の関係を表します。

WebXR を使用して、アノテーションによる世界の拡張から 360°動画再生、科学シミュレーション、仮想現実トレーニングシステムなど、想像できるあらゆるものに対応できますが、三次元ビデオゲームを典型的な WebXR アプリケーションの例として取り上げましょう。 ゲーム世界の空間に立っているプレイヤーのアバターのモデルを考えてみましょう。 世界空間を基準にしてアバターを配置するには、世界の参照空間で定義された座標系を使用します。

プレーヤーを新しい位置に移動するには、すべての座標を書き換えるか、移動するたびに手動で変換を適用しますが、参照空間とそれらを相互に作成できるため、より簡単な方法があります。 プレーヤーのアバターの新しい位置と方向を表す `XRRigidTransform` オブジェクトを作成してから、`XRReferenceSpace` メソッド `getOffsetReferenceSpace()` を使用して、新しい位置にアバターの視点を表す新しい参照空間を作成します。 これは、キーボードやマウスなどの非 XR 機器を使用してプレーヤーのアバターを世界中に移動するためのサポートを実装する場合に特に便利です。

新しく作成された参照空間を使用すると、アバターは同じ座標に留まることができますが、新しい位置に配置され（そして世界をその視点から見ることができるように）世界に現れます。 参照空間を使用してプレーヤーの視点を管理する方法の詳細については、の記事を参照してください。

私たちのゲームアバターの例の場合、アバター（または他の動いているクリーチャーや機械）が世界中を滑走する単純なブロブになることはまれです。 それらは通常、追加の形だけでなく、動く脚、歩くときに揺れる腕、回転したり素早く上下する頭、動き回る武器などの内部の動きも持っています。 標準の WebGL 手法を使用してこれらを実現し、位置決め行列または `XRRigidTransform` オブジェクトで実質的な原点に対して正しい位置にシフトします。

### 参照空間に関するデバイスの制限

一部の XR 機器は、API が不足している機能を補うために努力しているにもかかわらず、特定の体験をに対応するように作成できないものもあります。 例えば、GearVR デバイスなどの基本的なヘッドセットを、ユーザーが実質的な動きを追跡して環境を歩き回るのをに対応する必要があるアプリで機能させる方法はありません。

プログレッシブエンハンスメントをに対応し、それによってアプリまたはサイトの可用性を広げるには、必要な機能の量が最も少ない参照空間を選択するか、参照空間の取得の失敗を検出し、あまり強力でない代替手段で再試行するフォールバックメカニズムを提供します。

発生する互換性の問題は、VR のみのヘッドセットで `immersive-ar` モード（拡張現実セッション）をに対応できないのと同じくらい根本的なものであるか、XR セッションを作成しようとしたときに満たすことができない1つ以上の必須オプションの要求が含まれる場合があります。

XR セッションは、`navigator.xr.requestSession()` (en-US) メソッドを使用して作成します。 オプションの引数の 1 つは、`XRSessionInit` (en-US) 辞書に準拠したオブジェクトであり、これを使用して、セッションが対応する必要がある（または理想的には対応すべき）必須またはオプションの機能を指定できます。 現在対応しているオプションは、標準参照空間を識別する文字列のみです。 これらを使用すると、コードを実行する前に、必要な、または優先する参照空間型をに対応できる WebXR セッションにアクセスできることを保証できます。

**メモ:** 現在、`XRSession` (en-US) を作成するときに使用できるオプションは、使用または優先する参照空間のみです。 将来的には、より多くのオプションが利用可能になる可能性があります。

オブジェクトの配置と方向付け
--------------

アプリと WebXR API の間で交換されるすべての空間（位置、方向、および動き）情報は、フレームのレンダリング時に特定の空間に関連して表現されます。 それ以上の位置と方向の管理はユーザーと WebGL の間で行われますが、オブジェクトを 三次元世界に正しく配置するために、参照空間からの原点オフセットを利用します。

アニメーションフレームをレンダリングするときは、WebXR セッションの `XRSession` (en-US) オブジェクトの `requestAnimationFrame()` (en-US) メソッドを呼び出したときに指定されたコールバック関数が呼び出されます。 コールバックは、その引数の1つとして、フレームが発生する時刻を示すタイムスタンプを受け取り、対応するアニメーションフレームのすべてのレンダリングを実行する必要があります。

時刻値を増やしながらコールバックが繰り返し呼び出されると、コールバックは XR ハードウェアを使用して提示される一連のフレームを生成し、それによって 三次元シーンがユーザーに表示されます。

アニメーションプロセスの詳細については、レンダリングと WebXR フレームアニメーションコールバックの記事を参照してください。

仮想空間でオブジェクトを配置、方向付け、移動する方法の例と、コードレベルでの詳細な説明については、移動、向き、モーションの記事を参照してください。

関連情報
----

* WebXR 機器 API
* WebGL: ウェブのための 2D および 3D レンダリング
* ウェブの行列計算