# 機能設計書 162-SkeletonHelper

## 概要

本ドキュメントは、Three.jsライブラリにおけるSkeletonHelper機能の設計仕様を記述する。SkeletonHelperは、スケルトン（骨格）構造を3Dシーン内で視覚的に表示するためのヘルパークラスである。

### 本機能の処理概要

SkeletonHelperは、SkinnedMeshやその他のボーン階層を持つオブジェクトのスケルトン構造を線分で可視化する。各ボーンとその親ボーンを結ぶ線分を描画し、ボーンの位置と階層関係を視覚的に確認できるようにする。

**業務上の目的・背景**：キャラクターアニメーションやスケルタルアニメーションの開発において、ボーン構造の確認は不可欠である。このヘルパーを使用することで、開発者はスケルトンの構造、ボーンの位置、アニメーション中のボーンの動きをリアルタイムで確認でき、アニメーションのデバッグとリギング作業を効率的に行える。

**機能の利用シーン**：
- キャラクターモデルのリギング確認
- スケルタルアニメーションのデバッグ
- ボーン階層の構造確認
- モーションキャプチャデータの検証
- 3Dエディタでのボーン操作時のプレビュー

**主要な処理内容**：
1. オブジェクト階層からボーンリストの再帰的な抽出
2. 各ボーンとその親を結ぶ線分ジオメトリの生成
3. 頂点カラーによるグラデーション表示（デフォルト: 青から緑）
4. updateMatrixWorld()での動的な位置更新
5. setColors()による色のカスタマイズ
6. dispose()によるGPUリソースの解放

**関連システム・外部連携**：SkinnedMesh、Skeleton、Bone、LineSegments、LineBasicMaterialと連携し、Three.jsのレンダリングパイプラインに統合される。

**権限による制御**：特になし。すべてのユーザーが利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 37 | Bones Browser | 主機能 | スケルトン構造の表示 |

## 機能種別

ビジュアライゼーション / デバッグ補助

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| object | Object3D | Yes | スケルトンを含むオブジェクト（通常はSkinnedMesh） | ボーン階層を含むこと |

### 入力データソース

コンストラクタ引数として渡されるObject3Dから、ボーン階層を再帰的に探索してボーンリストを構築。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| SkeletonHelper | LineSegments | スケルトンを可視化するヘルパーオブジェクト |
| bones | Array<Bone> | 検出されたボーンの配列 |
| root | Object3D | ルートオブジェクトへの参照 |

### 出力先

Three.jsのシーングラフに追加され、WebGLRenderer/WebGPURendererによってレンダリングされる。

## 処理フロー

### 処理シーケンス

```
1. コンストラクタ呼び出し
   └─ getBoneList()でボーンリストを再帰的に取得
2. ジオメトリ生成
   └─ 各ボーンとその親を結ぶ線分用の頂点を準備
3. LineSegments初期化
   └─ 親クラスを初期化し、ジオメトリとマテリアルを設定
4. プロパティ設定
   └─ root, bones, matrix, matrixAutoUpdateを設定
5. 色設定
   └─ setColors()でデフォルト色（青→緑）を設定
```

### フローチャート

