# 機能設計書 59-GridMap

## 概要

本ドキュメントは、Godot Engineにおける3Dグリッドマップ（GridMap）の設計を記載するものである。

### 本機能の処理概要

**業務上の目的・背景**：GridMapは、3Dゲームにおいてタイルベースの環境を効率的に構築するためのノードである。MeshLibraryリソースに定義されたメッシュアイテムを3Dグリッド上に配置し、物理コリジョンとナビゲーションメッシュを自動生成する。2DのTileMapに相当する3D版として機能する。

**機能の利用シーン**：
- 3Dダンジョンや迷路の構築
- ブロックベースのゲーム（マインクラフト風）
- モジュラー建築システム
- プロシージャル生成された3D環境

**主要な処理内容**：
1. グリッドセルへのメッシュアイテム配置・削除・取得
2. オクタント単位でのレンダリング最適化（MultiMesh使用）
3. 物理コリジョンの自動生成（StaticBody3D）
4. ナビゲーションメッシュの自動ベイク
5. 24種類の直交回転のサポート
6. ベイクメッシュの生成（ライトマップUV対応）
7. 座標変換（マップ座標⇔ローカル座標）

**関連システム・外部連携**：
- MeshLibrary（メッシュアイテム定義）
- PhysicsServer3D（コリジョン処理）
- NavigationServer3D（経路探索）
- RenderingServer（描画）

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | GridMapエディタ | エディタ | セルの配置・編集 |
| - | MeshLibraryエディタ | エディタ | メッシュライブラリの定義 |

## 機能種別

3Dゲームオブジェクト / シーンノード

## 入力仕様

### プロパティ

| プロパティ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| mesh_library | MeshLibrary | Yes | 使用するメッシュライブラリ | - |
| cell_size | Vector3 | No | セルサイズ（メートル） | 0.001以上 |
| cell_octant_size | Int | No | オクタントサイズ | 0以外 |
| cell_center_x | Bool | No | X軸中央配置 | - |
| cell_center_y | Bool | No | Y軸中央配置 | - |
| cell_center_z | Bool | No | Z軸中央配置 | - |
| cell_scale | Float | No | セルスケール | - |
| collision_layer | Int | No | コリジョンレイヤー | 1-32 |
| collision_mask | Int | No | コリジョンマスク | 1-32 |
| collision_priority | Float | No | コリジョン優先度 | - |
| physics_material | PhysicsMaterial | No | 物理マテリアル | - |
| bake_navigation | Bool | No | ナビゲーションベイク有効化 | - |

### メソッド入力

| メソッド名 | パラメータ | 説明 |
|-----------|-----------|------|
| set_cell_item | position: Vector3i, item: int, orientation: int | セルにアイテムを配置 |
| get_cell_item | position: Vector3i | セルのアイテムIDを取得 |
| get_cell_item_orientation | position: Vector3i | セルの回転インデックスを取得 |
| get_cell_item_basis | position: Vector3i | セルの回転行列を取得 |
| local_to_map | local_position: Vector3 | ローカル座標をマップ座標に変換 |
| map_to_local | map_position: Vector3i | マップ座標をローカル座標に変換 |
| get_used_cells | - | 使用中セル座標リストを取得 |
| get_used_cells_by_item | item: int | 指定アイテムのセル座標リストを取得 |
| clear | - | 全セルをクリア |
| make_baked_meshes | gen_lightmap_uv: bool, lightmap_uv_texel_size: float | ベイクメッシュを生成 |

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 描画済みメッシュ | MultiMesh | レンダリングされたグリッドアイテム |
| コリジョン形状 | StaticBody3D | 物理衝突形状 |
| ナビゲーション領域 | NavigationRegion3D | 経路探索用領域 |
| ベイクメッシュ | ArrayMesh | 結合されたメッシュ |

## 処理フロー

### 処理シーケンス

```
1. セルデータの更新検出
   └─ dirty flagによる変更追跡
2. オクタントの作成・更新
   └─ set_cell_item呼び出し時にオクタント生成
3. オクタント更新処理
   └─ _octant_update関数で描画・物理・ナビゲーション更新
4. MultiMeshの生成
   └─ 同一アイテムをバッチ描画
5. 物理ボディの更新
   └─ StaticBody3Dにシェイプを追加
6. ナビゲーションリージョンの更新
   └─ NavigationServer3Dにメッシュを登録
```

### フローチャート

