# 画面設計書 13-Menubar - Render

## 概要

本ドキュメントは、three.js エディタにおけるレンダリングメニュー（Menubar - Render）の画面設計書である。このメニューは、3Dシーンを静止画または動画として高品質にレンダリング・エクスポートする機能を提供する。

### 本画面の処理概要

**業務上の目的・背景**：3Dシーン編集の最終成果物として、高品質な静止画や動画を出力することは、プレゼンテーション、ポートフォリオ作成、Web公開など様々な場面で必要とされる。このメニューは、SOLIDレンダリング（リアルタイム品質）とREALISTICレンダリング（パストレーシング品質）の両方を提供し、ユーザーのニーズに応じた出力を可能にする。

**画面へのアクセス方法**：エディタメイン画面（editor/index.html）のメニューバー領域に常時表示される。「Render」メニュータイトルをクリックすると、ドロップダウン形式でImage（静止画）とVideo（動画）のオプションが展開される。

**主要な操作・処理内容**：
1. **Image（静止画）レンダリング**：指定解像度で静止画をレンダリングし、新しいウィンドウに表示
2. **Video（動画）レンダリング**：指定解像度・FPS・時間長で動画をレンダリングし、MP4ファイルとしてブラウザ内で再生可能な形式で出力

**画面遷移**：メニュークリックでダイアログが表示され、設定後にレンダリング結果が新しいウィンドウで表示される。Video機能はVideoEncoder APIが利用可能なブラウザでのみ表示される。

**権限による表示制御**：Video機能は `'VideoEncoder' in window` のチェックにより、対応ブラウザでのみ表示される。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 13 | WebGLRenderer | 主機能 | 静止画・動画レンダリングのベースレンダラー |
| 17 | PostProcessing | 補助機能 | パストレーシングレンダリング |

## 画面種別

メニュー（ドロップダウン）+ ダイアログ

## URL/ルーティング

エディタメイン画面の一部として `editor/index.html` に含まれる。独立したルーティングは持たない。

## 入出力項目

### Imageダイアログ

| 項目名 | 入力/出力 | データ型 | デフォルト値 | 説明 |
|--------|----------|---------|-------------|------|
| Shading | 入力 | String | 'solid' | レンダリング品質（'solid' / 'realistic'） |
| Samples | 入力 | Integer | 16 | パストレーシングのサンプル数（3〜65536） |
| Width | 入力 | Integer | 1024 | 出力画像の幅 |
| Height | 入力 | Integer | 1024 | 出力画像の高さ |

### Videoダイアログ

| 項目名 | 入力/出力 | データ型 | デフォルト値 | 説明 |
|--------|----------|---------|-------------|------|
| Width | 入力 | Integer | 1024 | 出力動画の幅（偶数のみ） |
| Height | 入力 | Integer | 1024 | 出力動画の高さ（偶数のみ） |
| FPS | 入力 | Integer | 30 | フレームレート |
| Duration | 入力 | Integer | 10 | 動画の長さ（秒） |
| Quality | 入力 | String | 'high' | ビットレート品質（'low'/'medium'/'high'/'ultra'） |

## 表示項目

### メインメニュー

| 項目 | 表示内容 | 条件 |
|------|---------|------|
| Image | 静止画レンダリングダイアログを開く | 常時表示 |
| Video | 動画レンダリングダイアログを開く | VideoEncoder API対応時のみ |

### Imageダイアログ

| 項目 | 表示内容 |
|------|---------|
| タイトル | "Render Image" |
| Shadingセレクト | SOLID / REALISTIC |
| Samplesフィールド | サンプル数入力（REALISTICモード時のみ表示） |
| Resolutionフィールド | 幅 x 高さ |
| Renderボタン | レンダリング実行 |
| Cancelボタン | ダイアログを閉じる |

### Videoダイアログ

