# 機能設計書 159-SpotLightHelper

## 概要

本ドキュメントは、Three.jsライブラリにおけるSpotLightHelper機能の設計仕様を記載する。SpotLightHelperはスポットライト（SpotLight）の位置、方向、照射範囲を円錐形で可視化するためのヘルパーオブジェクトである。

### 本機能の処理概要

SpotLightHelperは、スポットライトの照射範囲を円錐形のワイヤーフレーム（cone）で表現する。光源位置から円形の照射面積までの範囲を視覚化し、スポットライトの角度と距離に基づいて動的に形状を更新するデバッグ・開発支援機能である。

**業務上の目的・背景**：スポットライトは角度と距離によって照射範囲が変わる複雑な光源である。SpotLightHelperは、この照射範囲を直感的に把握できる円錐形で可視化することで、ライティング設定のデバッグを支援する。

**機能の利用シーン**：
- スポットライトの照射範囲確認
- 舞台照明のような演出ライティングの設計
- シャドウマップ範囲のデバッグ
- 複数スポットライトの配置調整

**主要な処理内容**：
1. 円錐形（cone）のワイヤーフレーム生成
2. 放射線5本と円周32セグメントの線分構成
3. update()による角度・距離・色の動的更新
4. 親ワールド行列を考慮した位置計算

**関連システム・外部連携**：SpotLightと連携。WebGLRenderer/WebGPURendererによるレンダリングパイプラインと連携。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面機能マッピングに直接的な関連なし。デバッグ用途で利用 |

## 機能種別

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

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| light | SpotLight | Yes | 可視化するスポットライト | SpotLightインスタンス |
| color | number\|Color\|string | No | ヘルパーの色（未指定時はライトの色を使用） | 有効なカラー値 |

### 入力データソース

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

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| SpotLightHelper | Object3D | 円錐形でスポットライトを表すオブジェクト |

### 出力先

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

## 処理フロー

### 処理シーケンス

```
1. コンストラクタ呼び出し
   └─ light, colorパラメータの受け取り
2. lightプロパティ設定
3. matrixAutoUpdate = false
4. colorプロパティ設定
5. cone（円錐）の生成
   └─ 放射線5本（中心、±X、±Y方向）
   └─ 円周32セグメント
   └─ LineSegmentsとして構成
6. update()呼び出し
```

### フローチャート

