# 機能設計書 8-Layers

## 概要

本ドキュメントは、Three.jsライブラリにおける表示レイヤー管理機能を提供するLayersクラスの機能設計について記述する。Layersは、3Dオブジェクトを最大32個のレイヤーに割り当て、カメラやRaycasterによる可視性制御とレイキャスト対象の制御を可能にする。

### 本機能の処理概要

Layersクラスは、32ビットのビットマスクを使用してレイヤーメンバーシップを管理する。Object3DおよびCameraが持つlayersプロパティにより、オブジェクトとカメラ間のレイヤー一致を判定し、レンダリングやレイキャスティングの対象を制御する。

**業務上の目的・背景**：大規模な3Dシーンでは、すべてのオブジェクトを常にレンダリングする必要がない場合がある。例えば、デバッグ用のヘルパーオブジェクト、特定のカメラでのみ表示するUI要素、レイキャスト対象から除外したいオブジェクトなどがある。Layersはこれらのシナリオに対応するための軽量かつ効率的なフィルタリング機構を提供する。

**機能の利用シーン**：
- デバッグ用ヘルパーの表示/非表示切り替え
- VRの左目用/右目用オブジェクトの分離
- レイキャスト対象の限定（UIオブジェクトのみ判定など）
- 複数カメラでの選択的レンダリング
- 影を落とさないオブジェクトの管理

**主要な処理内容**：
1. **レイヤー設定**: set()による単一レイヤーへの切り替え
2. **レイヤー有効化**: enable()による特定レイヤーの追加
3. **全レイヤー有効化**: enableAll()による全32レイヤーの有効化
4. **レイヤー無効化**: disable()による特定レイヤーの削除
5. **全レイヤー無効化**: disableAll()による全レイヤーの無効化
6. **レイヤートグル**: toggle()によるレイヤーの切り替え
7. **レイヤーテスト**: test()による他Layersとの共通レイヤー判定
8. **レイヤー確認**: isEnabled()による特定レイヤーの有効状態確認

**関連システム・外部連携**：
- Object3DのlayersプロパティによるオブジェクトレベルのレイヤリNG
- CameraのlayersプロパティによるビューレベルのフィルタリNG
- Raycasterのlayersプロパティによるピッキング対象のフィルタリング

**権限による制御**：特になし（ライブラリレベルの機能のため、アプリケーション側での権限管理は行わない）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 4 | Sidebar - Object | 補助機能 | オブジェクトのレイヤー設定 |

## 機能種別

オブジェクト管理 / フィルタリング

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| layer | number | Yes | レイヤー番号（0-31） | 各メソッドで使用 |
| layers | Layers | Yes | 比較対象のLayersオブジェクト | test()で使用 |

### 入力データソース

- アプリケーションコードからの直接呼び出し
- Object3D、Camera、Raycasterのlayersプロパティ経由

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| mask | number | 32ビットのレイヤーマスク |
| test戻り値 | boolean | 共通レイヤーがあるか |
| isEnabled戻り値 | boolean | 指定レイヤーが有効か |

### 出力先

- test()、isEnabled()の戻り値
- WebGLRenderer/WebGPURendererによるレンダリング判定

## 処理フロー

### 処理シーケンス

```
1. Layersインスタンス生成
   └─ コンストラクタ()
       └─ mask = 1 (レイヤー0のみ有効)

2. レイヤー操作
   └─ set(layer)
       └─ mask = (1 << layer) >>> 0
   └─ enable(layer)
       └─ mask |= 1 << layer
   └─ enableAll()
       └─ mask = 0xffffffff
   └─ disable(layer)
       └─ mask &= ~(1 << layer)
   └─ disableAll()
       └─ mask = 0
   └─ toggle(layer)
       └─ mask ^= 1 << layer

3. レイヤー判定
   └─ test(layers)
       └─ return (this.mask & layers.mask) !== 0
   └─ isEnabled(layer)
       └─ return (this.mask & (1 << layer)) !== 0
```

### フローチャート