| 項目 | 表示内容 |
|------|---------|
| タイトル | "Render Video" |
| Resolutionフィールド | 幅 x 高さ + fps |
| Durationフィールド | 動画の長さ（秒） |
| Qualityセレクト | Low / Medium / High / Ultra |
| Renderボタン | レンダリング実行 |
| Cancelボタン | ダイアログを閉じる |

## イベント仕様

### 1-Image（静止画レンダリング）

- **トリガー**：Imageメニュー項目クリック → ダイアログのRenderボタンクリック
- **処理内容**：
  1. REALISTICモードの場合、シーン内のマテリアルがMeshStandardMaterialか検証
  2. editor.toJSON()でシーンをJSON化
  3. ObjectLoaderでカメラとシーンをパース
  4. WebGLRendererを作成し、プロジェクト設定（shadows、toneMapping等）を適用
  5. 新しいウィンドウを開いてcanvasを追加
  6. SOLIDモード：即座にrenderer.render()を実行
  7. REALISTICモード：ViewportPathtracerを使用してサンプル数に達するまで更新を繰り返す
- **画面更新**：新しいウィンドウにレンダリング結果が表示される

### 2-Video（動画レンダリング）

- **トリガー**：Videoメニュー項目クリック → ダイアログのRenderボタンクリック
- **処理内容**：
  1. APP.Playerを作成し、editor.toJSON()をロード
  2. 新しいウィンドウを開いてcanvasを追加
  3. VideoEncoderを設定（codec: 'avc1.640028'、ビットレートは品質設定に応じて2〜20Mbps）
  4. 各フレームをレンダリング→ImageBitmap→VideoFrameとしてエンコード
  5. フラッシュ後、createMP4()でMP4ファイルを生成
  6. BlobURLを作成してvideoタグに設定
- **画面更新**：新しいウィンドウに動画プレイヤーが表示される

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

本画面はブラウザ上で動作する3Dエディタであり、データベースへの直接的な更新は行わない。レンダリング結果はブラウザ内で表示またはダウンロード可能な形式で出力される。

## メッセージ仕様

| メッセージ種別 | メッセージ内容 | 表示条件 |
|---------------|---------------|---------|
| 警告（alert） | prompt/rendering/realistic/unsupportedMaterial | REALISTICモードでMeshStandardMaterial以外のマテリアルが含まれる場合 |
| 進捗表示 | "{現在サンプル} / {最大サンプル} ( {進捗}% )" | REALISTICレンダリング中 |
| 進捗表示 | "{現在フレーム} / {総フレーム} ( {進捗}% )" | 動画レンダリング中 |
| 完了表示 | "... ( 100% ) {ファイルサイズ} ✓" | 動画レンダリング完了時 |

## 例外処理

| 例外状況 | 処理内容 |
|---------|---------|
| 非対応マテリアル（REALISTICモード） | alertメッセージを表示し、レンダリングを中止 |
| ウィンドウが閉じられた（Image/Video） | ループ処理を中止（output.closedをチェック） |
| VideoEncoder非対応ブラウザ | Videoメニュー項目自体が表示されない |

## 備考

- Quality設定とビットレートの対応：
  - low: 2Mbps
  - medium: 5Mbps
  - high: 10Mbps
  - ultra: 20Mbps
- 動画エンコードはH.264（AVC）コーデックを使用
- MP4ファイルは独自のシンプルなmuxer（createMP4関数）で生成される
- 動画の幅・高さは偶数である必要がある（toDiv2関数で強制）
- パストレーシングは3〜65536サンプルの範囲で設定可能

---

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

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

### 推奨読解順序

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

レンダリングに必要なデータ構造と、プロジェクト設定の形式を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Editor.js | `editor/js/Editor.js` | editor.toJSON()の形式（scene, camera, project） |
| 1-2 | Viewport.Pathtracer.js | `editor/js/Viewport.Pathtracer.js` | パストレーシングの初期化と更新ロジック |

