# 帳票設計書 5-DRACOExporter

## 概要

本ドキュメントは、Three.jsライブラリにおけるDRACOExporterの帳票設計書である。DRACOExporterはGoogle Dracoライブラリを使用してジオメトリを圧縮形式（.drc）でエクスポートするためのモジュールであり、メッシュとポイントクラウドに対応する。

### 本帳票の処理概要

DRACOExporterは、Three.jsのMeshまたはPointsオブジェクトのジオメトリをDraco圧縮形式に変換してエクスポートする機能を提供する。Dracoは高効率な3Dジオメトリ圧縮アルゴリズムを使用し、大幅なファイルサイズ削減を実現する。

**業務上の目的・背景**：Draco形式はGoogleが開発したオープンソースの3Dジオメトリ圧縮ライブラリであり、WebGL/WebGPUアプリケーションにおいて転送サイズと読み込み時間を大幅に削減できる。glTFファイルに埋め込む形式が一般的だが、スタンドアロンの.drcファイルとしても利用可能。ネットワーク帯域の最適化、モバイルアプリケーションでの3Dコンテンツ配信に必要となる。

**帳票の利用シーン**：大規模3Dモデルのウェブ配信、モバイルアプリ向け軽量アセット作成、glTF-Pipelineとの連携、クラウドベースの3Dビューワー向けアセット準備時に利用される。

**主要な出力内容**：
1. Dracoエンコードされたジオメトリデータ
2. 頂点位置（必須、量子化可能）
3. 法線ベクトル（オプション、量子化可能）
4. UV座標（オプション、量子化可能）
5. 頂点カラー（オプション、量子化可能、sRGB形式）
6. 面インデックス（メッシュの場合）

**帳票の出力タイミング**：ユーザーがエクスポート操作を実行した時点でparseメソッドを呼び出すことで出力される。DracoEncoderModuleのロードが必要なため、事前準備が必要。

**帳票の利用者**：ウェブ開発者、3Dコンテンツ配信担当者、モバイルアプリ開発者、パフォーマンス最適化エンジニアが主な利用者である。

## 帳票種別

3Dモデルデータ出力（圧縮バイナリファイル）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | Three.js アプリケーション | N/A（ライブラリ使用） | DRACOExporter.parse() メソッド呼び出し |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | Draco Compressed (.drc) |
| 用紙サイズ | N/A（圧縮バイナリファイル） |
| 向き | N/A |
| ファイル名 | 任意（アプリケーション側で指定） |
| 出力方法 | Int8Array として返却 |
| 文字コード | N/A（バイナリ） |

### DRACO固有設定

| 項目 | 内容 |
|-----|------|
| decodeSpeed | デコード速度優先度 0-10（デフォルト: 5） |
| encodeSpeed | エンコード速度優先度 0-10（デフォルト: 5） |
| encoderMethod | エンコード方式（Edgebreaker: 1、Sequential: 0、デフォルト: 1） |
| quantization | 量子化ビット数 [POSITION, NORMAL, COLOR, TEX_COORD, GENERIC]（デフォルト: [16, 8, 8, 8, 8]） |
| exportUvs | UV座標を出力するか（デフォルト: true） |
| exportNormals | 法線を出力するか（デフォルト: true） |
| exportColor | 頂点カラーを出力するか（デフォルト: false） |

## 帳票レイアウト

### レイアウト概要

Dracoファイルは独自のバイナリフォーマットで、エンコーダーによって内部構造が決定される。

```
┌─────────────────────────────────────┐
│          Dracoヘッダー               │
│  (マジックナンバー、バージョン等)      │
├─────────────────────────────────────┤
│        エンコード設定メタデータ        │
│  (量子化ビット数、エンコード方式)      │
├─────────────────────────────────────┤
│         圧縮ジオメトリデータ          │
│  (頂点位置、法線、UV、カラー)         │
├─────────────────────────────────────┤
│         圧縮インデックスデータ         │
│  (メッシュの場合のみ)                │
└─────────────────────────────────────┘
```

