# 機能設計書 18-Camera

## 概要

本ドキュメントは、Three.jsライブラリにおけるCamera機能の設計を詳細に記述するものである。Cameraは、3Dシーンをどの視点からどのように描画するかを定義するための抽象基底クラスである。

### 本機能の処理概要

Cameraクラスは、Object3Dを継承したカメラの基底クラスであり、プロジェクション行列とビュー行列を管理する。実際のアプリケーションでは、PerspectiveCameraやOrthographicCameraなどの派生クラスを使用するが、すべてのカメラはこのCameraクラスを継承している。

**業務上の目的・背景**：3Dレンダリングにおいて、カメラは「どこから」「どの方向を」「どのような投影方法で」シーンを描画するかを定義する重要な要素である。Cameraクラスは、ワールド座標系からカメラ座標系への変換（ビュー行列）と、カメラ座標系からクリップ座標系への変換（プロジェクション行列）を統合的に管理する。これにより、派生クラスは投影方法に固有の処理のみを実装すればよい。

**機能の利用シーン**：すべてのカメラ派生クラス（PerspectiveCamera, OrthographicCamera, CubeCamera, StereoCamera, ArrayCamera）の基底として使用される。直接インスタンス化されることは稀で、主に型テストや共通機能の利用に使用される。

**主要な処理内容**：
1. プロジェクション行列（projectionMatrix）の管理
2. ビュー行列（matrixWorldInverse）の計算
3. プロジェクション行列の逆行列の管理
4. 座標系（WebGL/WebGPU）の設定
5. 逆深度バッファのサポート
6. カメラの向き取得（getWorldDirection）

**関連システム・外部連携**：Object3D（継承元）、WebGLRenderer/WebGPURenderer（描画処理）、Matrix4（行列計算）。

**権限による制御**：特になし

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | Cameraは基底クラスであり、派生クラスが各画面で使用される |

## 機能種別

3Dオブジェクト / 抽象基底クラス

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| - | - | - | コンストラクタは引数なし | - |

### 入力データソース

- 派生クラスから継承して使用

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| projectionMatrix | Matrix4 | プロジェクション行列 |
| projectionMatrixInverse | Matrix4 | プロジェクション行列の逆行列 |
| matrixWorldInverse | Matrix4 | ビュー行列（ワールド行列の逆行列） |
| coordinateSystem | number | 座標系定数 |

### 出力先

- レンダラーに渡されてシェーダーで使用

## 処理フロー

### 処理シーケンス

```
1. Cameraインスタンスの生成
   └─ Object3D初期化、行列初期化、座標系設定

2. シーングラフへの追加
   └─ scene.add(camera) または派生クラスで直接使用

3. ワールド行列の更新
   ├─ updateMatrixWorld(): 親からの継承で呼び出し
   └─ matrixWorldInverseの計算（スケール除外）

4. レンダリング時
   ├─ レンダラーがprojectionMatrixを取得
   └─ レンダラーがmatrixWorldInverseを取得

5. 方向取得
   └─ getWorldDirection(): カメラの向きベクトル（負のZ方向）
```

### フローチャート