**読解のコツ**: プロジェクト設定（shadows, toneMapping等）はレンダラーに適用される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Menubar.Render.js | `editor/js/Menubar.Render.js` | メニュー構築とダイアログ表示ロジック |

**主要処理フロー**:
1. **8-72行目**: MenubarRender関数でメニュー構築
2. **24-34行目**: Imageメニュー項目とクリックハンドラ
3. **36-50行目**: Videoメニュー項目（VideoEncoder対応時のみ追加）
4. **54-59行目**: showImageDialog()でRenderImageDialogを表示
5. **63-68行目**: showVideoDialog()でRenderVideoDialogを表示

#### Step 3: ダイアログクラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Menubar.Render.js | `editor/js/Menubar.Render.js` | RenderImageDialog（74-322行目）、RenderVideoDialog（324-579行目） |

**RenderImageDialog主要処理フロー**:
- **157-305行目**: renderButton.onClick() - レンダリング実行処理
- **159-193行目**: REALISTICモード時のマテリアル検証
- **196-217行目**: ObjectLoaderでシーン/カメラをパース、WebGLRenderer作成
- **245-300行目**: SOLIDモードは即座にrender()、REALISTICモードはpathtracerでループ

**RenderVideoDialog主要処理フロー**:
- **411-562行目**: renderButton.onClick() - 動画レンダリング実行処理
- **413-416行目**: APP.Playerを作成してJSONをロード
- **479-512行目**: VideoEncoderの設定
- **517-540行目**: フレームごとのレンダリングとエンコード
- **549行目**: createMP4()でMP4ファイル生成

#### Step 4: MP4生成ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Menubar.Render.js | `editor/js/Menubar.Render.js` | createMP4関数（583-826行目） |

**主要処理フロー**:
- **587-628行目**: ユーティリティ関数（u32, u16, str, concat, box, fullBox）
- **637-641行目**: ftypボックス作成
- **659-704行目**: stsd, stts, stsc, stsz, stco, stssボックス作成
- **762-782行目**: moov, mvhd, trakボックス作成
- **785-803行目**: stcoオフセット更新

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

```
MenubarRender (Menubar.Render.js)
    │
    ├─ image.onClick()
    │      └─ showImageDialog()
    │             └─ new RenderImageDialog()
    │                    │
    │                    └─ renderButton.onClick()
    │                           ├─ editor.toJSON()
    │                           ├─ ObjectLoader.parseAsync()
    │                           ├─ new WebGLRenderer()
    │                           ├─ window.open()
    │                           └─ SOLIDモード: renderer.render()
    │                              REALISTICモード: ViewportPathtracer
    │
    └─ video.onClick()
           └─ showVideoDialog()
                  └─ new RenderVideoDialog()
                         │
                         └─ renderButton.onClick()
                                ├─ new APP.Player()
                                ├─ player.load()
                                ├─ window.open()
                                ├─ new VideoEncoder()
                                ├─ ループ: player.render() → VideoFrame → encode()
                                ├─ createMP4()
                                └─ new Blob() → video.src
```

### データフロー図

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

editor.toJSON() ────────▶ Menubar.Render.js ──────────▶ 新規ウィンドウ
                              │
ダイアログ設定 ──────────────┘                           ▶ 静止画 (canvas)
(解像度/品質/FPS等)                                     ▶ 動画 (MP4 Blob)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Menubar.Render.js | `editor/js/Menubar.Render.js` | ソース | Renderメニューの主要実装 |
| Viewport.Pathtracer.js | `editor/js/Viewport.Pathtracer.js` | ソース | パストレーシング実装 |
| app.js | `editor/js/libs/app.js` | ソース | APP.Player（動画レンダリング用） |
| ui.js | `editor/js/libs/ui.js` | ソース | UIコンポーネント（UIPanel, UIButton, UISelect等） |
| Editor.js | `editor/js/Editor.js` | ソース | editor.toJSON()の実装 |
