# 画面設計書 27-物理シミュレーション

## 概要

本ドキュメントは、three.js Examples における物理エンジン連携サンプル群（約13件）の画面設計書である。Ammo.js、Rapier、Jolt などの物理エンジンと three.js を統合したリアルタイム物理シミュレーションのデモンストレーションを提供する。

### 本画面の処理概要

物理シミュレーションサンプル画面は、three.js のメッシュオブジェクトと外部物理エンジンを連携させたリアルタイム物理演算のサンプル集である。剛体シミュレーション（Box, Sphere, Convex hull）、ソフトボディシミュレーション（布、ロープ）、車両シミュレーション、キャラクターコントローラーなどを実装している。

**業務上の目的・背景**：ゲーム、シミュレーション、インタラクティブデモなど、物理演算を必要とするアプリケーション開発者に対して、物理エンジン統合の実装例を提供する。three.js 単体では物理演算を行わないため、外部物理エンジンとの連携方法を学習できる。複数の物理エンジン（Ammo.js/Rapier/Jolt）の選択肢と特徴を比較できる。

**画面へのアクセス方法**：
1. examples/index.html にアクセス
2. 左側パネルの「physics」カテゴリを選択
3. 検索フィルタで「physics」「ammo」「rapier」「jolt」を入力して絞り込み
4. 目的のサンプルを選択

**主要な操作・処理内容**：
1. 物理エンジンの初期化と物理ワールドの作成
2. メッシュと物理ボディの同期（位置・回転）
3. 衝突検出とレスポンス
4. 重力、摩擦、反発係数の設定
5. インスタンシングによる大量オブジェクトの物理シミュレーション
6. ソフトボディ（布、ロープ）のシミュレーション

**画面遷移**：
- 遷移元：Examples一覧画面（examples/index.html）
- 遷移先：なし（各サンプルは独立して動作）
- GitHub ソースコードページへの外部リンクあり

**権限による表示制御**：なし（パブリックアクセス）

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | Object3D | 主機能 | 物理演算対象オブジェクトの管理 |
| 75 | Mesh | 補助機能 | 物理メッシュオブジェクト |
| 127 | Matrix4 | 補助機能 | 変換行列の計算 |
| 124 | Vector3 | 補助機能 | 位置の管理 |
| 128 | Quaternion | 補助機能 | 回転の管理 |

## 画面種別

サンプル / デモンストレーション / シミュレーション

## URL/ルーティング

- カテゴリ: `examples/index.html` (physics)
- 個別サンプル:
  - `examples/physics_rapier_basic.html` - Rapier 基本サンプル
  - `examples/physics_rapier_instancing.html` - Rapier インスタンシング
  - `examples/physics_ammo_instancing.html` - Ammo インスタンシング
  - `examples/physics_ammo_cloth.html` - Ammo 布シミュレーション
  - `examples/physics_ammo_rope.html` - Ammo ロープシミュレーション
  - `examples/physics_jolt_instancing.html` - Jolt インスタンシング
  - 他約7件

## 入出力項目

| 項目名 | 入出力 | データ型 | 説明 |
|--------|--------|----------|------|
| 物理パラメータ | 入力 | Number | 質量、反発係数、摩擦係数 |
| メッシュジオメトリ | 入力 | Geometry | 衝突形状の定義 |
| 物理ワールド設定 | 入力 | Object | 重力、タイムステップ |
| 物理状態 | 出力 | Transform | 位置・回転（毎フレーム更新） |
| 衝突イベント | 出力 | Event | 衝突検出結果 |

## 表示項目

| 項目名 | 表示形式 | 説明 |
|--------|----------|------|
| 3Dシーン | Canvas | 物理シミュレーション結果の可視化 |
| 物理デバッグ表示 | Wireframe | コライダー形状の可視化（RapierHelper等） |
| Stats | DOM overlay | FPS、物理演算時間 |
| 情報パネル | HTML div | サンプル説明、操作ガイド |

## イベント仕様

### 1-物理エンジン初期化