```mermaid
flowchart TD
    A[Camera派生クラス生成] --> B[Camera基底クラス初期化]
    B --> C[projectionMatrix初期化]
    C --> D[matrixWorldInverse初期化]
    D --> E[coordinateSystem設定]
    E --> F{updateMatrixWorld呼び出し?}
    F -->|Yes| G[Object3D.updateMatrixWorld]
    G --> H[matrixWorld分解]
    H --> I{スケール=1?}
    I -->|Yes| J[matrixWorldInverse = matrixWorld.invert]
    I -->|No| K[スケール除外してinvert]
    J --> L[レンダリング準備完了]
    K --> L
    F -->|No| L
    L --> M{getWorldDirection?}
    M -->|Yes| N[負のZ方向を返す]
    M -->|No| O[待機]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | Object3D継承 | Object3Dクラスを継承 | クラス定義 |
| BR-02 | タイプフラグ | isCamera=trueを設定 | インスタンス生成時 |
| BR-03 | 座標系デフォルト | coordinateSystemのデフォルトはWebGLCoordinateSystem | インスタンス生成時 |
| BR-04 | スケール除外 | glTF準拠のためビュー行列からスケールを除外 | updateMatrixWorld時 |
| BR-05 | 逆方向視線 | getWorldDirectionはObject3Dと逆（負のZ方向） | 方向取得時 |

### 計算ロジック

- matrixWorldInverse = matrixWorld^(-1)（スケール=1の場合）
- matrixWorldInverse = compose(position, quaternion, (1,1,1))^(-1)（スケール!=1の場合）

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 抽象クラス | 直接インスタンス化は非推奨 | 派生クラスを使用 |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- updateMatrixWorld()は親からの継承で自動呼び出し
- 行列計算はフレームごとに実行されるため軽量であること

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

該当なし

## 備考

- 派生クラス（PerspectiveCamera, OrthographicCamera等）でupdateProjectionMatrix()を実装
- reversedDepthプロパティで逆深度バッファに対応
- WebGPU使用時はcoordinateSystemをWebGPUCoordinateSystemに設定

---

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

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

### 推奨読解順序

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

Cameraの構造とその依存関係を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Camera.js | `src/cameras/Camera.js` | クラス定義全体 |
| 1-2 | Object3D.js | `src/core/Object3D.js` | 継承元クラス |
| 1-3 | Matrix4.js | `src/math/Matrix4.js` | 行列クラス |

**読解のコツ**: Cameraは位置・回転・スケールをObject3Dから継承し、追加でプロジェクション行列を管理する。ビュー行列（matrixWorldInverse）はワールド行列から自動計算される。

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

Cameraの初期化と主要メソッドを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Camera.js | `src/cameras/Camera.js` | コンストラクタ・メソッド |

**主要処理フロー**:
1. **23行目**: コンストラクタでsuper()呼び出し（Object3D初期化）
2. **34行目**: isCameraフラグをtrueに設定
3. **36行目**: type = 'Camera'
4. **43行目**: matrixWorldInverse = new Matrix4()
5. **50行目**: projectionMatrix = new Matrix4()
6. **57行目**: projectionMatrixInverse = new Matrix4()
7. **64行目**: coordinateSystem = WebGLCoordinateSystem
8. **66行目**: _reversedDepth = false
9. **76-80行目**: reversedDepthゲッター
10. **82-95行目**: copy()メソッド
11. **106-110行目**: getWorldDirection() - 負のZ方向を返す
12. **112-130行目**: updateMatrixWorld() - matrixWorldInverseを計算
13. **132-150行目**: updateWorldMatrix() - matrixWorldInverseを計算

#### Step 3: updateMatrixWorldの詳細を理解する

ビュー行列の計算処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Camera.js | `src/cameras/Camera.js` | updateMatrixWorld内部 |

**主要処理フロー**:
1. **114行目**: super.updateMatrixWorld()でObject3Dの処理を実行
2. **118行目**: matrixWorld.decompose()で位置・回転・スケールを取得
3. **120-122行目**: スケール=(1,1,1)の場合、直接invert
4. **124-128行目**: スケール!=(1,1,1)の場合、スケールを(1,1,1)に置換してinvert

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

```
Camera
    │
    └─ extends Object3D
            │
            ├─ position (Vector3)
            │
            ├─ rotation (Euler)
            │
            ├─ quaternion (Quaternion)
            │
            ├─ scale (Vector3)
            │
            └─ matrixWorld (Matrix4)

Camera固有:
    │
    ├─ projectionMatrix (Matrix4)
    │
    ├─ projectionMatrixInverse (Matrix4)
    │
    ├─ matrixWorldInverse (Matrix4)
    │
    └─ coordinateSystem (number)

Camera.updateMatrixWorld()
    │
    ├─ super.updateMatrixWorld() ──▶ Object3D.updateMatrixWorld()
    │
    ├─ matrixWorld.decompose() ───▶ position, quaternion, scale
    │
    └─ matrixWorldInverse.invert() ▶ ビュー行列生成
```

### データフロー図

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

position, rotation, scale
    │
    ▼
Object3D.updateMatrixWorld() ───▶ matrixWorld ───────────────────▶ ワールド行列
    │
    ▼
Camera.updateMatrixWorld() ─────▶ matrixWorldInverse ────────────▶ ビュー行列
    │
    ▼
派生クラス.updateProjectionMatrix() ─▶ projectionMatrix ─────────▶ プロジェクション行列
    │
    ▼
レンダラー ─────────────────────────────────────────────────────▶ シェーダーで使用
    MVP = projectionMatrix * matrixWorldInverse * modelMatrix
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Camera.js | `src/cameras/Camera.js` | ソース | 基底カメラクラス |
| Object3D.js | `src/core/Object3D.js` | ソース | 継承元クラス |
| Matrix4.js | `src/math/Matrix4.js` | ソース | 行列クラス |
| Vector3.js | `src/math/Vector3.js` | ソース | 位置ベクトル |
| Quaternion.js | `src/math/Quaternion.js` | ソース | 回転表現 |
| constants.js | `src/constants.js` | ソース | WebGLCoordinateSystem定数 |
| PerspectiveCamera.js | `src/cameras/PerspectiveCamera.js` | ソース | 派生クラス |
| OrthographicCamera.js | `src/cameras/OrthographicCamera.js` | ソース | 派生クラス |
| CubeCamera.js | `src/cameras/CubeCamera.js` | ソース | 派生クラス |
