# 画面設計書 37-Bones Browser

## 概要

本ドキュメントは、three.jsのドキュメントに含まれる「Bones Browser」画面（docs/scenes/bones-browser.html）の設計書である。three.jsのスケルタルアニメーション（ボーンアニメーション）システムを3Dプレビューで確認でき、各ボーンの位置・回転・スケールをリアルタイムに調整してスキニングの仕組みを視覚的に理解できるインタラクティブツールを提供する。

### 本画面の処理概要

このページは、three.jsのスケルタルアニメーションシステム（Bone, Skeleton, SkinnedMesh）の動作を3Dで表示し、lil-guiを使用して各ボーンのトランスフォーム（位置・回転・スケール）をリアルタイムに調整できるインタラクティブブラウザである。開発者はボーン階層構造とスキンウェイトがメッシュ変形にどう影響するかを視覚的に学習できる。

**業務上の目的・背景**：3Dキャラクターアニメーションにおいて、スケルタルアニメーションは最も重要な技術の一つである。ボーンの親子関係、スキンウェイト、バインドポーズの概念を理解するには、実際にボーンを操作して結果を確認するのが効果的である。本ツールは、これらの概念を直感的に理解させ、アニメーション実装の学習を支援することを目的としている。

**画面へのアクセス方法**：ドキュメントトップページ（docs/index.html）のBone、Skeleton、SkinnedMesh等のドキュメントページ内リンクから、または直接URLでアクセス。

**主要な操作・処理内容**：
1. ボーン階層構造の自動生成（4セグメント + ルート = 5ボーン）
2. 各ボーンの位置・回転・スケールのGUI調整
3. アニメーションの自動再生（Animate Bonesトグル）
4. pose()メソッドによる初期ポーズへのリセット
5. SkeletonHelperによるボーン構造の可視化
6. OrbitControlsによるカメラ回転操作

**画面遷移**：ドキュメントページのiframe内で表示。「Open in New Window」リンクで新しいウィンドウで開くことも可能。

**権限による表示制御**：特になし。公開ドキュメントとして認証不要でアクセス可能。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 85 | SkinnedMesh | 主機能 | スキンメッシュのプレビュー |
| 86 | Skeleton | 主機能 | スケルトン構造の表示 |
| 87 | Bone | 補助機能 | 個別ボーンの操作 |
| 13 | WebGLRenderer | 補助機能 | 3Dレンダリング |
| 19 | PerspectiveCamera | 補助機能 | ビューカメラ |

## 画面種別

インタラクティブプレビュー画面（3Dボーンエディタ）

## URL/ルーティング

`docs/scenes/bones-browser.html`

## 入出力項目

| 項目名 | 入出力 | データ型 | 説明 |
|--------|--------|----------|------|
| Animate Bones トグル | 入力 | Boolean | 自動アニメーションの有効/無効 |
| pose() ボタン | 入力 | Click | 初期ポーズへリセット |
| ボーン位置 (x, y, z) | 入力 | Number | 各ボーンの位置調整 |
| ボーン回転 (x, y, z) | 入力 | Number | 各ボーンの回転調整（-π/2 〜 π/2） |
| ボーン スケール (x, y, z) | 入力 | Number | 各ボーンのスケール調整（0 〜 2） |
| 3Dプレビュー | 出力 | Canvas | スキンメッシュの3D表示 |

## 表示項目

| 表示項目 | 説明 |
|----------|------|
| スキンメッシュ | CylinderGeometryベースのスキンメッシュ |
| SkeletonHelper | ボーン構造を線で可視化 |
| General Optionsパネル | Animate Bones、pose()ボタン |
| Bone 0〜4 パネル | 各ボーンのトランスフォーム調整 |
| 「Open in New Window」リンク | 新しいウィンドウで開くリンク |

### ボーン構造

```
Bone 0 (ルート)
  └─ Bone 1
       └─ Bone 2
            └─ Bone 3
                 └─ Bone 4
```

## イベント仕様

### 1-Animate Bonesトグル

**トリガー**: チェックボックス変更
**処理内容**:
1. state.animateBones フラグを更新
2. render()ループ内でフラグを参照
3. true時: 各ボーンのrotation.zをsin(time)で更新

### 2-pose()ボタン

**トリガー**: ボタンクリック
**処理内容**:
1. mesh.pose() を呼び出し
2. 全ボーンがバインドポーズ（初期位置）にリセット
3. GUIの値は更新されない（表示と実際の値に差異が生じる）

### 3-ボーンパラメータ変更

**トリガー**: lil-guiスライダーの値変更
**処理内容**:
1. bone.position.x/y/z、bone.rotation.x/y/z、bone.scale.x/y/z を直接更新
2. 親ボーンからの相対座標で計算
3. 自動的にSkinnedMeshのスキニング計算が実行

### 4-カメラ回転

**トリガー**: マウスドラッグ
**処理内容**:
1. OrbitControls がマウスイベントをキャプチャ
2. カメラ位置をターゲット周りに回転
3. ズームは enableZoom = false で無効化

## データベース更新仕様

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

