# 画面設計書 26-WebXRサンプル

## 概要

本ドキュメントは、three.js Examples における WebXR API を使用した VR/AR サンプル群（約26件）の画面設計書である。VR ヘッドセットや AR デバイス向けの没入型体験を実現するための WebXR Device API のデモンストレーションを提供する。

### 本画面の処理概要

WebXRサンプル画面は、three.js の WebXR 対応機能を使用した VR（Virtual Reality）と AR（Augmented Reality）のサンプル集である。VRヘッドセット（Meta Quest、HTC VIVE等）やARデバイス（スマートフォン、タブレット）向けの没入型体験を実装している。ハンドトラッキング、コントローラー入力、ヒットテスト（AR）、空間アンカーなどの機能を提供する。

**業務上の目的・背景**：VR/AR アプリケーション開発者に対して、WebXR Device API と three.js の統合方法を提供する。ゲーム、トレーニング、バーチャルショールーム、AR ナビゲーションなど、様々な没入型アプリケーションの開発に活用できる。ネイティブアプリを開発せずにブラウザ上で VR/AR 体験を提供できる点が利点である。

**画面へのアクセス方法**：
1. examples/index.html にアクセス
2. 左側パネルの「webxr」カテゴリを選択
3. 検索フィルタで「webxr」「vr」「ar」を入力して絞り込み
4. 目的のサンプルを選択
5. VR/AR デバイスを接続し、「Enter VR」または「Start AR」ボタンをクリック

**主要な操作・処理内容**：
1. WebXR セッションの開始と終了
2. VR/AR コントローラーからの入力処理
3. ハンドトラッキングによる手の位置・ジェスチャー検出
4. AR ヒットテストによる現実世界の平面検出
5. VR テレポート移動
6. ハプティックフィードバック（振動）

**画面遷移**：
- 遷移元：Examples一覧画面（examples/index.html）
- 遷移先：XR セッション（VR/AR モード）
- GitHub ソースコードページへの外部リンクあり

**権限による表示制御**：
- VR サンプル：VR ヘッドセット接続時のみ「Enter VR」ボタン表示
- AR サンプル：AR 対応デバイス（モバイル等）でのみ「Start AR」ボタン表示

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 177 | WebXRController | 主機能 | XRコントローラーの管理 |
| 178 | XRManager | 主機能 | WebXRセッション管理 |
| 22 | StereoCamera | 補助機能 | VRステレオ表示 |
| 13 | WebGLRenderer | 補助機能 | レンダリング処理 |
| 19 | PerspectiveCamera | 補助機能 | カメラ設定 |

## 画面種別

サンプル / デモンストレーション / インタラクティブ

## URL/ルーティング

- カテゴリ: `examples/index.html` (webxr)
- 個別サンプル:
  - `examples/webxr_ar_hittest.html` - AR ヒットテスト
  - `examples/webxr_ar_cones.html` - AR コーン配置
  - `examples/webxr_vr_handinput.html` - VR ハンドトラッキング
  - `examples/webxr_vr_teleport.html` - VR テレポート
  - `examples/webxr_xr_dragging.html` - オブジェクトドラッグ
  - 他約21件

## 入出力項目

| 項目名 | 入出力 | データ型 | 説明 |
|--------|--------|----------|------|
| XR セッション状態 | 入力 | XRSession | VR/AR セッション情報 |
| コントローラー入力 | 入力 | XRInputSource | ボタン、トリガー、スティック |
| ハンド入力 | 入力 | XRHand | 手の関節位置 |
| ヒットテスト結果 | 入力 | XRHitTestResult | AR 平面検出結果 |
| ステレオレンダリング | 出力 | Canvas x 2 | 左右目用のレンダリング |
| ハプティクス | 出力 | Vibration | コントローラー振動 |

## 表示項目

| 項目名 | 表示形式 | 説明 |
|--------|----------|------|
| 3Dシーン（VR/AR） | XR Display | ヘッドセットまたはデバイスへの出力 |
| Enter VR/Start AR ボタン | HTML button | XR セッション開始用のUI |
| レティクル | 3D Mesh | AR ヒットポイントの表示 |
| ハンドモデル | 3D Model | 手の可視化 |
| コントローラーモデル | 3D Model | VR コントローラーの可視化 |

