# 画面設計書 2-Viewport

## 概要

three.js EditorのViewportコンポーネントの設計書。本ドキュメントでは、3Dシーンのプレビュー・操作領域の構成、機能、操作について詳細に記述する。

### 本画面の処理概要

Viewportは、3Dシーンをリアルタイムにレンダリングし、オブジェクトの選択・変形・プレビューを行うためのメイン操作領域である。TransformControls、EditorControls、ViewHelperなどの補助機能を統合し、直感的な3D編集体験を提供する。

**業務上の目的・背景**：3Dシーン編集において、視覚的なフィードバックを即座に得られる環境が不可欠である。Viewportは、ユーザーがオブジェクトを直接操作し、その結果をリアルタイムに確認できる場を提供することで、効率的な3Dコンテンツ制作を支援する。レンダリングモード（ソリッド、ワイヤーフレーム、法線、パストレーシング）の切り替えにより、様々な確認ニーズに対応する。

**画面へのアクセス方法**：エディタメイン画面の中央に常時表示される。特別な操作なしにアクセス可能。

**主要な操作・処理内容**：
1. マウス操作によるカメラ制御（回転、パン、ズーム）
2. オブジェクトのクリック選択（Raycasterによるピッキング）
3. TransformControlsによるオブジェクトの移動・回転・スケール変形
4. ダブルクリックによるオブジェクトへのフォーカス
5. グリッド・ヘルパー表示の切り替え
6. ViewHelperによる視点の素早い切り替え
7. VR/AR（WebXR）モードへの切り替え
8. パストレーシングレンダリング

**画面遷移**：Viewport内での状態変化（選択オブジェクト、カメラ位置など）はSidebarのパネル表示に反映される。オブジェクトを選択すると、Sidebar - Objectパネルが自動的に表示される。

**権限による表示制御**：権限による制御は存在しない。すべての機能がすべてのユーザーに開放されている。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 13 | WebGLRenderer | 主機能 | 3Dシーンのプレビューレンダリング |
| 14 | WebGPURenderer | 主機能 | WebGPU使用時のプレビューレンダリング |
| 4 | Raycaster | 主機能 | マウスピッキングによるオブジェクト選択 |
| 19 | PerspectiveCamera | 主機能 | Viewportカメラの透視投影 |
| 20 | OrthographicCamera | 補助機能 | 正射影カメラへの切り替え時に使用 |
| 154 | GridHelper | 補助機能 | 編集用グリッドの表示 |
| 152 | BoxHelper | 補助機能 | 選択オブジェクトの境界ボックス表示 |
| 168 | PMREMGenerator | 補助機能 | 環境マップのPBR用フィルタリング |
| 7 | Timer | 補助機能 | アニメーション用の時間計測 |

## 画面種別

3Dビュー / プレビュー領域

## URL/ルーティング

- DOM ID: `#viewport`
- URLルーティングなし（エディタ内コンポーネント）

## 入出力項目

| 項目名 | 入力/出力 | データ型 | 説明 |
|--------|----------|----------|------|
| マウス座標 | 入力 | Vector2 | クリック・ドラッグ位置 |
| 選択オブジェクト | 出力 | Object3D | 選択されたシーン内オブジェクト |
| カメラ状態 | 入出力 | Object | 位置、ターゲット、ズームレベル |
| レンダリング画像 | 出力 | Canvas | レンダリング結果 |

## 表示項目

| 要素 | 表示内容 | 説明 |
|------|----------|------|
| 3Dシーン | シーン内の全オブジェクト | メインレンダリング領域 |
| グリッド | 2層のグリッドヘルパー（粗/密） | 空間把握のための基準線 |
| 選択ボックス | Box3Helper | 選択オブジェクトの境界表示 |
| TransformControls | ギズモ（矢印、円、四角） | 変形操作のためのUI |
| ViewHelper | 軸表示キューブ | 視点切り替えUI（右下） |
| ViewportControls | カメラ、シェーディング選択 | 左上のコントロールUI |
| ViewportInfo | オブジェクト数、頂点数、三角形数 | 右上の情報表示 |

## イベント仕様

### 1-オブジェクト選択（クリック）

マウスクリックによるオブジェクト選択処理。