### ヘッダー部

Dracoの内部ヘッダーはエンコーダーライブラリによって自動生成される。Three.jsエクスポーターから直接制御するヘッダー項目はない。

### 明細部（属性データ）

| No | 項目名 | 説明 | データ取得元 | 量子化ビット数 |
|----|-------|------|-------------|--------------|
| 1 | POSITION | 頂点位置 | geometry.getAttribute('position') | options.quantization[0] (デフォルト: 16) |
| 2 | NORMAL | 法線ベクトル | geometry.getAttribute('normal') | options.quantization[1] (デフォルト: 8) |
| 3 | COLOR | 頂点カラー | geometry.getAttribute('color') | options.quantization[2] (デフォルト: 8) |
| 4 | TEX_COORD | UV座標 | geometry.getAttribute('uv') | options.quantization[3] (デフォルト: 8) |

### フッター部

Dracoフォーマットには明示的なフッターは存在しない。

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| object | エクスポート対象のMeshまたはPoints | Yes |
| options | エクスポートオプション | No |
| DracoEncoderModule | Dracoエンコーダーライブラリ | Yes（グローバル） |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | 頂点インデックス | 昇順 |

### 改ページ条件

N/A（単一ファイル出力）

## データベース参照仕様

### 参照テーブル一覧

本エクスポーターはデータベースを使用せず、Three.jsオブジェクトのメモリ上のデータを直接参照する。

| データソース | 用途 | 参照方法 |
|-------------|------|---------|
| Mesh | メッシュデータ | isMesh プロパティで判定 |
| Points | 点群データ | isPoints プロパティで判定 |
| BufferGeometry | ジオメトリデータ | geometry プロパティ |

### テーブル別参照項目詳細

#### BufferGeometry（Mesh用）

| 参照項目（属性名） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| position | POSITION属性 | 必須 | Float配列で取得 |
| normal | NORMAL属性 | exportNormals=true時 | Float配列で取得 |
| uv | TEX_COORD属性 | exportUvs=true時 | Float配列で取得 |
| color | COLOR属性 | exportColor=true時 | sRGB変換後Float配列 |
| index | 面インデックス | 存在時 | なければ連番生成 |

#### BufferGeometry（Points用）

| 参照項目（属性名） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| position | POSITION属性 | 必須 | Float配列で取得 |
| color | COLOR属性 | exportColor=true時 | sRGB変換後Float配列 |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| 面インデックス配列 | index存在時: index.array、なし時: [0,1,2,...,count-1] | なし | Uint16/Uint32 |
| 頂点カラー(sRGB) | ColorManagement.workingToColorSpace(color, SRGBColorSpace) | なし | 作業色空間→sRGB |
| 圧縮サイズ | エンコーダー依存 | なし | 元データの数分の1程度 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[parse呼び出し] --> B[オプションマージ]
    B --> C{DracoEncoderModule存在?}
    C -->|No| D[Error throw]
    C -->|Yes| E[エンコーダー初期化]
    E --> F{isMesh?}
    F -->|Yes| G[MeshBuilder生成]
    F -->|No| H{isPoints?}
    H -->|Yes| I[PointCloudBuilder生成]
    H -->|No| J[Error throw]
    G --> K[position属性追加]
    I --> K
    K --> L{exportNormals?}
    L -->|Yes| M[normal属性追加]
    L -->|No| N{exportUvs?}
    M --> N
    N -->|Yes| O[uv属性追加]
    N -->|No| P{exportColor?}
    O --> P
    P -->|Yes| Q[color属性追加]
    P -->|No| R[面インデックス追加]
    Q --> R
    R --> S[速度オプション設定]
    S --> T[エンコード方式設定]
    T --> U[量子化設定]
    U --> V[エンコード実行]
    V --> W{成功?}
    W -->|No| X[Error throw]
    W -->|Yes| Y[Int8Array生成]
    Y --> Z[クリーンアップ]
    Z --> AA[結果返却]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| エンコーダー未ロード | DracoEncoderModule未定義 | "THREE.DRACOExporter: required the draco_encoder to work." | draco_encoder.jsをロード |