サンプル読み込み時の物理エンジン初期化：
1. 物理エンジンライブラリを動的インポート
2. 物理ワールド（World）を作成
3. 重力を設定（通常 -9.8 m/s^2）
4. タイムステップを設定

### 2-物理ボディ追加

メッシュに物理ボディを追加する処理：
1. メッシュの userData.physics にパラメータを設定
2. physics.addMesh(mesh, mass, restitution) を呼び出し
3. 物理エンジン側でコライダーとリジッドボディを作成
4. メッシュと物理ボディの対応付けを管理

### 3-物理シミュレーション更新

毎フレームの物理更新：
1. physics.world.step() で物理シミュレーションを進行
2. 各物理ボディの位置・回転を取得
3. 対応するメッシュの position/quaternion を更新
4. RapierHelper（デバッグ表示）を更新

### 4-オブジェクト落下・消滅

落下したオブジェクトの処理：
1. object.position.y < threshold をチェック
2. scene.remove(object) でシーンから削除
3. physics.removeMesh(object) で物理ボディを削除
4. メモリリークを防ぐためリソースを解放

### 5-定期的なオブジェクト生成

一定間隔でオブジェクトを生成：
1. setInterval(addBody, interval) で定期実行
2. ランダムなジオメトリとマテリアルでメッシュ作成
3. ランダムな位置に配置
4. physics.addMesh() で物理ボディを追加

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

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

本画面はフロントエンドのみで動作するサンプルであり、データベースへのアクセスは行わない。

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| - | - | - | データベース操作なし |

## メッセージ仕様

| 種別 | メッセージ | 発生条件 |
|------|-----------|----------|
| 情報 | コンソールログ | 物理エンジン初期化完了 |
| エラー | 物理エンジン読み込み失敗 | WASM ファイルが見つからない場合 |

## 例外処理

| 例外状況 | 処理内容 |
|----------|----------|
| 物理エンジン未対応ブラウザ | WASM 非対応時のエラー表示 |
| 物理演算負荷過大 | オブジェクト数を制限、警告表示 |
| メモリ不足 | 古いオブジェクトを削除 |

## 備考

- Ammo.js: Bullet Physics の JavaScript/WebAssembly ポート、最も成熟
- Rapier: Rust 製の高性能物理エンジン、WebAssembly
- Jolt: C++ 製の新しい物理エンジン、WebAssembly
- ソフトボディは Ammo.js でのみサポート
- インスタンシングと組み合わせることで大量オブジェクトのシミュレーションが可能

---

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

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

### 推奨読解順序

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

物理エンジン統合のアーキテクチャを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | RapierPhysics.js | `examples/jsm/physics/RapierPhysics.js` | Rapier 統合ヘルパー |
| 1-2 | AmmoPhysics.js | `examples/jsm/physics/AmmoPhysics.js` | Ammo 統合ヘルパー |
| 1-3 | JoltPhysics.js | `examples/jsm/physics/JoltPhysics.js` | Jolt 統合ヘルパー |

**読解のコツ**: 各物理ヘルパーは共通のインターフェース（addScene, addMesh, removeMesh）を持ち、内部で物理エンジン固有の処理を行う。

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

Rapier 基本サンプルの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | physics_rapier_basic.html | `examples/physics_rapier_basic.html` | Rapier 基本サンプル |

**主要処理フロー**:
1. **Line 33**: RapierPhysics をインポート
2. **Line 34**: RapierHelper をインポート（デバッグ表示用）
3. **Line 43-116**: init() 関数でシーン初期化
4. **Line 89-95**: 床メッシュを作成、userData.physics = { mass: 0 } で静的オブジェクト
5. **Line 118-132**: initPhysics() で物理エンジン初期化
6. **Line 121**: physics = await RapierPhysics()
7. **Line 123**: physics.addScene(scene)
8. **Line 128-129**: RapierHelper でデバッグ表示
9. **Line 135-156**: addBody() でランダムなオブジェクトを追加
10. **Line 154**: physics.addMesh(mesh, 1, 0.5) で質量1、反発0.5
11. **Line 167-192**: animate() で更新処理