```mermaid
flowchart TD
    A[開始: new SpotLightHelper] --> B[light, color引数受け取り]
    B --> C[lightプロパティ設定]
    C --> D[matrixAutoUpdate = false]
    D --> E[colorプロパティ設定]
    E --> F[cone用頂点定義開始]
    F --> G[放射線5本の頂点追加]
    G --> H[円周32セグメントの頂点追加]
    H --> I[BufferGeometry作成]
    I --> J[LineBasicMaterial作成]
    J --> K[cone LineSegments作成]
    K --> L[this.add cone]
    L --> M[update呼び出し]
    M --> N[終了]

    O[update呼び出し] --> P[light.updateWorldMatrix]
    P --> Q[target.updateWorldMatrix]
    Q --> R{親オブジェクトあり?}
    R -->|Yes| S[親のmatrixWorld考慮]
    R -->|No| T[lightのmatrixWorld直接使用]
    S --> U[coneLength計算]
    T --> U
    U --> V[coneWidth計算: length × tan angle]
    V --> W[cone.scale設定]
    W --> X[cone.lookAt target]
    X --> Y{color指定あり?}
    Y -->|Yes| Z[指定色を設定]
    Y -->|No| AA[lightの色をコピー]
    Z --> AB[終了]
    AA --> AB
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-159-01 | 自動カラー | color未指定時はlightの色を使用 | color未指定時 |
| BR-159-02 | 距離デフォルト | light.distanceが0の場合は1000を使用 | distance=0時 |
| BR-159-03 | 手動更新 | 光源変形後はupdate()を呼ぶ必要あり | 光源変更時 |
| BR-159-04 | 親考慮 | 親オブジェクトがある場合はその行列を考慮 | 親あり時 |
| BR-159-05 | フォグ無効 | fog: falseでフォグの影響を受けない | 常時 |

### 計算ロジック

円錐サイズの計算:
```javascript
coneLength = light.distance ? light.distance : 1000
coneWidth = coneLength * Math.tan(light.angle)
cone.scale.set(coneWidth, coneWidth, coneLength)
```

円周頂点の計算（32セグメント）:
```javascript
for (i = 0; i < 32; i++) {
  p1 = (i / 32) * Math.PI * 2
  p2 = ((i + 1) / 32) * Math.PI * 2
  // (cos(p1), sin(p1), 1) → (cos(p2), sin(p2), 1)
}
```

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 暗黙的エラー | lightがnull/undefined | エラー発生 |
| - | 暗黙的エラー | light.targetがない | エラー発生 |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- 放射線頂点数: 10（5本 × 2頂点）
- 円周頂点数: 64（32セグメント × 2頂点）
- 合計頂点数: 74
- ドローコール: 1
- update()は光源変更時に手動呼び出し

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

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

## 備考

- dispose()メソッドを呼び出すことでGPUリソースを解放可能
- Object3Dを継承
- coneプロパティで円錐オブジェクトにアクセス可能

---

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

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

### 推奨読解順序

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

SpotLightHelperはObject3Dを継承し、coneというLineSegments子要素を持つ。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SpotLight.js | `src/lights/SpotLight.js` | angle, distance, target属性 |
| 1-2 | Object3D.js | `src/core/Object3D.js` | matrixWorld, updateWorldMatrix |
| 1-3 | Vector3.js | `src/math/Vector3.js` | setFromMatrixPosition |

**読解のコツ**: SpotLightはangle（照射角度）とdistance（照射距離）で照射範囲が決まる。tan(angle)で円錐の底面半径が計算される。

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

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

**主要処理フロー**:
1. **8行目**: _vectorのキャッシュ
2. **36行目**: コンストラクタ開始
3. **45行目**: lightプロパティ設定
4. **47行目**: matrixAutoUpdate = false
5. **55行目**: colorプロパティ設定
6. **57行目**: type = 'SpotLightHelper'
7. **59行目**: BufferGeometry作成開始
8. **61-67行目**: 放射線5本の頂点定義
   - 中心 (0,0,0)→(0,0,1)
   - +X方向 (0,0,0)→(1,0,1)
   - -X方向 (0,0,0)→(-1,0,1)
   - +Y方向 (0,0,0)→(0,1,1)
   - -Y方向 (0,0,0)→(0,-1,1)
9. **69-78行目**: 円周32セグメントの生成ループ
10. **81行目**: position属性設定
11. **83行目**: LineBasicMaterial生成
12. **85行目**: cone LineSegments作成
13. **86行目**: this.add(cone)
14. **88行目**: update()呼び出し

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | SpotLightHelper.js | `src/helpers/SpotLightHelper.js` | 107-149行目のupdate |

**主要処理フロー**:
- **109-110行目**: light/targetのupdateWorldMatrix
- **113-125行目**: 親オブジェクトの考慮
  - 親ありの場合: 親のmatrixWorldの逆行列を適用
  - 親なしの場合: lightのmatrixWorldをそのまま使用
- **128行目**: matrixWorld更新
- **130-131行目**: coneLength/coneWidth計算
- **133行目**: cone.scale設定
- **135行目**: ターゲット位置取得
- **137行目**: cone.lookAt(target)
- **139-147行目**: 色設定

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | SpotLightHelper.js | `src/helpers/SpotLightHelper.js` | 96-100行目のdispose |

**主要処理フロー**:
- **98行目**: cone.geometry.dispose()
- **99行目**: cone.material.dispose()

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

```
SpotLightHelper (src/helpers/SpotLightHelper.js)
    │
    ├─ extends Object3D (src/core/Object3D.js)
    │
    ├─ child: cone (LineSegments)
    │      ├─ BufferGeometry (放射線+円周)
    │      └─ LineBasicMaterial
    │
    └─ references SpotLight (src/lights/SpotLight.js)
           ├─ matrixWorld
           ├─ target.matrixWorld
           ├─ angle
           ├─ distance
           └─ color
```

### データフロー図

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

SpotLight          ───▶  SpotLightHelper Constructor  ───▶  Object3D + cone
    │                        │
    │                        ├─▶ 放射線5本生成
    │                        │        └─▶ 原点→(±1,±1,1)
    │                        │
    │                        └─▶ 円周32セグメント生成
    │                                 └─▶ cos/sin計算
    │
    └── [ライト変更時] ──▶  update()
                                  │
                                  ├─▶ coneLength = distance or 1000
                                  ├─▶ coneWidth = length × tan(angle)
                                  ├─▶ cone.scale設定
                                  └─▶ cone.lookAt(target)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SpotLightHelper.js | `src/helpers/SpotLightHelper.js` | ソース | メイン実装 |
| SpotLight.js | `src/lights/SpotLight.js` | ソース | 対象光源クラス |
| Object3D.js | `src/core/Object3D.js` | ソース | 親クラス（3Dオブジェクト） |
| LineSegments.js | `src/objects/LineSegments.js` | ソース | 子要素（線分描画） |
| 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ベクトル演算 |
