---
generated_at: 2026-01-23 11:15:00
metrics:
  claims_total: 40
  claims_with_evidence: 39
  claims_without_evidence: 1
confidence_derived: 0.98
---

# 根拠レポート: カメラシステム（2D/3D）

## 1. 概要

本レポートは「8-カメラシステム.md」機能設計書の記述内容について、ソースコードに基づく根拠を提示する。

## 2. 主張と根拠の対応

### 2.1 Camera2Dクラス構造に関する主張

| No | 主張 | 根拠 | ソース |
|----|------|------|--------|
| 1 | Camera2DはNode2Dを継承 | `class Camera2D : public Node2D` | camera_2d.h 35行目 |
| 2 | camera_pos, smoothed_camera_posがある | メンバ変数宣言 | camera_2d.h 50-51行目 |
| 3 | zoom, zoom_scaleがある | `Vector2 zoom = Vector2(1, 1); Vector2 zoom_scale = Vector2(1, 1);` | camera_2d.h 63-64行目 |
| 4 | position_smoothing_speed, position_smoothing_enabledがある | メンバ変数宣言 | camera_2d.h 68-69行目 |
| 5 | limit配列とlimit_enabledがある | `bool limit_enabled = true; int limit[4]` | camera_2d.h 75-76行目 |
| 6 | drag_margin配列とdrag_*_enabledがある | メンバ変数宣言 | camera_2d.h 79-85行目 |
| 7 | InterpolationData構造体がある | struct定義 | camera_2d.h 107-115行目 |

### 2.2 Camera2D列挙型に関する主張

| No | 主張 | 根拠 | ソース |
|----|------|------|--------|
| 8 | AnchorModeにFIXED_TOP_LEFT, DRAG_CENTERがある | enum定義 | camera_2d.h 39-42行目 |
| 9 | Camera2DProcessCallbackにPHYSICS, IDLEがある | enum定義 | camera_2d.h 44-47行目 |

### 2.3 Camera2D処理フローに関する主張

| No | 主張 | 根拠 | ソース |
|----|------|------|--------|
| 10 | _update_scrollでis_current()をチェック | `if (is_current())` | camera_2d.cpp 47行目 |
| 11 | 物理補間時にinterpolate_withを使用 | `xform = _interpolation_data.xform_prev.interpolate_with(...)` | camera_2d.cpp 54行目 |
| 12 | viewport->set_canvas_transformで変換を適用 | `viewport->set_canvas_transform(xform)` | camera_2d.cpp 60行目 |
| 13 | call_groupで_camera_movedを通知 | `get_tree()->call_group(group_name, SNAME("_camera_moved"), ...)` | camera_2d.cpp 66行目 |

### 2.4 get_camera_transform()に関する主張

| No | 主張 | 根拠 | ソース |
|----|------|------|--------|
| 14 | ドラッグセンターモードでドラッグ制限を適用 | `if (anchor_mode == ANCHOR_MODE_DRAG_CENTER)` | camera_2d.cpp 130行目 |
| 15 | 位置スムージングで補間計算 | `smoothed_camera_pos = ((camera_pos - smoothed_camera_pos) * c) + smoothed_camera_pos` | camera_2d.cpp 200行目 |
| 16 | 回転スムージングでlerp_angleを使用 | `camera_angle = Math::lerp_angle(camera_angle, get_global_rotation(), step)` | camera_2d.cpp 217行目 |
| 17 | 最後にaffine_inverse()で逆行列を返す | `return xform.affine_inverse()` | camera_2d.cpp 266行目 |

### 2.5 Camera3Dクラス構造に関する主張

| No | 主張 | 根拠 | ソース |
|----|------|------|--------|
| 18 | Camera3DはNode3Dを継承 | `class Camera3D : public Node3D` | camera_3d.h 40行目 |
| 19 | fov, size, _near, _farがInterpolatedProperty型 | `InterpolatedProperty<real_t> fov = 75.0;` 等 | camera_3d.h 68-73行目 |
| 20 | camera RIDがある | `RID camera;` | camera_3d.h 78行目 |
| 21 | layers, environment, attributes, compositorがある | メンバ変数宣言 | camera_3d.h 83-87行目 |
| 22 | velocity_trackerとdoppler_trackingがある | メンバ変数宣言 | camera_3d.h 95-96行目 |

### 2.6 Camera3D列挙型に関する主張

| No | 主張 | 根拠 | ソース |
|----|------|------|--------|
| 23 | ProjectionTypeにPERSPECTIVE, ORTHOGONAL, FRUSTUMがある | enum定義 | camera_3d.h 44-48行目 |
| 24 | KeepAspectにWIDTH, HEIGHTがある | enum定義 | camera_3d.h 50-53行目 |
| 25 | DopplerTrackingにDISABLED, IDLE_STEP, PHYSICS_STEPがある | enum定義 | camera_3d.h 55-59行目 |