```mermaid
flowchart TD
    A[set_cell_item呼び出し] --> B{アイテムID < 0?}
    B -->|Yes| C[セル削除]
    B -->|No| D{オクタント存在?}
    D -->|No| E[オクタント作成]
    D -->|Yes| F[オクタント更新]
    E --> F
    F --> G[dirty flag設定]
    G --> H[_queue_octants_dirty]
    H --> I[_update_octants_callback]
    I --> J[_octant_update]
    J --> K[MultiMesh生成]
    J --> L[物理シェイプ追加]
    J --> M[ナビゲーション登録]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-59-01 | セル座標制限 | 各軸の座標は±2^20の範囲内 | 常時 |
| BR-59-02 | 直交回転 | 24種類の直交回転のみサポート | 常時 |
| BR-59-03 | オクタント最適化 | 同一アイテムはMultiMeshでバッチ描画 | 常時 |
| BR-59-04 | ベイクメッシュ排他 | ベイクメッシュ生成後はオクタント描画無効 | make_baked_meshes後 |

### 計算ロジック

オクタント座標計算:
```
octant_x = x > 0 ? x / octant_size : (x - (octant_size - 1)) / octant_size
octant_y = y > 0 ? y / octant_size : (y - (octant_size - 1)) / octant_size
octant_z = z > 0 ? z / octant_size : (z - (octant_size - 1)) / octant_size
```

オフセット計算:
```
offset = Vector3(
    cell_size.x * 0.5 * center_x,
    cell_size.y * 0.5 * center_y,
    cell_size.z * 0.5 * center_z
)
```

座標変換:
```
local_to_map: map_position = (local_position / cell_size).floor()
map_to_local: local_position = map_position * cell_size + offset
```

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

本機能はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ERR_INVALID_DATA | データ不正 | MeshLibraryが未設定 | MeshLibraryを設定 |
| ERR_INVALID_PARAMETER | パラメータ不正 | セル座標が範囲外 | ±2^20以内の座標を指定 |
| ERR_FAIL_INDEX | インデックス不正 | 無効なアイテムID | 有効なアイテムIDを指定 |
| ERR_FAIL_COND | 条件不正 | セルサイズが0.001未満 | 0.001以上を指定 |

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

即時反映。トランザクション管理なし。

## パフォーマンス要件

- オクタント単位でのMultiMesh描画により大量セルに対応
- dirty flagによる遅延更新で不要な再計算を回避
- ベイクメッシュによるライトマップ対応と描画最適化

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

特になし。

## 備考

- INVALID_CELL_ITEM = -1
- 直交回転は0-23のインデックスで指定（_ortho_bases配列）
- オクタントサイズのデフォルトは8

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | grid_map.h | `modules/gridmap/grid_map.h` | GridMapクラス定義、Cell/Octant構造体 |

**読解のコツ**: IndexKey構造体がセル座標をユニークキーとして管理し、OctantKey構造体がオクタント座標を管理する。cell_mapがセルデータ、octant_mapがオクタントデータを保持する。

#### Step 2: セル操作を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | grid_map.cpp | `modules/gridmap/grid_map.cpp` | set_cell_item、get_cell_item関数 |

**主要処理フロー**:
- **350-427行目**: set_cell_item関数でセル配置・削除
- **429-443行目**: get_cell_item関数でセル取得
- **445-459行目**: get_cell_item_orientation関数で回転取得
- **461-486行目**: _ortho_bases配列（24種類の直交回転行列）

#### Step 3: オクタント処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | grid_map.cpp | `modules/gridmap/grid_map.cpp` | _octant_update関数 |

**主要処理フロー**:
- **530-554行目**: オクタント座標計算
- **600-834行目**: _octant_update関数でMultiMesh生成、物理・ナビゲーション更新
- **768-807行目**: MultiMeshの生成とインスタンス設定

#### Step 4: 座標変換を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | grid_map.cpp | `modules/gridmap/grid_map.cpp` | local_to_map、map_to_local関数 |

**主要処理フロー**:
- **556-559行目**: local_to_map関数
- **561-568行目**: map_to_local関数
- **1342-1347行目**: _get_offset関数

#### Step 5: ベイクメッシュを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | grid_map.cpp | `modules/gridmap/grid_map.cpp` | make_baked_meshes関数 |

**主要処理フロー**:
- **1359-1439行目**: make_baked_meshes関数でメッシュ結合
- **1397-1412行目**: SurfaceToolを使用したメッシュ追加

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

```
GridMap
    │
    ├─ set_cell_item
    │      ├─ get_octant_key_from_cell_coords
    │      ├─ Octant生成（存在しない場合）
    │      │      └─ PhysicsServer3D::body_create
    │      ├─ cell_map更新
    │      └─ _queue_octants_dirty
    │
    ├─ _update_octants_callback
    │      └─ _octant_update
    │             ├─ PhysicsServer3D::body_clear_shapes
    │             ├─ MultiMesh生成
    │             │      └─ RS::multimesh_create
    │             ├─ PhysicsServer3D::body_add_shape
    │             └─ NavigationServer3D::region_create
    │
    ├─ local_to_map
    │      └─ (local_position / cell_size).floor()
    │
    ├─ map_to_local
    │      └─ map_position * cell_size + _get_offset()
    │
    └─ make_baked_meshes
           ├─ SurfaceTool::append_from
           └─ ArrayMesh::add_surface_from_arrays
```

### データフロー図

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

set_cell_item ─────────────▶ cell_map更新 ─────────────────▶ IndexKey→Cell
                             octant_map更新                   OctantKey→Octant

dirty flags ───────────────▶ _update_octants_callback ─────▶ MultiMesh描画
                                                              StaticBody3D
                                                              NavigationRegion3D

MeshLibrary ───────────────▶ メッシュ・シェイプ取得 ────────▶ 描画・物理・ナビ

local_position ────────────▶ local_to_map ─────────────────▶ map_position

map_position ──────────────▶ map_to_local ─────────────────▶ local_position
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| grid_map.cpp | `modules/gridmap/grid_map.cpp` | ソース | GridMap本体 |
| grid_map.h | `modules/gridmap/grid_map.h` | ヘッダ | クラス定義 |
| mesh_library.cpp | `scene/resources/3d/mesh_library.cpp` | ソース | メッシュライブラリ |
| mesh_library.h | `scene/resources/3d/mesh_library.h` | ヘッダ | MeshLibraryクラス定義 |
| grid_map_editor_plugin.cpp | `editor/plugins/gridmap_editor_plugin.cpp` | ソース | エディタプラグイン |
