# 機能設計書 76-InstancedMesh

## 概要

本ドキュメントは、Three.jsライブラリにおけるInstancedMesh（インスタンスメッシュ）機能の設計を記述する。InstancedMeshは、同一のジオメトリとマテリアルを持つ多数のオブジェクトを効率的にレンダリングするためのGPUインスタンシング機能を提供する。

### 本機能の処理概要

InstancedMeshは、Meshクラスを継承し、同一のジオメトリとマテリアルを持つ複数のインスタンスを単一のドローコールでレンダリングする。各インスタンスは個別の変換行列（位置、回転、スケール）と色を持つことができ、大量のオブジェクト（森の木、群衆、パーティクル等）を効率的に描画する。

**業務上の目的・背景**：3Dグラフィックスにおいて、同一のメッシュを大量に描画する場合、個別にMeshオブジェクトを作成するとドローコールが増加し、パフォーマンスが著しく低下する。InstancedMeshはGPUインスタンシングを活用し、単一のドローコールで数千〜数万のインスタンスを描画することで、CPU-GPU間のオーバーヘッドを大幅に削減する。

**機能の利用シーン**：森林シミュレーション（木々の大量描画）、群衆シミュレーション、パーティクルシステム、星空や小惑星帯の表現、建築ビジュアライゼーションでの繰り返しオブジェクト。

**主要な処理内容**：
1. インスタンスごとの変換行列（instanceMatrix）の管理
2. インスタンスごとの色（instanceColor）の管理（オプション）
3. インスタンスごとのモーフターゲット重み（morphTexture）の管理
4. 境界ボックス/境界球の計算
5. インスタンス単位のレイキャスト

**関連システム・外部連携**：WebGLRenderer/WebGPURenderer、InstancedBufferAttribute、DataTexture（モーフ用）、AnimationMixer。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 23 | WebGL上級サンプル | 補助機能 | インスタンス描画 |

## 機能種別

3Dオブジェクト生成 / GPUインスタンシング

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| geometry | BufferGeometry | No | メッシュのジオメトリ | BufferGeometry型 |
| material | Material/Array<Material> | No | メッシュのマテリアル | Material型または配列 |
| count | number | Yes | インスタンス数 | 正の整数 |

### 入力データソース

JavaScriptコードからのコンストラクタ呼び出し。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| isInstancedMesh | boolean | 型識別フラグ（常にtrue） |
| instanceMatrix | InstancedBufferAttribute | 全インスタンスの変換行列（Float32Array、16要素/インスタンス） |
| previousInstanceMatrix | InstancedBufferAttribute | 前フレームの変換行列（速度計算用、オプション） |
| instanceColor | InstancedBufferAttribute | 全インスタンスの色（オプション） |
| morphTexture | DataTexture | モーフターゲット重み（オプション） |
| count | number | インスタンス数 |
| boundingBox | Box3 | 全インスタンスの境界ボックス（オプション） |
| boundingSphere | Sphere | 全インスタンスの境界球（オプション） |

### 出力先

3Dシーングラフ、WebGLレンダリングパイプライン（インスタンス描画）

## 処理フロー

### 処理シーケンス