```mermaid
flowchart TD
    A[Layers生成] --> B[mask = 1]
    B --> C{操作種別}
    C -->|set| D[mask = 1 << layer]
    C -->|enable| E[mask OR= 1 << layer]
    C -->|enableAll| F[mask = 0xffffffff]
    C -->|disable| G[mask AND= NOT 1 << layer]
    C -->|disableAll| H[mask = 0]
    C -->|toggle| I[mask XOR= 1 << layer]
    C -->|test| J{mask AND other.mask != 0?}
    J -->|Yes| K[return true]
    J -->|No| L[return false]
    C -->|isEnabled| M{mask AND 1 << layer != 0?}
    M -->|Yes| N[return true]
    M -->|No| O[return false]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | デフォルトレイヤー | 初期状態ではレイヤー0のみ有効（mask=1） | コンストラクタ |
| BR-02 | 32レイヤー制限 | レイヤー番号は0-31の範囲 | 全メソッド |
| BR-03 | ビット演算 | すべての操作は32ビット整数のビット演算で実行 | 全メソッド |
| BR-04 | 符号なし変換 | set()では >>> 0 で符号なし整数に変換 | set() |
| BR-05 | 相互可視性 | test()は両者が少なくとも1つの共通レイヤーを持つかを判定 | test() |

### 計算ロジック

**レイヤー設定（排他的）:**
```javascript
set(layer) {
    this.mask = (1 << layer | 0) >>> 0;
}
```

**レイヤー有効化（追加）:**
```javascript
enable(layer) {
    this.mask |= 1 << layer | 0;
}
```

**レイヤー無効化（削除）:**
```javascript
disable(layer) {
    this.mask &= ~(1 << layer | 0);
}
```

**レイヤートグル:**
```javascript
toggle(layer) {
    this.mask ^= 1 << layer | 0;
}
```

**レイヤーテスト:**
```javascript
test(layers) {
    return (this.mask & layers.mask) !== 0;
}
```

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

### 操作別データベース影響一覧

該当なし（Layersはデータベースを使用しない）

## エラー処理

### エラーケース一覧

該当なし（Layersは明示的なエラー処理を行わない）

### リトライ仕様

該当なし

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

該当なし（メモリ上のオブジェクト操作のみ）

## パフォーマンス要件

- すべての操作は単純なビット演算であり、O(1)の計算量
- 大量のオブジェクトでtest()を呼んでもパフォーマンスへの影響は最小限
- レンダリングループ内で頻繁に使用されることを想定

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

該当なし（クライアントサイドのグラフィックスライブラリ）

## 備考

- JavaScriptの32ビット整数制限により、最大32レイヤー
- Object3DのlayersはCameraのlayersから継承されない（独立して管理）
- デフォルトですべてのObject3DとCameraはレイヤー0に属するため、通常動作では可視性に影響しない

---

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

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

### 推奨読解順序

#### Step 1: クラス構造を理解する

Layersの基本構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Layers.js | `src/core/Layers.js` | クラス全体の構造（非常にシンプル） |

**読解のコツ**: Layersはmaskプロパティのみを持つ非常にシンプルなクラス。ビット演算の知識があれば容易に理解可能。

#### Step 2: コンストラクタを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Layers.js | `src/core/Layers.js` | コンストラクタでのmask初期化 |

**主要処理フロー**:
- **19-29行目**: コンストラクタ
- **27行目**: maskの初期化（1 | 0 = 1、レイヤー0のみ有効）

#### Step 3: レイヤー操作を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Layers.js | `src/core/Layers.js` | set(), enable(), enableAll(), disable(), disableAll(), toggle() |

**主要処理フロー**:
- **36-40行目**: set() - 排他的レイヤー設定
- **47-51行目**: enable() - レイヤー追加
- **56-60行目**: enableAll() - 全レイヤー有効化
- **67-71行目**: toggle() - レイヤートグル
- **78-82行目**: disable() - レイヤー削除
- **87-91行目**: disableAll() - 全レイヤー無効化

#### Step 4: レイヤー判定を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Layers.js | `src/core/Layers.js` | test(), isEnabled() |

**主要処理フロー**:
- **100-104行目**: test() - 共通レイヤー判定
- **112-116行目**: isEnabled() - 特定レイヤーの有効状態確認

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

```
Layers
    │
    ├─ constructor()
    │      └─ mask = 1 | 0
    │
    ├─ set(layer)
    │      └─ mask = (1 << layer | 0) >>> 0
    │
    ├─ enable(layer)
    │      └─ mask |= 1 << layer | 0
    │
    ├─ enableAll()
    │      └─ mask = 0xffffffff | 0
    │
    ├─ toggle(layer)
    │      └─ mask ^= 1 << layer | 0
    │
    ├─ disable(layer)
    │      └─ mask &= ~(1 << layer | 0)
    │
    ├─ disableAll()
    │      └─ mask = 0
    │
    ├─ test(layers)
    │      └─ return (mask & layers.mask) !== 0
    │
    └─ isEnabled(layer)
           └─ return (mask & (1 << layer | 0)) !== 0
```

### データフロー図

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

                    ┌─────────────────────┐
                    │ constructor()       │
                    │ mask = 1 (layer 0)  │
                    └─────────────────────┘
                              │
                              ↓
                    ┌─────────────────────┐
                    │      mask           │
                    │ (32-bit bitmask)    │
                    │                     │
                    │ bit 0  = layer 0    │
                    │ bit 1  = layer 1    │
                    │ ...                 │
                    │ bit 31 = layer 31   │
                    └─────────────────────┘
                              │
            ┌─────────────────┼─────────────────┐
            ↓                 ↓                 ↓
      ┌──────────┐     ┌──────────┐     ┌──────────┐
      │ set()    │     │ enable() │     │ toggle() │
      │ ────────>│     │ ────────>│     │ ────────>│
      │ 排他設定  │     │ 追加      │     │ 切替     │
      └──────────┘     └──────────┘     └──────────┘
                              │
                              ↓
                    ┌─────────────────────┐
                    │ test(other.mask)    │──→ boolean
                    │ isEnabled(layer)    │──→ boolean
                    └─────────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Layers.js | `src/core/Layers.js` | ソース | Layersクラス本体 |
| Object3D.js | `src/core/Object3D.js` | ソース | layers使用元（オブジェクトレベル） |
| Camera.js | `src/cameras/Camera.js` | ソース | layers使用元（カメラレベル） |
| Raycaster.js | `src/core/Raycaster.js` | ソース | layers使用元（レイキャスト） |