1. `mousedown`イベントでクリック開始位置を記録（行213-218）
2. `mouseup`イベントで終了位置を取得し、移動距離が0なら選択処理を実行（行220-228）
3. `selector.getPointerIntersects()`でRaycastを実行（行198）
4. `signals.intersectionsDetected.dispatch()`で交差結果を通知（行199）
5. Selectorがオブジェクト選択を処理し、`signals.objectSelected`を発火

### 2-オブジェクト変形（ドラッグ）

TransformControlsによるオブジェクト変形処理。

1. TransformControlsの`mouseDown`イベントで変形開始、現在位置を記録（行90-100）
2. ドラッグ中は`objectChange`イベントで`signals.objectChanged`を発火（行85-88）
3. `mouseUp`イベントで変形完了、Commandを生成して履歴に登録（行101-145）
   - translate: SetPositionCommand
   - rotate: SetRotationCommand
   - scale: SetScaleCommand

### 3-カメラ制御

EditorControlsによるカメラ操作。

1. 左ドラッグ: 回転（Orbit）
2. 中ドラッグ/右ドラッグ: パン
3. スクロール: ズーム
4. 操作時に`signals.cameraChanged`を発火（行280-285）
5. パストレーサーモード時は`pathtracer.reset()`を呼び出し（行429）

### 4-ダブルクリック（フォーカス）

オブジェクトへのカメラフォーカス処理。

1. `dblclick`イベントでダブルクリック位置を取得（行255-270）
2. `selector.getPointerIntersects()`でRaycastを実行（行260）
3. 交差があれば`signals.objectFocused.dispatch()`を発火（行266）
4. `controls.focus(object)`でカメラをオブジェクトに向ける（行460-462）

### 5-レンダリング

フレームごとのレンダリング処理。

1. `renderer.setAnimationLoop(animate)`でアニメーションループ開始（行368）
2. `animate()`関数内でアニメーション更新とレンダリング判定（行807-857）
3. `render()`関数でシーン、グリッド、ヘルパー、ViewHelperを描画（行915-936）
4. レンダリング時間を計測し`signals.sceneRendered`を発火（行935）

### 6-シェーディングモード切り替え

viewportShadingChangedシグナルによるモード切り替え。

| モード | 処理 |
|--------|------|
| realistic | パストレーサー初期化（行708） |
| solid | overrideMaterialをnullに（行712） |
| normals | MeshNormalMaterialで上書き（行716） |
| wireframe | MeshBasicMaterial(wireframe)で上書き（行720） |

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

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

Viewportコンポーネント単体でのデータベース操作はない。変形操作はCommandパターンでHistoryに記録され、エディタ全体の自動保存機能によりIndexedDBに永続化される。

## メッセージ仕様

Viewport単体でのメッセージ表示はない。

## 例外処理

| 状況 | 処理 |
|------|------|
| レンダラー未初期化 | `render()`関数冒頭で早期リターン（行917） |
| PMREMGenerator dispose失敗 | console.warnでログ出力し処理継続（行351-354） |
| XR非対応ブラウザ | XRコンポーネントが機能を無効化 |

## 備考

- WebGLRendererとWebGPURendererの両方に対応
- PMREMGeneratorはレンダラー種別によって異なるモジュールを使用（WebGL: THREE.PMREMGenerator、WebGPU: three/webgpu PMREMGenerator）
- パストレーサーはWebGLRenderer使用時のみ利用可能
- ダークモード対応：prefers-color-schemeに応じてグリッド色とクリア色を変更

---

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

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

### 推奨読解順序

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

Viewport内で使用される主要なデータ構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Viewport.js | `editor/js/Viewport.js` | 行24-77でのcontainer、renderer、camera、scene、sceneHelpers、grid、selectionBoxの初期化 |
| 1-2 | Editor.js | `editor/js/Editor.js` | editor.scene、editor.camera、editor.sceneHelpers、editor.selectedの構造 |

**読解のコツ**: THREE.jsのScene、Camera、Rendererの基本概念を理解しておくと、コードの意図が把握しやすい。

#### Step 2: エントリーポイントを理解する