```
1. コンストラクタ呼び出し
   └─ Meshの初期化
   └─ instanceMatrixの作成（count * 16 のFloat32Array）
   └─ 全インスタンスを単位行列で初期化
2. setMatrixAt() - インスタンスの変換設定
3. setColorAt() - インスタンスの色設定（初回呼び出し時にinstanceColor作成）
4. setMorphAt() - インスタンスのモーフ設定（初回呼び出し時にmorphTexture作成）
5. レイキャスト時
   └─ 各インスタンスについて個別にMesh.raycastを実行
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[Meshコンストラクタ]
    B --> C[isInstancedMesh = true]
    C --> D[instanceMatrix作成]
    D --> E[全インスタンスを単位行列で初期化]
    E --> F[終了]

    G[setMatrixAt] --> H[行列を配列に書き込み]

    I[setColorAt] --> J{instanceColor存在?}
    J -->|No| K[instanceColor作成]
    J -->|Yes| L[色を配列に書き込み]
    K --> L
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-76-1 | needsUpdate必須 | setMatrixAt/setColorAt後はneedsUpdate=trueが必要 | 変更反映時 |
| BR-76-2 | 境界の手動計算 | boundingBox/boundingSphereは自動計算されない | 手動呼び出し必要 |
| BR-76-3 | モーフテクスチャ更新 | setMorphAt後はmorphTexture.needsUpdate=trueが必要 | 変更反映時 |

### 計算ロジック

**境界球の計算**：
```javascript
// 全インスタンスの変換済み境界球を結合
for (let i = 0; i < count; i++) {
    getMatrixAt(i, matrix);
    sphere.copy(geometry.boundingSphere).applyMatrix4(matrix);
    boundingSphere.union(sphere);
}
```

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

データベース操作なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 表示異常 | needsUpdateを設定せずに描画 | needsUpdate=trueを設定 |
| - | 範囲外アクセス | 不正なインデックス指定 | index < countを確認 |

### リトライ仕様

該当なし。

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

該当なし。

## パフォーマンス要件

- 単一ドローコールで数千〜数万インスタンスを描画可能
- instanceMatrix.needsUpdate=trueはGPUへの転送を発生させるため、頻繁な更新は避ける
- computeBoundingBox/computeBoundingSphereは全インスタンスをイテレートするため、count増加に伴い処理時間が増加

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

特になし。

## 備考

- InstancedMeshはMeshを継承しているため、基本的なMeshの機能を継承
- updateMorphTargets()は空のメソッドとしてオーバーライドされている
- dispose()でmorphTextureが解放される

---

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

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

### 推奨読解順序

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

InstancedMeshが持つプロパティの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | InstancedBufferAttribute.js | `src/core/InstancedBufferAttribute.js` | インスタンスバッファ属性 |
| 1-2 | DataTexture.js | `src/textures/DataTexture.js` | モーフ用データテクスチャ |
| 1-3 | Mesh.js | `src/objects/Mesh.js` | 基底クラス |

**読解のコツ**: instanceMatrixは16要素（4x4行列）×インスタンス数のFloat32Arrayで構成される。

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

InstancedMeshクラスの構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | InstancedMesh.js | `src/objects/InstancedMesh.js` | クラス全体の構造 |

**主要処理フロー**:
1. **37-39行目**: コンストラクタでMeshを初期化
2. **48行目**: isInstancedMeshフラグの設定
3. **57行目**: instanceMatrixの作成（count * 16）
4. **93行目**: countの設定
5. **111-115行目**: 全インスタンスを単位行列で初期化

#### Step 3: インスタンス操作を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | InstancedMesh.js | `src/objects/InstancedMesh.js` | getMatrixAt/setMatrixAt（223-341行目） |
| 3-2 | InstancedMesh.js | `src/objects/InstancedMesh.js` | getColorAt/setColorAt（216-328行目） |
| 3-3 | InstancedMesh.js | `src/objects/InstancedMesh.js` | getMorphAt/setMorphAt（241-381行目） |

**主要処理フロー**:
- **229-232行目**: getMatrixAt - 配列から行列を読み取り
- **337-341行目**: setMatrixAt - 行列を配列に書き込み
- **318-327行目**: setColorAt - instanceColor未作成時に作成

#### Step 4: レイキャスト処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | InstancedMesh.js | `src/objects/InstancedMesh.js` | raycast()（259-309行目） |

**主要処理フロー**:
- **271行目**: 境界球の計算（未計算の場合）
- **273-276行目**: 境界球との交差判定
- **280-307行目**: 各インスタンスについて個別にraycast実行
- **299行目**: 交差結果にinstanceIdを追加

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

```
InstancedMesh
    │
    ├─ extends Mesh
    │      └─ extends Object3D
    │
    ├─ instanceMatrix (InstancedBufferAttribute)
    │      └─ Float32Array (count * 16)
    │
    ├─ instanceColor (InstancedBufferAttribute, optional)
    │      └─ Float32Array (count * 3)
    │
    └─ morphTexture (DataTexture, optional)
           └─ Float32Array (len * count)

InstancedMesh.raycast()
    │
    ├─ computeBoundingSphere()
    ├─ ray.intersectsSphere()
    └─ for each instance
           ├─ getMatrixAt()
           ├─ _mesh.raycast()
           └─ intersect.instanceId = instanceId
```

### データフロー図

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

geometry (引数) ──────────────▶ Meshコンストラクタ ─────────────▶ this.geometry
material (引数) ──────────────▶ Meshコンストラクタ ─────────────▶ this.material
count (引数) ─────────────────▶ インスタンス初期化 ─────────────▶ this.instanceMatrix

setMatrixAt(index, matrix)
matrix ───────────────────────▶ toArray() ──────────────────────▶ instanceMatrix.array[index*16]

setColorAt(index, color)
color ────────────────────────▶ toArray() ──────────────────────▶ instanceColor.array[index*3]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| InstancedMesh.js | `src/objects/InstancedMesh.js` | ソース | インスタンスメッシュクラス |
| Mesh.js | `src/objects/Mesh.js` | ソース | 基底クラス（メッシュ） |
| InstancedBufferAttribute.js | `src/core/InstancedBufferAttribute.js` | ソース | インスタンスバッファ属性 |
| DataTexture.js | `src/textures/DataTexture.js` | ソース | モーフ用データテクスチャ |
| Matrix4.js | `src/math/Matrix4.js` | ソース | 変換行列 |
| Color.js | `src/math/Color.js` | ソース | 色管理 |
| Box3.js | `src/math/Box3.js` | ソース | 境界ボックス |
| Sphere.js | `src/math/Sphere.js` | ソース | 境界球 |