## イベント仕様

### 1-XR セッション開始

「Enter VR」または「Start AR」ボタン押下時：
1. ARButton.createButton() または VRButton.createButton() でボタン作成
2. renderer.xr.enabled = true で XR 対応を有効化
3. ユーザーがボタンをクリックすると XR セッション開始
4. renderer.setAnimationLoop() で XR フレームループ開始

### 2-コントローラー入力

VR コントローラーからの入力処理：
1. renderer.xr.getController(index) でコントローラー取得
2. 'select' イベントでトリガー押下を検出
3. 'squeeze' イベントでグリップ押下を検出
4. controller.position/rotation でコントローラー位置取得

### 3-ハンドトラッキング

ハンドトラッキング対応デバイスでの処理：
1. renderer.xr.getHand(index) でハンド取得
2. XRHandModelFactory でハンドモデル作成
3. 各関節（ジョイント）の位置・回転を取得
4. ジェスチャー検出（ピンチ、グラブ等）

### 4-AR ヒットテスト

AR モードでの平面検出：
1. session.requestReferenceSpace('viewer') でリファレンススペース取得
2. session.requestHitTestSource() でヒットテストソース作成
3. frame.getHitTestResults() でヒット結果を取得
4. hit.getPose() で位置・向きを取得
5. レティクルを配置してユーザーにフィードバック

### 5-オブジェクト選択（select イベント）

コントローラーでオブジェクトを選択時：
1. controller.addEventListener('select', onSelect)
2. onSelect 内でレイキャストまたはレティクル位置を使用
3. 新しいオブジェクトを配置または既存オブジェクトを操作

## データベース更新仕様

### 操作別データベース影響一覧

本画面はフロントエンドのみで動作するサンプルであり、データベースへのアクセスは行わない。

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| - | - | - | データベース操作なし |

## メッセージ仕様

| 種別 | メッセージ | 発生条件 |
|------|-----------|----------|
| 情報 | "ENTER VR" / "START AR" | XR 対応デバイス検出時 |
| 警告 | "VR NOT SUPPORTED" | VR 非対応デバイス |
| 警告 | "AR NOT SUPPORTED" | AR 非対応デバイス |

## 例外処理

| 例外状況 | 処理内容 |
|----------|----------|
| WebXR 非対応ブラウザ | エラーメッセージ表示、通常の 3D 表示 |
| XR デバイス未接続 | ボタン無効化、接続案内表示 |
| ヒットテスト失敗 | レティクル非表示 |
| コントローラー切断 | イベントリスナー解除 |

## 備考

- WebXR は HTTPS または localhost でのみ動作
- VR サンプルは Meta Quest、HTC VIVE 等で動作確認
- AR サンプルは ARCore/ARKit 対応デバイスで動作
- ハンドトラッキングは対応ヘッドセット（Quest 2+等）が必要
- iframe 内での XR セッションには allow="xr-spatial-tracking" が必要

---

## コードリーディングガイド

本画面を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

WebXR 関連のクラスと API の構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | WebXRManager.js | `src/renderers/webxr/WebXRManager.js` | XR セッション管理 |
| 1-2 | WebXRController.js | `src/renderers/webxr/WebXRController.js` | コントローラー入力 |
| 1-3 | ARButton.js | `examples/jsm/webxr/ARButton.js` | AR セッション開始ボタン |
| 1-4 | VRButton.js | `examples/jsm/webxr/VRButton.js` | VR セッション開始ボタン |

**読解のコツ**: renderer.xr プロパティが WebXRManager のインスタンス。XRSession, XRReferenceSpace などは WebXR Device API のネイティブオブジェクト。

#### Step 2: AR ヒットテストを理解する

AR サンプルの基本的な構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | webxr_ar_hittest.html | `examples/webxr_ar_hittest.html` | AR ヒットテストの実装 |