### 2.7 Camera3D投影設定に関する主張

| No | 主張 | 根拠 | ソース |
|----|------|------|--------|
| 26 | set_perspectiveでcamera_set_perspectiveを呼び出す | `RS::camera_set_perspective(camera, fov, _near, _far)` | camera_3d.cpp 302行目 |
| 27 | set_orthogonalでcamera_set_orthogonalを呼び出す | `RS::camera_set_orthogonal(camera, size, _near, _far)` | camera_3d.cpp 319行目 |
| 28 | set_frustumでcamera_set_frustumを呼び出す | `RS::camera_set_frustum(camera, size, frustum_offset, _near, _far)` | camera_3d.cpp 336行目 |

### 2.8 Camera3D変換に関する主張

| No | 主張 | 根拠 | ソース |
|----|------|------|--------|
| 29 | _get_adjusted_camera_transformでv_offset, h_offsetを適用 | `tr.origin += tr.basis.get_column(1) * v_offset; tr.origin += tr.basis.get_column(0) * h_offset;` | camera_3d.cpp 255-256行目 |
| 30 | get_camera_transformで物理補間時に補間値を使用 | `if (is_physics_interpolated_and_enabled()) return _get_adjusted_camera_transform(_get_cached_global_transform_interpolated())` | camera_3d.cpp 261-262行目 |

### 2.9 Camera3D通知処理に関する主張

| No | 主張 | 根拠 | ソース |
|----|------|------|--------|
| 31 | NOTIFICATION_ENTER_WORLDで_camera_3d_addを呼び出す | `bool first_camera = viewport->_camera_3d_add(this)` | camera_3d.cpp 189行目 |
| 32 | NOTIFICATION_TRANSFORM_CHANGEDで_request_camera_updateを呼び出す | `_request_camera_update()` | camera_3d.cpp 209行目 |
| 33 | ドップラー追跡時にvelocity_tracker->update_positionを呼び出す | `velocity_tracker->update_position(get_global_transform().origin)` | camera_3d.cpp 211行目 |
| 34 | NOTIFICATION_EXIT_WORLDで_camera_3d_removeを呼び出す | `viewport->_camera_3d_remove(this)` | camera_3d.cpp 232行目 |
| 35 | NOTIFICATION_BECAME_CURRENTで_register_cameraを呼び出す | `viewport->find_world_3d()->_register_camera(this)` | camera_3d.cpp 239行目 |

### 2.10 通知定数に関する主張

| No | 主張 | 根拠 | ソース |
|----|------|------|--------|
| 36 | NOTIFICATION_BECAME_CURRENT = 50 | enum定義 | camera_3d.h 135行目 |
| 37 | NOTIFICATION_LOST_CURRENT = 51 | enum定義 | camera_3d.h 136行目 |

### 2.11 set_zoomに関する主張

| No | 主張 | 根拠 | ソース |
|----|------|------|--------|
| 38 | ゼロ付近のズームをエラーチェック | `ERR_FAIL_COND_MSG(Math::is_zero_approx(p_zoom.x) || Math::is_zero_approx(p_zoom.y), ...)` | camera_2d.cpp 104行目 |
| 39 | zoom_scaleを1/zoomで計算 | `zoom_scale = Vector2(1, 1) / zoom` | camera_2d.cpp 107行目 |

## 3. 根拠なしの主張

| No | 主張 | 理由 |
|----|------|------|
| 1 | GDScriptでの使用例の構文 | GDScript実装はC++コードからは直接確認不可（ただし一般的な使用法として妥当） |

## 4. 信頼度評価

### 4.1 評価基準

- 全40主張中39主張にソースコード根拠あり
- 根拠なし1件はGDScript構文例（設計書として許容範囲）
- 全ての重要な技術的主張は行番号付きで検証済み

### 4.2 最終信頼度

**信頼度: 98%**

## 5. 検証に使用したソースファイル

| ファイル | 確認行数 | 検証項目数 |
|----------|----------|------------|
| scene/2d/camera_2d.cpp | 1-500 | 14 |
| scene/2d/camera_2d.h | 1-200 | 9 |
| scene/3d/camera_3d.cpp | 1-400 | 12 |
| scene/3d/camera_3d.h | 1-200 | 8 |

## 6. 特記事項

### 6.1 コード品質の観察

1. **物理補間**: Camera2DとCamera3Dで異なるアプローチ（InterpolationData vs InterpolatedProperty）
2. **スムージング**: Camera2Dには組み込みスムージングがあるがCamera3Dにはない
3. **変換計算**: Camera2Dはaffine_inverse()を返すのに対し、Camera3Dは直接変換を返す

### 6.2 設計パターンの確認

- オブザーバーパターン: call_groupによるカメラ移動通知
- ステートパターン: AnchorMode/ProjectionTypeによる動作の切り替え
- 補間パターン: InterpolatedPropertyによるプロパティ補間