| 非対応オブジェクト | Mesh/Points以外 | "DRACOExporter: Unsupported object type." | MeshまたはPointsを渡す |
| エンコード失敗 | エンコード結果が0バイト | "THREE.DRACOExporter: Draco encoding failed." | 入力データを確認 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 頂点数: 〜数百万 |
| 目標出力時間 | encodeSpeed設定により変動（5で中程度） |
| 圧縮率 | 元データの1/5〜1/20程度（設定依存） |
| 同時出力数上限 | 1（同期処理） |

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

- Dracoエンコーダーは外部WebAssemblyモジュール（draco_encoder.js）に依存
- 外部モジュールのロード元は信頼できるソースを使用すること
- 出力ファイルへのアクセス制御はアプリケーション側の責務

## 備考

- draco_encoder.jsは別途ロードが必要（CDNまたはローカルホスト）
- glTFファイルに埋め込む場合はglTF-Pipelineの使用を推奨
- スタンドアロン.drcファイルはマテリアル、テクスチャ、アニメーション、ノード階層を含まない
- 頂点カラーは作業色空間からsRGBに変換されて出力される（glTF埋め込み時はLinear-sRGB）

---

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

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

### 推奨読解順序

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

Draco圧縮の概念とエクスポーターの役割を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | DRACOExporter.js | `examples/jsm/exporters/DRACOExporter.js` | 5-24行目: JSDocとDraco形式の説明 |

**読解のコツ**: DracoEncoderModuleはグローバル変数として提供される外部ライブラリであることを理解する。

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

parseメソッドの全体構造とオプション処理を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | DRACOExporter.js | `examples/jsm/exporters/DRACOExporter.js` | 34-44行目: parseメソッドとデフォルトオプション |

**主要処理フロー**:
1. **36-44行**: デフォルトオプションのマージ
2. **46-50行**: DracoEncoderModule存在チェック
3. **52-56行**: エンコーダーとビルダーの初期化

#### Step 3: Mesh処理を理解する

メッシュのエンコード処理を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | DRACOExporter.js | `examples/jsm/exporters/DRACOExporter.js` | 59-123行目: Mesh処理 |

**主要処理フロー**:
- **61-62行**: MeshBuilderとMesh初期化
- **64-65行**: position属性追加
- **67-85行**: 面インデックス追加（存在時/非存在時）
- **87-97行**: normal属性追加（exportNormals時）
- **99-109行**: uv属性追加（exportUvs時）
- **111-123行**: color属性追加（exportColor時）

#### Step 4: Points処理を理解する

ポイントクラウドのエンコード処理を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | DRACOExporter.js | `examples/jsm/exporters/DRACOExporter.js` | 125-151行目: Points処理 |

**主要処理フロー**:
- **127-128行**: PointCloudBuilderとPointCloud初期化
- **130-131行**: position属性追加
- **133-145行**: color属性追加（exportColor時）

#### Step 5: エンコード実行を理解する

圧縮処理とクリーンアップを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | DRACOExporter.js | `examples/jsm/exporters/DRACOExporter.js` | 153-222行目: エンコード実行 |

**主要処理フロー**:
- **155行**: DracoInt8Array生成
- **159-162行**: encode/decode速度設定
- **166-170行**: エンコード方式設定
- **174-186行**: 量子化設定（5属性分）
- **190-198行**: エンコード実行（Mesh/Points）
- **200行**: オブジェクト破棄
- **202-206行**: エンコード失敗チェック
- **209-215行**: 出力配列生成
- **217-219行**: リソースクリーンアップ

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

