# 機能設計書 157-CameraHelper

## 概要

本ドキュメントは、Three.jsライブラリにおけるCameraHelper機能の設計仕様を記載する。CameraHelperはカメラの視錐台（フラスタム）を線分で可視化するためのヘルパーオブジェクトである。

### 本機能の処理概要

CameraHelperは、指定されたカメラの投影行列に基づいて視錐台の形状を計算し、ニア面・ファー面・側面・上方向インジケータ・ターゲットラインなどを色分けされた線分で描画する。カメラの視野範囲を直感的に把握できるデバッグ・開発支援機能である。

**業務上の目的・背景**：3D開発において、カメラの視野範囲を正確に把握することは、シーン構成やカリング最適化に重要である。CameraHelperは、透視投影・正射影の両方のカメラに対応し、実際の撮影範囲を視覚化することで、カメラ配置の調整を支援する。

**機能の利用シーン**：
- カメラ配置のデバッグ
- シャドウマップ用カメラの範囲確認
- カリング範囲の最適化
- マルチカメラシーンでの各カメラ可視化

**主要な処理内容**：
1. 投影行列の逆行列から視錐台頂点を計算
2. ニア面・ファー面・側面・コーン・上方向・ターゲット・クロスラインの描画
3. 各部位ごとの色分け（setColorsメソッド）
4. update()メソッドによる視錐台の動的更新
5. WebGL/WebGPU座標系への対応

**関連システム・外部連携**：Camera, PerspectiveCamera, OrthographicCameraと連携。WebGLRenderer/WebGPURendererの座標系に対応。

**権限による制御**：本機能に権限制御はない。全てのユーザーが利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 14 | Menubar - View | 補助機能 | カメラヘルパー表示切替 |

## 機能種別

可視化処理 / デバッグ支援

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| camera | Camera | Yes | 可視化するカメラインスタンス | Cameraインスタンス |

### 入力データソース

コンストラクタ引数として直接指定。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| CameraHelper | LineSegments | 視錐台を表す線分オブジェクト |

### 出力先

シーングラフへの追加（scene.add()）によりレンダリング対象となる。

## 処理フロー

### 処理シーケンス

```
1. コンストラクタ呼び出し
   └─ cameraパラメータの受け取り
2. pointMapの構築
   └─ 各頂点に名前付きインデックスをマッピング
3. 線分ペアの定義
   └─ ニア面: n1-n2-n4-n3-n1
   └─ ファー面: f1-f2-f4-f3-f1
   └─ 側面: n1-f1, n2-f2, n3-f3, n4-f4
   └─ コーン: p-n1, p-n2, p-n3, p-n4
   └─ 上方向: u1-u2-u3
   └─ ターゲット: c-t, p-c
   └─ クロス: cn1-cn2, cn3-cn4, cf1-cf2, cf3-cf4
4. BufferGeometryの構築
   └─ position属性とcolor属性を設定
5. LineBasicMaterialの生成
   └─ vertexColors: true, toneMapped: false
6. LineSegmentsとして初期化
7. カメラのmatrixWorldを共有
   └─ matrixAutoUpdate = false
8. update()呼び出し
9. setColors()でデフォルト色設定
```

### フローチャート

