# 機能設計書 114-AnimationObjectGroup

## 概要

本ドキュメントは、Three.jsにおける`AnimationObjectGroup`クラスの機能設計を記述する。AnimationObjectGroupは、共通のアニメーション状態を受け取るオブジェクトのグループを管理し、複数のオブジェクトに対して同一のアニメーションを同期して適用する機能を提供する。

### 本機能の処理概要

AnimationObjectGroupは、同一のアニメーションクリップを複数のオブジェクトに同時に適用したい場合に使用するコンテナクラスである。通常、AnimationMixerはルートオブジェクトに対して1つのアクションを実行するが、AnimationObjectGroupを使用することで、グループ内のすべてのオブジェクトが同じアニメーション状態を共有できる。

**業務上の目的・背景**：3Dシーンにおいて、同一の動作をする複数のオブジェクト（群衆、編隊飛行、機械部品の連動等）をアニメーションする際、各オブジェクトに個別のAnimationMixerを作成するのは非効率である。AnimationObjectGroupを使用することで、メモリ使用量を削減し、アニメーション管理を一元化できる。

**機能の利用シーン**：
- 群衆シミュレーション（同じ歩行アニメーションを複数キャラクターに適用）
- 編隊飛行（複数の航空機に同じ飛行動作を適用）
- 機械・ロボットの連動部品アニメーション
- パーティクルシステムと連動したオブジェクト群のアニメーション

**主要な処理内容**：
1. オブジェクトグループの管理（追加・削除・キャッシュ）
2. PropertyBindingの配列管理（グループ内全オブジェクト用）
3. 動的なオブジェクト追加・削除への対応
4. キャッシュ領域とアクティブ領域の分離管理

**関連システム・外部連携**：AnimationMixerのルートオブジェクトとして使用でき、PropertyBinding.Compositeと連携してグループ内の全オブジェクトにプロパティ変更を伝播する。

**権限による制御**：特になし（ライブラリ内部機能）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 該当なし | - | - | AnimationObjectGroupはライブラリ内部で使用されるクラスであり、直接的なUI関連はない |

## 機能種別

オブジェクト管理 / グループ同期 / キャッシュ管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| ...arguments | Object3D | No | 可変長引数でオブジェクトを受け取る | 0個以上のObject3D |

### 入力データソース

- 3Dシーン内のObject3Dインスタンス群

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| uuid | string | グループの一意識別子 |
| isAnimationObjectGroup | boolean | 型判定フラグ |
| stats | Object | グループ統計情報（total, inUse, bindingsPerObject） |

### 出力先

- AnimationMixerのルートオブジェクトとして使用
- PropertyBinding.Compositeへの参照提供

## 処理フロー

### 処理シーケンス

```
1. コンストラクタによるグループ生成
   └─ 引数のオブジェクトを_objectsに格納
   └─ UUIDの自動生成
   └─ インデックスマップの初期化

2. add() - オブジェクト追加
   └─ 未知のオブジェクト → ACTIVE領域に追加
   └─ キャッシュ済みオブジェクト → CACHED→ACTIVEに移動
   └─ バインディングの追加/移動

3. remove() - オブジェクト削除
   └─ ACTIVE→CACHED領域に移動
   └─ バインディングの移動

4. uncache() - キャッシュ解放
   └─ オブジェクトとバインディングを完全に削除
   └─ インデックスの再構築
```

### フローチャート