```
DRACOExporter.parse(object, options)
    │
    ├─ オプションマージ
    │      ├─ decodeSpeed: 5
    │      ├─ encodeSpeed: 5
    │      ├─ encoderMethod: MESH_EDGEBREAKER_ENCODING (1)
    │      ├─ quantization: [16, 8, 8, 8, 8]
    │      ├─ exportUvs: true
    │      ├─ exportNormals: true
    │      └─ exportColor: false
    │
    ├─ DracoEncoderModule存在チェック
    │      └─ なし: Error throw
    │
    ├─ dracoEncoder = DracoEncoderModule()
    │
    ├─ encoder = new dracoEncoder.Encoder()
    │
    ├─ object.isMesh === true
    │      │
    │      ├─ builder = new dracoEncoder.MeshBuilder()
    │      ├─ dracoObject = new dracoEncoder.Mesh()
    │      │
    │      ├─ AddFloatAttributeToMesh(POSITION)
    │      ├─ AddFacesToMesh(faces)
    │      ├─ AddFloatAttributeToMesh(NORMAL) [optional]
    │      ├─ AddFloatAttributeToMesh(TEX_COORD) [optional]
    │      └─ AddFloatAttributeToMesh(COLOR) [optional]
    │
    ├─ object.isPoints === true
    │      │
    │      ├─ builder = new dracoEncoder.PointCloudBuilder()
    │      ├─ dracoObject = new dracoEncoder.PointCloud()
    │      │
    │      ├─ AddFloatAttribute(POSITION)
    │      └─ AddFloatAttribute(COLOR) [optional]
    │
    ├─ encoder.SetSpeedOptions(encodeSpeed, decodeSpeed)
    ├─ encoder.SetEncodingMethod(encoderMethod)
    ├─ encoder.SetAttributeQuantization(0-4, bits)
    │
    ├─ EncodeMeshToDracoBuffer / EncodePointCloudToDracoBuffer
    │
    ├─ dracoEncoder.destroy(dracoObject)
    │
    ├─ 結果チェック（length === 0でError）
    │
    ├─ Int8Array生成（encodedData.GetValue(i)をコピー）
    │
    └─ クリーンアップ
           ├─ dracoEncoder.destroy(encodedData)
           ├─ dracoEncoder.destroy(encoder)
           └─ dracoEncoder.destroy(builder)
```

### データフロー図

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

Mesh/Points ────────▶ DracoEncoderModule() ────▶ dracoEncoder
      │                     │
      ▼                     ▼
geometry.position ─▶ AddFloatAttribute(POSITION) ▶ Draco属性
geometry.normal ───▶ AddFloatAttribute(NORMAL) ──▶ Draco属性
geometry.uv ───────▶ AddFloatAttribute(TEX_COORD)▶ Draco属性
geometry.color ────▶ createVertexColorSRGBArray() ▶ sRGB変換
      │                     │
      │                     ▼
      │              AddFloatAttribute(COLOR) ────▶ Draco属性
      │                     │
geometry.index ────▶ AddFacesToMesh() ────────────▶ Dracoメッシュ
      │                     │
      │                     ▼
      │              SetSpeedOptions()
      │              SetEncodingMethod()
      │              SetAttributeQuantization()
      │                     │
      │                     ▼
      │              EncodeMeshToDracoBuffer()
      │                     │
      │                     ▼
      │              DracoInt8Array
      │                     │
      │                     ▼
      └──────────────▶ Int8Array（出力）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| DRACOExporter.js | `examples/jsm/exporters/DRACOExporter.js` | ソース | メインエクスポーター実装 |
| draco_encoder.js | 外部（google/draco） | 外部ライブラリ | Dracoエンコーダー本体 |
| three.module.js | `build/three.module.js` | ソース | Three.jsコアライブラリ（Color, ColorManagement等） |
