# 機能設計書 176-NodeLibrary

## 概要

本ドキュメントは、Three.jsのノードライブラリ管理クラス「NodeLibrary」の機能設計について記述する。NodeLibraryはライト、マテリアル、トーンマッピングなどのThree.jsの既存機能に対応するノード実装を管理する。

### 本機能の処理概要

NodeLibraryクラスは、Three.jsの従来のライブラリ機能（ライト、マテリアル、トーンマッピング）をノードベースの実装に関連付けるための管理クラスである。WebGPURendererでは、NodeMaterialベースでないマテリアルやライトもノードシステムを通じて処理されるため、このマッピングが不可欠となる。

**業務上の目的・背景**：Three.jsには従来のMeshStandardMaterial、DirectionalLightなどの非ノードベースのクラスが多数存在する。これらをWebGPURenderer（ノードベースレンダラー）で使用するには、対応するノード実装に変換する必要がある。NodeLibraryはこの変換マッピングを一元管理し、既存コードの互換性を維持しながらノードベースレンダリングを実現する。

**機能の利用シーン**：
- 従来のマテリアル（MeshStandardMaterial等）をノードマテリアルに変換する場合
- ライトオブジェクトに対応するライトノードを取得する場合
- トーンマッピング定数に対応するノード関数を取得する場合
- カスタムのライト/マテリアル/トーンマッピングノードを登録する場合

**主要な処理内容**：
1. fromMaterial: 従来のマテリアルをノードマテリアルに変換
2. addLight/getLightNodeClass: ライトとライトノードのマッピング管理
3. addMaterial/getMaterialNodeClass: マテリアルとノードマテリアルのマッピング管理
4. addToneMapping/getToneMappingFunction: トーンマッピング定数と関数のマッピング管理

**関連システム・外部連携**：
- WebGPURenderer: ノードライブラリを使用してマテリアル/ライトを変換
- NodeMaterial: 変換先のノードベースマテリアル
- AnalyticLightNode: ライトのノード実装

**権限による制御**：特になし（内部APIとして使用）

## 関連画面

画面機能マッピングに直接的な関連画面の登録なし。本機能は内部APIとしてレンダラーから呼び出される。

## 機能種別

マッピング管理 / 変換処理 / ノードシステム

## 入力仕様

### 入力パラメータ

#### fromMaterial メソッド

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| material | Material | Yes | 変換対象のマテリアル | - |

#### addLight メソッド

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| lightNodeClass | AnalyticLightNode.constructor | Yes | ライトノードのクラス定義 | 関数であること |
| lightClass | Light.constructor | Yes | ライトのクラス定義 | 関数であること |

#### addMaterial メソッド

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| materialNodeClass | NodeMaterial.constructor | Yes | ノードマテリアルのクラス定義 | 関数であること |
| materialClassType | string | Yes | マテリアルタイプ文字列 | 文字列であること |

#### addToneMapping メソッド

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| toneMappingNode | Function | Yes | トーンマッピングノード関数 | 関数であること |
| toneMapping | number | Yes | トーンマッピング定数 | 数値であること |

### 入力データソース

- Material: 従来のマテリアルオブジェクト
- Light.constructor: ライトのクラス定義
- NodeMaterial.constructor: ノードマテリアルのクラス定義
- トーンマッピング定数: THREE.LinearToneMapping等

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| nodeMaterial | NodeMaterial | 変換されたノードマテリアル |
| lightNodeClass | AnalyticLightNode.constructor | ライトノードのクラス定義 |
| materialNodeClass | NodeMaterial.constructor | ノードマテリアルのクラス定義 |
| toneMappingFunction | Function | トーンマッピング関数 |

### 出力先

- レンダラー内部のノードシステム

## 処理フロー

### 処理シーケンス

#### fromMaterial