Viewportの初期化とDOMへの追加を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.html | `editor/index.html` | 行83-84でのViewportインスタンス生成とDOM追加 |
| 2-2 | Viewport.js | `editor/js/Viewport.js` | 行24のViewport関数開始、UIPanel生成 |

**主要処理フロー**:
1. **行29-34**: UIPanel作成、ViewportControls/ViewportInfo追加
2. **行48-62**: グリッドヘルパー生成（2層構造）
3. **行67-73**: 選択ボックス（Box3Helper）生成
4. **行79-147**: TransformControls初期化とイベント設定
5. **行279-288**: EditorControls初期化
6. **行341-411**: rendererCreatedシグナルでレンダラー初期化

#### Step 3: イベント処理を理解する

マウス操作とシグナルの連携を追跡。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Viewport.js | `editor/js/Viewport.js` | 行194-274のマウスイベント処理 |
| 3-2 | EditorControls.js | `editor/js/EditorControls.js` | カメラ制御の詳細実装 |
| 3-3 | Selector.js | `editor/js/Selector.js` | getPointerIntersectsの実装 |

**主要処理フロー**:
- **行207-218**: onMouseDown - クリック開始位置記録
- **行220-228**: onMouseUp - 選択処理呼び出し
- **行255-270**: onDoubleClick - フォーカス処理

#### Step 4: レンダリングパイプラインを理解する

アニメーションループとレンダリング処理を追跡。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Viewport.js | `editor/js/Viewport.js` | 行807-857のanimate関数、行915-936のrender関数 |
| 4-2 | Viewport.Pathtracer.js | `editor/js/Viewport.Pathtracer.js` | パストレーサーの実装 |

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

```
Viewport.js
    │
    ├─ UIPanel (container)
    │      ├─ ViewportControls.js
    │      └─ ViewportInfo.js
    │
    ├─ THREE.GridHelper (grid1, grid2)
    │
    ├─ THREE.Box3Helper (selectionBox)
    │
    ├─ TransformControls
    │      └─ commands/SetPositionCommand.js
    │      └─ commands/SetRotationCommand.js
    │      └─ commands/SetScaleCommand.js
    │
    ├─ EditorControls.js
    │
    ├─ ViewHelper.js
    │
    ├─ Viewport.XR.js
    │
    └─ Viewport.Pathtracer.js
           └─ three-gpu-pathtracer
```

### データフロー図

```
[入力]               [処理]                    [出力]

マウスクリック ────▶ getPointerIntersects() ─▶ signals.objectSelected
                         │
                         ▼
                    Raycaster.intersect()
                         │
                         ▼
マウスドラッグ ────▶ TransformControls ──────▶ SetPositionCommand
                                               SetRotationCommand
                                               SetScaleCommand
                         │
                         ▼
               signals.objectChanged ────────▶ render()
                                                  │
                                                  ▼
                                            Canvas出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Viewport.js | `editor/js/Viewport.js` | ソース | メインViewportコンポーネント |
| Viewport.Controls.js | `editor/js/Viewport.Controls.js` | ソース | カメラ・シェーディング選択UI |
| Viewport.Info.js | `editor/js/Viewport.Info.js` | ソース | 情報表示パネル |
| Viewport.ViewHelper.js | `editor/js/Viewport.ViewHelper.js` | ソース | 軸表示・視点切替UI |
| Viewport.XR.js | `editor/js/Viewport.XR.js` | ソース | WebXR連携 |
| Viewport.Pathtracer.js | `editor/js/Viewport.Pathtracer.js` | ソース | パストレーサー |
| EditorControls.js | `editor/js/EditorControls.js` | ソース | カメラ操作コントロール |
| Selector.js | `editor/js/Selector.js` | ソース | オブジェクト選択処理 |
| TransformControls.js | `examples/jsm/controls/TransformControls.js` | ライブラリ | 変形操作ギズモ |
| SetPositionCommand.js | `editor/js/commands/SetPositionCommand.js` | ソース | 位置変更コマンド |
| SetRotationCommand.js | `editor/js/commands/SetRotationCommand.js` | ソース | 回転変更コマンド |
| SetScaleCommand.js | `editor/js/commands/SetScaleCommand.js` | ソース | スケール変更コマンド |