```mermaid
flowchart TD
    A[コンストラクタ開始] --> B[getBoneList呼び出し]
    B --> C{オブジェクトがボーンか?}
    C -->|Yes| D[ボーンリストに追加]
    C -->|No| E[子オブジェクトを再帰探索]
    D --> E
    E --> F[ジオメトリ生成]
    F --> G{親がボーンか?}
    G -->|Yes| H[線分用頂点を追加]
    G -->|No| I[スキップ]
    H --> J[BufferAttribute設定]
    I --> J
    J --> K[LineBasicMaterial生成]
    K --> L[LineSegments初期化]
    L --> M[プロパティ設定]
    M --> N[setColors呼び出し]
    N --> O[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | ボーン検出 | isBone === true のオブジェクトをボーンとして認識 | getBoneList() |
| BR-002 | 線分描画条件 | 親もボーンである場合のみ線分を描画 | ジオメトリ生成時 |
| BR-003 | 行列同期 | ヘルパーの行列はルートオブジェクトのmatrixWorldと同期 | 常時 |
| BR-004 | デフォルト色 | color1: 青(0x0000ff)、color2: 緑(0x00ff00) | コンストラクタ |

### 計算ロジック

ボーン位置の計算: ルートの逆行列とボーンのワールド行列を乗算して、ローカル座標系でのボーン位置を算出。

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

該当なし（クライアントサイドのみで動作）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | TypeError | objectがnullまたはundefined | 有効なObject3Dを渡す |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- 軽量な線分表示のため、レンダリング負荷は最小限
- ボーン数が多い場合でも効率的に動作するよう設計
- updateMatrixWorld()は毎フレーム呼び出されるため、最適化済み

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

特になし（クライアントサイドのビジュアライゼーション機能）

## 備考

- depthTest, depthWriteがfalseのため、常に他のオブジェクトの前面に描画される
- transparentがtrueに設定されている
- dispose()を呼び出してGPUリソースを適切に解放すること

---

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

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

### 推奨読解順序

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

SkeletonHelperはLineSegmentsを継承し、ボーン階層を線分で表現する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SkeletonHelper.js | `src/helpers/SkeletonHelper.js` | クラス定義とプロパティ構造（root, bones） |

**読解のコツ**: LineSegmentsを継承しているため、線分描画の機能を持つ。bonesプロパティで可視化対象のボーンリストを保持している。

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

コンストラクタとgetBoneList関数が主要なエントリーポイント。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | SkeletonHelper.js | `src/helpers/SkeletonHelper.js` | constructor (31-97行目)、getBoneList (173-191行目) |

**主要処理フロー**:
1. **33行目**: getBoneList()でボーン階層を再帰的に取得
2. **35-56行目**: ボーン間の線分用ジオメトリを生成
3. **58行目**: LineBasicMaterial生成（vertexColors, depthTest: false等）
4. **60行目**: super()でLineSegmentsを初期化
5. **78行目**: this.rootにルートオブジェクトを保存
6. **85行目**: this.bonesにボーンリストを保存
7. **87-88行目**: 行列の同期設定
8. **92-95行目**: setColors()でデフォルト色を設定

#### Step 3: 更新処理を理解する

updateMatrixWorld()メソッドは各フレームでボーン位置を更新する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | SkeletonHelper.js | `src/helpers/SkeletonHelper.js` | updateMatrixWorld (99-132行目) |

**主要処理フロー**:
- **106行目**: ルートの逆ワールド行列を計算
- **108-126行目**: 各ボーンの位置を計算して頂点を更新
- **114-116行目**: ボーンのワールド位置を計算
- **118-120行目**: 親ボーンのワールド位置を計算
- **128行目**: position属性のneedsUpdateをtrueに設定
- **130行目**: 親クラスのupdateMatrixWorld()を呼び出し

#### Step 4: 色設定を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | SkeletonHelper.js | `src/helpers/SkeletonHelper.js` | setColors (141-157行目) |

**主要処理フロー**:
- **146-151行目**: 各線分の2頂点にcolor1とcolor2を交互に設定
- **153行目**: color属性のneedsUpdateをtrueに設定

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

```
SkeletonHelper (constructor)
    │
    ├─ getBoneList(object)
    │      └─ 再帰的にボーン探索
    │             └─ object.isBone で判定
    │
    ├─ BufferGeometry
    │      ├─ Float32BufferAttribute (position)
    │      └─ Float32BufferAttribute (color)
    │
    ├─ LineBasicMaterial
    │      └─ vertexColors: true, depthTest: false
    │
    ├─ LineSegments (super)
    │
    └─ setColors(color1, color2)
           └─ 頂点カラー設定

updateMatrixWorld(force)
    │
    ├─ Matrix4.invert (ルート逆行列)
    │
    ├─ Matrix4.multiplyMatrices (ボーン位置計算)
    │
    ├─ Vector3.setFromMatrixPosition
    │
    └─ BufferAttribute.setXYZ (頂点更新)
```

### データフロー図

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

Object3D ──────────────▶ getBoneList() ───────────────▶ ボーン配列
  (SkinnedMesh等)          └─ 再帰探索

ボーン配列 ─────────────▶ ジオメトリ生成 ─────────────▶ LineSegments
                           └─ 各ボーン-親間の線分

matrixWorld ────────────▶ updateMatrixWorld() ─────────▶ 更新された
                           └─ 位置計算                   頂点座標
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SkeletonHelper.js | `src/helpers/SkeletonHelper.js` | ソース | 本機能のメイン実装 |
| LineSegments.js | `src/objects/LineSegments.js` | ソース | 基底クラス（線分描画） |
| LineBasicMaterial.js | `src/materials/LineBasicMaterial.js` | ソース | 線分マテリアル |
| BufferGeometry.js | `src/core/BufferGeometry.js` | ソース | ジオメトリ管理 |
| BufferAttribute.js | `src/core/BufferAttribute.js` | ソース | 頂点属性管理 |
| Matrix4.js | `src/math/Matrix4.js` | ソース | 行列計算 |
| Vector3.js | `src/math/Vector3.js` | ソース | 位置計算 |
| Color.js | `src/math/Color.js` | ソース | 色管理 |
| Bone.js | `src/objects/Bone.js` | ソース | ボーンクラス |
| SkinnedMesh.js | `src/objects/SkinnedMesh.js` | ソース | スキンメッシュ（典型的な入力） |
| Skeleton.js | `src/objects/Skeleton.js` | ソース | スケルトン管理 |