```
1. 入力がNodeMaterialか確認
   └─ NodeMaterialの場合はそのまま返却
2. マテリアルタイプからノードマテリアルクラスを取得
3. ノードマテリアルクラスが見つかった場合：
   └─ 新しいインスタンスを作成
   └─ 元のマテリアルの全プロパティをコピー
4. ノードマテリアルを返却（見つからない場合はnull）
```

#### addLight

```
1. addClass()を呼び出してライトノードを登録
   └─ lightNodesマップにマッピングを追加
```

#### addMaterial

```
1. addType()を呼び出してマテリアルノードを登録
   └─ materialNodesマップにマッピングを追加
```

#### addType/addClass

```
1. ライブラリに既に登録されているか確認
   └─ 登録済みの場合は警告を出力して終了
2. nodeClassが関数であることを確認
   └─ 関数でない場合はエラーをスロー
3. type/baseClassが適切な型であることを確認
   └─ 不適切な場合はエラーをスロー
4. ライブラリに登録
```

### フローチャート

```mermaid
flowchart TD
    A[fromMaterial開始] --> B{material.isNodeMaterial?}
    B -->|Yes| C[materialをそのまま返却]
    B -->|No| D[getMaterialNodeClass呼び出し]
    D --> E{nodeMaterialClassあり?}
    E -->|No| F[nullを返却]
    E -->|Yes| G[new nodeMaterialClass]
    G --> H[プロパティをコピー]
    H --> I[nodeMaterialを返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-176-01 | NodeMaterial透過 | 入力がNodeMaterialの場合はそのまま返却 | fromMaterial実行時 |
| BR-176-02 | プロパティ完全コピー | 元マテリアルの全プロパティを新マテリアルにコピー | fromMaterial実行時 |
| BR-176-03 | 重複登録警告 | 既に登録されているマッピングを上書きしようとした場合は警告 | addType/addClass実行時 |
| BR-176-04 | 型検証 | クラス定義は関数であることを検証 | addType/addClass実行時 |

### 計算ロジック

特になし（マッピングテーブルの管理のみ）

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

本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| Error | 例外スロー | nodeClassが関数でない場合 | エラーメッセージを含む例外をスロー |
| Error | 例外スロー | baseClass/typeが不適切な型の場合 | エラーメッセージを含む例外をスロー |
| 警告 | コンソール警告 | 既存のマッピングを上書きしようとした場合 | 警告を出力して処理を中断 |

### リトライ仕様

リトライ処理は実装されていない

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

トランザクション処理は適用されない（メモリ上のマッピング管理）

## パフォーマンス要件

- get系メソッド: O(1)のマップルックアップ
- add系メソッド: O(1)のマップ挿入
- fromMaterial: O(n)（nはプロパティ数）

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

特になし（内部API）

## 備考

- lightNodesはWeakMapで、マテリアルは通常のMapで管理される
- WeakMapを使用することで、ライトオブジェクトがGCされた際にマッピングも自動的にクリーンアップされる
- マテリアルはタイプ文字列で識別されるため、通常のMapを使用

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | NodeLibrary.js | `src/renderers/common/nodes/NodeLibrary.js` | 16-40行目のコンストラクタとプロパティ定義 |

**読解のコツ**: 3種類のマッピングテーブル（lightNodes, materialNodes, toneMappingNodes）の構造を理解する。lightNodesはWeakMap、他2つはMapを使用。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | NodeLibrary.js | `src/renderers/common/nodes/NodeLibrary.js` | 52-74行目 fromMaterialメソッド |

**主要処理フロー**:
1. **54行目**: isNodeMaterialチェック - 既にノードマテリアルなら透過
2. **58行目**: getMaterialNodeClassでクラス取得
3. **60-68行目**: プロパティコピーループ
4. **72行目**: 変換結果を返却

#### Step 3: マッピング登録メソッドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | NodeLibrary.js | `src/renderers/common/nodes/NodeLibrary.js` | 82-86行目 addToneMappingメソッド |
| 3-2 | NodeLibrary.js | `src/renderers/common/nodes/NodeLibrary.js` | 118-122行目 addMaterialメソッド |
| 3-3 | NodeLibrary.js | `src/renderers/common/nodes/NodeLibrary.js` | 142-146行目 addLightメソッド |

**主要処理フロー**:
- **84行目**: addType()に委譲（マテリアル/トーンマッピング用）
- **144行目**: addClass()に委譲（ライト用）

#### Step 4: 内部ヘルパーメソッドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | NodeLibrary.js | `src/renderers/common/nodes/NodeLibrary.js` | 155-169行目 addTypeメソッド |
| 4-2 | NodeLibrary.js | `src/renderers/common/nodes/NodeLibrary.js` | 178-192行目 addClassメソッド |

**主要処理フロー**:
- **157-162行目**: 重複チェックと警告
- **164行目**: nodeClassが関数かチェック
- **165行目**: type/baseClassの型チェック
- **167行目**: ライブラリに登録

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

```
NodeLibrary
    │
    ├─ fromMaterial(material)
    │      ├─ material.isNodeMaterial チェック
    │      ├─ getMaterialNodeClass(material.type)
    │      │      └─ materialNodes.get(materialType)
    │      └─ プロパティコピー
    │
    ├─ addMaterial(materialNodeClass, materialClassType)
    │      └─ addType(materialNodeClass, materialClassType, materialNodes)
    │             ├─ 重複チェック
    │             ├─ 型検証
    │             └─ library.set(type, nodeClass)
    │
    ├─ addLight(lightNodeClass, lightClass)
    │      └─ addClass(lightNodeClass, lightClass, lightNodes)
    │             ├─ 重複チェック
    │             ├─ 型検証
    │             └─ library.set(baseClass, nodeClass)
    │
    ├─ addToneMapping(toneMappingNode, toneMapping)
    │      └─ addType(toneMappingNode, toneMapping, toneMappingNodes)
    │
    ├─ getMaterialNodeClass(materialType)
    │      └─ materialNodes.get(materialType)
    │
    ├─ getLightNodeClass(light)
    │      └─ lightNodes.get(light)
    │
    └─ getToneMappingFunction(toneMapping)
           └─ toneMappingNodes.get(toneMapping)