#### Step 3: 物理ヘルパーの内部を理解する

RapierPhysics.js の内部実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | RapierPhysics.js | `examples/jsm/physics/RapierPhysics.js` | Rapier 統合実装 |

**主要処理フロー**:
- **import('@dimforge/rapier3d-compat')**: Rapier WASM を動的インポート
- **RAPIER.init()**: Rapier 初期化
- **new RAPIER.World()**: 物理ワールド作成
- **addMesh()**: メッシュから RigidBody と Collider を作成
- **step()**: 物理シミュレーションを進行
- **setMeshPosition/setMeshRotation**: メッシュと物理ボディを同期

#### Step 4: ソフトボディを理解する

Ammo.js によるソフトボディシミュレーションを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | physics_ammo_cloth.html | `examples/physics_ammo_cloth.html` | 布シミュレーション |

**主要処理フロー**:
- btSoftBodyHelpers.CreatePatch() で布を作成
- softBody.setTotalMass() で質量設定
- softBody.get_m_cfg().set_viterations() で反復回数設定
- 頂点位置を毎フレーム更新

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

```
physics_rapier_basic.html (エントリーポイント)
    |
    +-- init()
    |      +-- THREE.Scene()
    |      +-- THREE.PerspectiveCamera()
    |      +-- THREE.WebGLRenderer()
    |      +-- floor = new THREE.Mesh()
    |      |      +-- userData.physics = { mass: 0 }
    |      +-- scene.add(floor)
    |      +-- initPhysics()
    |
    +-- initPhysics()
    |      +-- physics = await RapierPhysics()
    |      |      +-- import('@dimforge/rapier3d-compat')
    |      |      +-- RAPIER.init()
    |      |      +-- new RAPIER.World()
    |      |
    |      +-- physics.addScene(scene)
    |      |      +-- scene.traverse() で全メッシュを検索
    |      |      +-- userData.physics があれば addMesh()
    |      |
    |      +-- physicsHelper = new RapierHelper(physics.world)
    |      +-- scene.add(physicsHelper)
    |      |
    |      +-- setInterval(addBody, 1000)
    |
    +-- addBody()
    |      +-- new THREE.Mesh(geometry, material)
    |      +-- scene.add(mesh)
    |      +-- physics.addMesh(mesh, mass, restitution)
    |
    +-- animate()
           +-- [落下オブジェクト削除]
           |      +-- scene.remove(object)
           |      +-- physics.removeMesh(object)
           |
           +-- physicsHelper.update()
           +-- controls.update()
           +-- renderer.render(scene, camera)
```

### データフロー図

```
[物理シミュレーションのデータフロー]

THREE.Mesh ───────> physics.addMesh(mesh, mass, restitution)
(位置/回転)               |
                         v
                  RigidBody + Collider 作成
                         |
                         v
                  physics.world に追加
                         |
                         v
                  world.step(dt)  [毎フレーム]
                         |
                         v
                  RigidBody から位置/回転を取得
                         |
                         v
                  mesh.position/quaternion を更新
                         |
                         v
                  renderer.render()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| RapierPhysics.js | `examples/jsm/physics/RapierPhysics.js` | ソース | Rapier 統合 |
| AmmoPhysics.js | `examples/jsm/physics/AmmoPhysics.js` | ソース | Ammo 統合 |
| JoltPhysics.js | `examples/jsm/physics/JoltPhysics.js` | ソース | Jolt 統合 |
| RapierHelper.js | `examples/jsm/helpers/RapierHelper.js` | ソース | Rapier デバッグ表示 |
| RoundedBoxGeometry.js | `examples/jsm/geometries/RoundedBoxGeometry.js` | ソース | 角丸ボックスジオメトリ |
| physics_rapier_*.html | `examples/physics_rapier_*.html` | テンプレート | Rapier サンプル |
| physics_ammo_*.html | `examples/physics_ammo_*.html` | テンプレート | Ammo サンプル |
| physics_jolt_*.html | `examples/physics_jolt_*.html` | テンプレート | Jolt サンプル |