```mermaid
flowchart TD
    A[開始: new CameraHelper] --> B[camera引数受け取り]
    B --> C[pointMap初期化]
    C --> D[線分ペア定義ループ]
    D --> E[addLine関数で頂点追加]
    E --> F{全線分定義完了?}
    F -->|No| D
    F -->|Yes| G[BufferGeometry作成]
    G --> H[LineBasicMaterial作成]
    H --> I[LineSegments初期化]
    I --> J[camera.matrixWorldを共有]
    J --> K[update呼び出し]
    K --> L[setColors呼び出し]
    L --> M[終了]

    N[update呼び出し] --> O[投影行列逆行列取得]
    O --> P[座標系判定]
    P --> Q[nearZ/farZ設定]
    Q --> R[各頂点座標計算]
    R --> S[position属性更新]
    S --> T[needsUpdate=true]
    T --> U[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-157-01 | シーン直下配置 | CameraHelperはシーンの直下に配置する必要あり | 常時 |
| BR-157-02 | 手動更新 | カメラ変形・投影行列変更後はupdate()を呼ぶ必要あり | カメラ変更時 |
| BR-157-03 | 座標系対応 | WebGL(-1〜1)とWebGPU(0〜1)の座標系に自動対応 | 常時 |
| BR-157-04 | 反転深度対応 | reversedDepth設定に対応（nearZ=1, farZ=0） | reversedDepth時 |
| BR-157-05 | 色分け | フラスタム/コーン/上/ターゲット/クロスで色を分ける | 常時 |

### 計算ロジック

視錐台頂点の計算:
```javascript
// 正規化デバイス座標から3D座標への変換
vector.set(x, y, z).unproject(camera)
// x, y: -1〜1 (または0〜1)
// z: nearZ or farZ
```

座標系別のZ値:
```javascript
// WebGL座標系
nearZ = -1, farZ = 1
// WebGPU座標系
nearZ = 0, farZ = 1
// 反転深度
nearZ = 1, farZ = 0
```

pointMapの構造:
- n1〜n4: ニア面の4頂点
- f1〜f4: ファー面の4頂点
- p: カメラ位置
- c: 中心
- t: ターゲット
- u1〜u3: 上方向インジケータ
- cn1〜cn4, cf1〜cf4: クロスライン

## データベース操作仕様

該当なし（本機能はデータベースを使用しない）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| Error | 無効な座標系 | camera.coordinateSystemが未知の値 | エラーをスロー |

### リトライ仕様

該当なし

## トランザクション仕様

該当なし

## パフォーマンス要件

- 頂点数: 50（25線分ペア）
- ドローコール: 1
- update()はカメラ変更時に手動呼び出し

## セキュリティ考慮事項

該当なし（クライアントサイドの可視化機能）

## 備考

- dispose()メソッドを呼び出すことでGPUリソースを解放可能
- setColors()で各部位の色をカスタマイズ可能
- lightgl.jsのシャドウマップサンプルを参考に実装

---

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

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

### 推奨読解順序

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

CameraHelperはpointMapで頂点インデックスを管理する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Camera.js | `src/cameras/Camera.js` | projectionMatrixInverseの理解 |
| 1-2 | PerspectiveCamera.js | `src/cameras/PerspectiveCamera.js` | 透視投影の投影行列 |
| 1-3 | Vector3.js | `src/math/Vector3.js` | unproject()メソッドの動作 |
| 1-4 | constants.js | `src/constants.js` | WebGLCoordinateSystem, WebGPUCoordinateSystem |

**読解のコツ**: unproject()は正規化デバイス座標(NDC)からワールド座標への変換を行う。投影行列の逆行列を使用して計算する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | CameraHelper.js | `src/helpers/CameraHelper.js` | 本体実装 |

**主要処理フロー**:
1. **10-11行目**: _vector, _cameraのキャッシュ
2. **39行目**: コンストラクタ開始
3. **41-42行目**: BufferGeometry, LineBasicMaterial初期化
4. **44-47行目**: vertices, colors, pointMap初期化
5. **49-94行目**: addLine()で線分ペア定義
   - **51-54行目**: ニア面（n1-n2-n4-n3-n1）
   - **58-61行目**: ファー面（f1-f2-f4-f3-f1）
   - **65-68行目**: 側面（n-f接続）
   - **72-75行目**: コーン（p-n接続）
   - **79-81行目**: 上方向（u1-u2-u3三角形）
   - **85-86行目**: ターゲット（c-t, p-c）
   - **90-94行目**: クロスライン
6. **96-102行目**: addLine, addPoint関数定義
7. **118-119行目**: BufferGeometry属性設定
8. **130行目**: cameraプロパティ設定
9. **131行目**: updateProjectionMatrix呼び出し
10. **133-134行目**: matrix共有、matrixAutoUpdate=false
11. **143行目**: update()呼び出し
12. **147-153行目**: デフォルト色でsetColors()

#### Step 3: setColorsを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | CameraHelper.js | `src/helpers/CameraHelper.js` | 167-224行目のsetColors |

**主要処理フロー**:
- **169-171行目**: geometryとcolorAttribute取得
- **175-192行目**: 各線分セグメントに色を設定
- **220行目**: needsUpdate = true
- **222行目**: thisを返す

#### Step 4: updateを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | CameraHelper.js | `src/helpers/CameraHelper.js` | 229-309行目のupdate |

**主要処理フロー**:
- **231-232行目**: geometry, pointMap取得
- **234行目**: w, h定数（正規化座標の範囲）
- **241行目**: 投影行列逆行列取得
- **245-268行目**: 座標系判定とnearZ/farZ設定
- **272-305行目**: setPoint()で各頂点座標計算
- **307行目**: needsUpdate = true

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

```
CameraHelper (src/helpers/CameraHelper.js)
    │
    ├─ extends LineSegments (src/objects/LineSegments.js)
    │      └─ extends Line (src/objects/Line.js)
    │             └─ extends Object3D (src/core/Object3D.js)
    │
    ├─ references Camera (src/cameras/Camera.js)
    │      └─ projectionMatrixInverse
    │      └─ matrixWorld
    │      └─ coordinateSystem
    │      └─ reversedDepth
    │
    ├─ uses Vector3 (src/math/Vector3.js)
    │      └─ unproject() → NDC→ワールド変換
    │
    ├─ uses BufferGeometry (src/core/BufferGeometry.js)
    │
    ├─ uses LineBasicMaterial (src/materials/LineBasicMaterial.js)
    │
    └─ uses Color (src/math/Color.js)
           └─ 各部位の色定義