**主要処理フロー**:
1. **Line 27**: ARButton.createButton() でボタン作成（requiredFeatures: ['hit-test']）
2. **Line 55-60**: renderer.xr.enabled = true で XR 有効化
3. **Line 64**: ARButton.createButton() の結果を DOM に追加
4. **Line 84-90**: renderer.xr.getController() でコントローラー取得
5. **Line 92-98**: レティクル（Ring）を作成
6. **Line 117-166**: animate() 内でヒットテスト処理
7. **Line 124-134**: hitTestSource のリクエスト
8. **Line 147-162**: ヒット結果からレティクル位置を更新

#### Step 3: VR コントローラーを理解する

VR コントローラー入力の処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | webxr_xr_dragging.html | `examples/webxr_xr_dragging.html` | コントローラーでのドラッグ |

**主要処理フロー**:
- controller.addEventListener('selectstart', onSelectStart)
- controller.addEventListener('selectend', onSelectEnd)
- 選択中のオブジェクトをコントローラーに attach/detach

#### Step 4: ハンドトラッキングを理解する

ハンドトラッキングの実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | webxr_vr_handinput.html | `examples/webxr_vr_handinput.html` | ハンドトラッキングサンプル |
| 4-2 | XRHandModelFactory.js | `examples/jsm/webxr/XRHandModelFactory.js` | ハンドモデル生成 |

**主要処理フロー**:
- renderer.xr.getHand(index) でハンド取得
- XRHandModelFactory.createHandModel() でモデル作成
- 'pinchstart', 'pinchend' イベントでピンチジェスチャー検出

### プログラム呼び出し階層図

```
webxr_ar_hittest.html (エントリーポイント)
    |
    +-- ARButton.createButton(renderer, { requiredFeatures: ['hit-test'] })
    |      +-- navigator.xr.requestSession('immersive-ar', ...)
    |
    +-- renderer.xr.enabled = true
    |      +-- WebXRManager の初期化
    |
    +-- renderer.xr.getController(0)
    |      +-- controller.addEventListener('select', onSelect)
    |
    +-- animate(timestamp, frame)
    |      |
    |      +-- [XR セッション中]
    |      |      +-- frame.getHitTestResults(hitTestSource)
    |      |      +-- hit.getPose(referenceSpace)
    |      |      +-- reticle.matrix.fromArray(pose.transform.matrix)
    |      |
    |      +-- renderer.render(scene, camera)
    |
    +-- onSelect()
           +-- if (reticle.visible)
                  +-- new THREE.Mesh(geometry, material)
                  +-- scene.add(mesh)
```

### データフロー図

```
[AR ヒットテストのデータフロー]

XRSession ────────> requestReferenceSpace('viewer')
                          |
                          v
                    requestHitTestSource()
                          |
                          v
XRFrame ──────────> getHitTestResults()
                          |
                          v
XRHitTestResult[] ──> hit.getPose(referenceSpace)
                          |
                          v
XRPose ──────────────> transform.matrix
                          |
                          v
                    reticle.matrix.fromArray()
                          |
                          v
                    レティクル表示


[VR コントローラーのデータフロー]

XRInputSource ────────> renderer.xr.getController(index)
                              |
                              v
WebXRController ────────> position/rotation
                              |
                              v
                        select/squeeze イベント
                              |
                              v
                        ユーザーインタラクション
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| WebXRManager.js | `src/renderers/webxr/WebXRManager.js` | ソース | XR セッション管理 |
| WebXRController.js | `src/renderers/webxr/WebXRController.js` | ソース | コントローラー入力 |
| ARButton.js | `examples/jsm/webxr/ARButton.js` | ソース | AR セッション開始 |
| VRButton.js | `examples/jsm/webxr/VRButton.js` | ソース | VR セッション開始 |
| XRHandModelFactory.js | `examples/jsm/webxr/XRHandModelFactory.js` | ソース | ハンドモデル生成 |
| XRControllerModelFactory.js | `examples/jsm/webxr/XRControllerModelFactory.js` | ソース | コントローラーモデル生成 |
| webxr_ar_*.html | `examples/webxr_ar_*.html` | テンプレート | AR サンプル |
| webxr_vr_*.html | `examples/webxr_vr_*.html` | テンプレート | VR サンプル |
| webxr_xr_*.html | `examples/webxr_xr_*.html` | テンプレート | VR/AR 共通サンプル |