## メッセージ仕様

特になし。

## 例外処理

| 例外状況 | 処理内容 |
|----------|----------|
| WebGL非対応ブラウザ | エラーメッセージ表示 |

## 備考

- CylinderGeometry を使用し、heightSegments を segmentCount * 3 で細かく分割
- スキンインデックスとスキンウェイトは頂点Y座標から自動計算
- 隣接する2つのボーンに対してリニア補間でウェイト分配
- SkeletonHelper.material.linewidth = 2 でボーン線を太く表示
- mesh.bind(skeleton) でスケルトンをメッシュにバインド

---

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

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

### 推奨読解順序

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

スキニングに必要なジオメトリ属性（skinIndex, skinWeight）を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | bones-browser.html | `docs/scenes/bones-browser.html` | createGeometry関数（110-147行目） |

**読解のコツ**:
- skinIndex: 各頂点が影響を受けるボーンのインデックス（最大4つ）
- skinWeight: 各ボーンからの影響度（合計1.0）
- 頂点Y座標からボーンインデックスと重みを計算

#### Step 2: ボーン階層を理解する

ボーンの親子関係の構築を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | bones-browser.html | `docs/scenes/bones-browser.html` | createBones関数（149-169行目） |

**主要処理フロー**:
1. **151行目**: bonesリスト初期化
2. **153-155行目**: ルートボーン作成、位置を-halfHeightに設定
3. **157-164行目**: 子ボーンを順次作成、prevBone.add(bone)で親子関係構築
4. **162行目**: bone.position.y = segmentHeightで相対位置設定

#### Step 3: メッシュとスケルトンのバインドを理解する

SkinnedMeshの作成とSkeletonのバインド処理を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | bones-browser.html | `docs/scenes/bones-browser.html` | createMesh関数（171-193行目） |

**主要処理フロー**:
- **180行目**: new SkinnedMesh(geometry, material)
- **181行目**: new Skeleton(bones)
- **183行目**: mesh.add(bones[0]) - ルートボーンをメッシュに追加
- **185行目**: mesh.bind(skeleton) - スケルトンをバインド
- **187-189行目**: SkeletonHelper作成・追加

#### Step 4: GUIセットアップを理解する

各ボーンのコントローラー設定を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | bones-browser.html | `docs/scenes/bones-browser.html` | setupDatGui関数（195-239行目） |

**主要処理フロー**:
- **197-203行目**: General Optionsフォルダ（Animate Bones、pose）
- **207-237行目**: 各ボーンのフォルダ作成、position/rotation/scaleのコントローラー追加

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

```
bones-browser.html
    │
    ├─ initScene()
    │      ├─ new GUI()
    │      ├─ new Scene()
    │      ├─ new PerspectiveCamera()
    │      ├─ new WebGLRenderer()
    │      ├─ new OrbitControls() (enableZoom = false)
    │      ├─ DirectionalLight x 3
    │      ├─ initBones()
    │      │      ├─ createGeometry(sizing) → geometry
    │      │      │      └─ skinIndex, skinWeight属性設定
    │      │      ├─ createBones(sizing) → bones[]
    │      │      │      └─ Bone親子階層構築
    │      │      └─ createMesh(geometry, bones) → mesh
    │      │             ├─ new SkinnedMesh()
    │      │             ├─ new Skeleton(bones)
    │      │             ├─ mesh.bind(skeleton)
    │      │             └─ new SkeletonHelper()
    │      └─ setupDatGui()
    │             ├─ General Options（animateBones, pose）
    │             └─ Bone 0〜4（position, rotation, scale）
    │
    └─ render() (requestAnimationFrame)
           ├─ if (state.animateBones)
           │      └─ bones[i].rotation.z = sin(time) * 2 / bones.length
           └─ renderer.render(scene, camera)
```

### データフロー図

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

sizing パラメータ ──▶ createGeometry() ───────────────▶ geometry
                             │                              │
                             ├─ CylinderGeometry            ├─ position属性
                             └─ skinIndex/skinWeight計算    ├─ skinIndex属性
                                                            └─ skinWeight属性

sizing パラメータ ──▶ createBones() ─────────────────▶ bones[]
                             │
                             └─ 親子階層構築

geometry + bones ───▶ createMesh() ──────────────────▶ SkinnedMesh
                             │
                             ├─ new Skeleton(bones)
                             └─ mesh.bind(skeleton)

GUIスライダー ──────▶ bone.position/rotation/scale ──▶ スキニング計算
                             │
                             └─ メッシュ変形
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| bones-browser.html | `docs/scenes/bones-browser.html` | ソース | Bones Browserのメイン |
| three.module.js | `build/three.module.js` | ライブラリ | three.jsコア（Bone, Skeleton, SkinnedMesh） |
| lil-gui.module.min.js | `examples/jsm/libs/lil-gui.module.min.js` | ライブラリ | GUIパネル |
| OrbitControls.js | `examples/jsm/controls/OrbitControls.js` | ライブラリ | カメラ制御 |
| main.css | `files/main.css` | スタイル | 共通スタイル |