```

### データフロー図

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

Camera            ───▶  CameraHelper Constructor     ───▶  LineSegmentsオブジェクト
    │                        │
    │                        ├─▶ pointMap構築
    │                        │        └─▶ 名前→インデックス対応
    │                        │
    │                        ├─▶ 線分定義
    │                        │        └─▶ 25ペア（50頂点）
    │                        │
    │                        └─▶ update()
    │                                 │
    │                                 ├─▶ projectionMatrixInverse取得
    │                                 ├─▶ 座標系判定
    │                                 └─▶ unproject()で頂点計算
    │
    └── [カメラ変更時] ──▶  update() ───▶ 頂点位置再計算
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| CameraHelper.js | `src/helpers/CameraHelper.js` | ソース | メイン実装 |
| Camera.js | `src/cameras/Camera.js` | ソース | カメラ基底クラス |
| PerspectiveCamera.js | `src/cameras/PerspectiveCamera.js` | ソース | 透視投影カメラ |
| OrthographicCamera.js | `src/cameras/OrthographicCamera.js` | ソース | 正射影カメラ |
| LineSegments.js | `src/objects/LineSegments.js` | ソース | 親クラス（線分描画） |
| Object3D.js | `src/core/Object3D.js` | ソース | 基底クラス（3Dオブジェクト） |
| BufferGeometry.js | `src/core/BufferGeometry.js` | ソース | ジオメトリデータ管理 |
| BufferAttribute.js | `src/core/BufferAttribute.js` | ソース | 頂点属性データ |
| LineBasicMaterial.js | `src/materials/LineBasicMaterial.js` | ソース | 線描画マテリアル |
| Vector3.js | `src/math/Vector3.js` | ソース | 3Dベクトル、unproject |
| Color.js | `src/math/Color.js` | ソース | 色管理ユーティリティ |
| constants.js | `src/constants.js` | ソース | 座標系定数 |