```

### データフロー図

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

Material ────────────────▶ fromMaterial() ──────────────────▶ NodeMaterial
  │                              │
  └─ type: "MeshStandardMaterial" ├─ getMaterialNodeClass()
                                 │      └─ MeshStandardNodeMaterial
                                 └─ プロパティコピー


Light.constructor ───────▶ addLight() ─────────────────────▶ void
AnalyticLightNode.constructor     │
                                 └─ addClass()
                                        └─ lightNodes.set(Light, Node)


materialType ────────────▶ getMaterialNodeClass() ─────────▶ NodeMaterial.constructor
                                 │
                                 └─ materialNodes.get(type)


toneMapping ─────────────▶ getToneMappingFunction() ───────▶ Function
                                 │
                                 └─ toneMappingNodes.get(toneMapping)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| NodeLibrary.js | `src/renderers/common/nodes/NodeLibrary.js` | ソース | ノードライブラリ管理の本体 |
| NodeMaterial.js | `src/materials/nodes/NodeMaterial.js` | ソース | ノードベースマテリアルの基底クラス |
| MeshStandardNodeMaterial.js | `src/materials/nodes/MeshStandardNodeMaterial.js` | ソース | StandardMaterialのノード版 |
| AnalyticLightNode.js | `src/nodes/lighting/AnalyticLightNode.js` | ソース | ライトノードの基底クラス |
| DirectionalLightNode.js | `src/nodes/lighting/DirectionalLightNode.js` | ソース | DirectionalLightのノード版 |
| ToneMappingFunctions.js | `src/nodes/display/ToneMappingFunctions.js` | ソース | トーンマッピング関数群 |
| utils.js | `src/utils.js` | ソース | warn関数を提供 |