```mermaid
flowchart TD
    A[AnimationObjectGroup生成] --> B[オブジェクト配列初期化]
    B --> C{操作}
    C -->|add| D{オブジェクト状態}
    D -->|未知| E[ACTIVE領域に追加]
    D -->|CACHED| F[ACTIVE領域に移動]
    E --> G[バインディング作成]
    F --> H[バインディング移動]
    C -->|remove| I[ACTIVE→CACHED移動]
    I --> J[バインディング移動]
    C -->|uncache| K[完全削除]
    K --> L[インデックス再構築]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-114-01 | UUID重複検出 | 同一UUIDのオブジェクトを追加するとエラー | add()実行時 |
| BR-114-02 | キャッシュ分離 | nCachedObjects_より前がキャッシュ、以降がアクティブ | 常時 |
| BR-114-03 | バインディング同期 | オブジェクト追加時に既存パスのバインディングを作成 | add()実行時 |

### 計算ロジック

**アクティブオブジェクト数**:
```javascript
inUse = _objects.length - nCachedObjects_
```

**バインディング数**:
```javascript
bindingsPerObject = _bindings.length
```

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

該当なし（メモリ内データ構造）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | エラーログ | 同一UUIDの異なるオブジェクトを追加 | キャッシュをクリアするかインフラを再構築 |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- O(1)のインデックスルックアップ（_indicesByUUID使用）
- キャッシュ領域によるオブジェクト再追加の高速化

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

特になし

## 備考

- 同一プロパティはターゲットグループ経由か直接のどちらかでのみ制御可能（両方は不可）
- アニメーション対象のプロパティは全オブジェクトで互換性が必要

---

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

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

### 推奨読解順序

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

AnimationObjectGroupの内部構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | AnimationObjectGroup.js | `src/animation/AnimationObjectGroup.js` | コンストラクタ（25-95行目） |

**読解のコツ**: AnimationObjectGroupの主要な内部構造
- `_objects`: オブジェクト配列（キャッシュ + アクティブ）
- `nCachedObjects_`: キャッシュ領域の閾値
- `_indicesByUUID`: UUID→インデックスのマップ
- `_paths`, `_parsedPaths`: パス情報
- `_bindings`: PropertyBinding配列の配列
- `_bindingsIndicesByPath`: パス→バインディングインデックスのマップ

#### Step 2: オブジェクト管理メソッドを理解する

add/remove/uncacheの動作を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AnimationObjectGroup.js | `src/animation/AnimationObjectGroup.js` | add()（102-188行目） |
| 2-2 | AnimationObjectGroup.js | `src/animation/AnimationObjectGroup.js` | remove()（195-242行目） |
| 2-3 | AnimationObjectGroup.js | `src/animation/AnimationObjectGroup.js` | uncache()（249-336行目） |

**主要処理フロー**:
- **102-188行目**: add() - 新規オブジェクトをACTIVE領域に追加、またはCACHED→ACTIVEに移動
- **195-242行目**: remove() - ACTIVE→CACHED領域に移動
- **249-336行目**: uncache() - オブジェクトとバインディングを完全に削除

#### Step 3: 内部インターフェースを理解する

PropertyBinding.Compositeとの連携を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | AnimationObjectGroup.js | `src/animation/AnimationObjectGroup.js` | subscribe_()（340-375行目） |
| 3-2 | AnimationObjectGroup.js | `src/animation/AnimationObjectGroup.js` | unsubscribe_()（377-407行目） |

**主要処理フロー**:
- **340-375行目**: subscribe_ - パスに対するバインディング配列を取得/作成
- **377-407行目**: unsubscribe_ - パスのバインディング購読を解除

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

```
AnimationObjectGroup
    │
    ├─ constructor(...objects)
    │      └─ UUIDマップ初期化
    │
    ├─ add(...objects)
    │      ├─ 新規オブジェクト → ACTIVE領域追加
    │      │      └─ new PropertyBinding() [各パス]
    │      └─ CACHEDオブジェクト → ACTIVE領域移動
    │             └─ バインディング配列の入れ替え
    │
    ├─ remove(...objects)
    │      └─ ACTIVE→CACHED移動
    │             └─ バインディング配列の入れ替え
    │
    ├─ uncache(...objects)
    │      ├─ CACHEDから完全削除
    │      └─ ACTIVEから完全削除
    │             └─ バインディング配列のpop
    │
    ├─ subscribe_(path, parsedPath)  [内部]
    │      ├─ 既存パス → 既存バインディング配列を返す
    │      └─ 新規パス → PropertyBinding作成
    │
    └─ unsubscribe_(path)  [内部]
           └─ バインディング配列の削除
```

### データフロー図

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

Object3D群 ─────────────▶ AnimationObjectGroup生成 ────▶ グループインスタンス
                                │
                                ▼
AnimationMixer ─────────▶ mixer.clipAction(clip, group)
                                │
                                ▼
                        PropertyBinding.Composite生成
                                │
                                ▼
                        group.subscribe_(path)
                                │
                                ▼
                        バインディング配列取得
                                │
                                ▼
アニメーション更新 ────▶ binding.setValue() [各オブジェクト]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AnimationObjectGroup.js | `src/animation/AnimationObjectGroup.js` | ソース | メインクラス定義 |
| PropertyBinding.js | `src/animation/PropertyBinding.js` | ソース | プロパティバインディング |
| AnimationMixer.js | `src/animation/AnimationMixer.js` | ソース | グループをルートとして使用 |
| MathUtils.js | `src/math/MathUtils.js` | ソース | generateUUID |
