PlayCanvasエディターのシーンを動的にGLB / USDZとしてエクスポートをする

#### PlayCanvasについて
[PlayCanvas](https://playcanvas.jp/)はJavaScriptで記述されたWebGLのエンジンで、最近GitHubのスター数が7000を超えました。SaaS型のエディターを兼ね備えているゲームエンジンです。engineについては主にSnapのメンバー[Will Eastcott](https://twitter.com/willeastcott)を中心にOSSとして公開及び継続的に開発が進められています。Engine単体として利用する場合には、Three.js, Babylon.jsなどのWebGLライブラリと似た使い方を使用することができます。またビジュアルエディターとコードエディターが存在しており。エディターはクラウド上でプロジェクトの作成から公開までが出来ます。FBXやOBJといった3Dモデルの素材については、ブラウザへドラッグアンドドロップをすることでGUIから操作・配置ができるエディターがあります。

本記事では、[PlayCanvas](https://playcanvas.jp/)のExamplesを参考にGLB形式 / USDZ形式でエクスポートをするPlayCanvasエディターでも同様にダウンロードをする方法を紹介します。
- [GltfExport - Tutorial](https://playcanvas.github.io/#/loaders/gltf-export)

#### エクスポーターについて

[PlayCanva Engine](https://github.com/playcanvas/engine)のGitHubリポジトリには、Extrasといった、`Gltfエクスポーター(GltfExpoter)`や`USDZエクスポーター(UsdzExporter)`のコードを含む、`extras.js`というスクリプト集が本体とは別に存在しています。

ビルド済みのそれぞれの最新バージョンのコードはこちらからCDN経由で配信もされています。

- PlayCanvas Engine
```
https://code.playcanvas.com/playcanvas-latest.js
```

- PlayCanvas Engine Extras
```
https://code.playcanvas.com/playcanvas-extras-latest.js
```

PlayCanvasエディターを利用している場合には、開発中には自動的に読み込むファイルに`extras.js`が読み込まれています。エディターを利用しない場合や開発したプロジェクトをホスティングをする場合には、別途`extras.js`をプロジェクトに追加をしてください。


## PlayCanvasエディターに組み込む

今回は、PlayCanvasエディターと親和性の高い[pcui](https://github.com/playcanvas/pcui)ライブラリを利用して、シーンを`glb` `usdz`に変換をしてダウンロードボタンを配置します。

### 1. pcuiをダウンロードてシーンに配置
[こちらのリンク先](https://gist.github.com/yushimatenjin/a0dc42c5aa13f9987c66f4de0b3b1982#file-pcui-bundle-min-js
)はpcuiをビルドしたスクリプトとなります。
コードを`puci-bundle-min.js`などの名前でエディターのプロジェクトに配置をしてください。


### 2. エクスポート用のスクリプトを追加

エディターから新規に`exporter-ui.js`といった名前でスクリプトを作成します。
スクリプトを新規に作成しこちらを貼り付けてください。
```exporter-ui.js
const ExporterUi = pc.createScript('exporter-ui');

ExporterUi.prototype.initialize = function () {
    // HTML要素を作成してCSSを適用
    const wrapper = document.createElement("div");
    wrapper.id = "glb-exporter-wrapper"
    wrapper.style.position = "absolute"
    wrapper.style.zIndex = "5"
    wrapper.style.width = "300px"
    wrapper.style.height = "100vh"
    document.body.appendChild(wrapper);

    // pcuiのセットアップ
    const { Container, Button } = pcui;
    const container = new Container({ grid: true });
    wrapper.appendChild(container.dom)

    this.glbExportButton = new Button({ id: "glb-export-button", text: "Download GLB" });
    this.usdzExportButton = new Button({ id: "usdz-export-button", text: "Download USDZ" });
    container.append(this.glbExportButton);
    container.append(this.usdzExportButton);

    this.glbExportButton.on("click", () => this.exportGlb());
    this.usdzExportButton.on("click", () => this.exportUsdz());

};

ExporterUi.prototype.exportGlb = async function () {
    const exporter = new pcx.GltfExporter()
    const buffer = await exporter.build(this.app.root);
    const blob = new Blob([buffer], { type: "application/octet-stream", });
    const fileName = "model.glb";
    this.download(blob, fileName)
}


ExporterUi.prototype.exportUsdz = async function () {

 const exporter = new pcx.UsdzExporter()
    const buffer = await exporter.build(this.app.root);
    const blob = new Blob([buffer], { type: "application/octet-stream", });
    const fileName = "model.usdz";
    this.download(blob, fileName)
}

// モデルデータのダウンロード
ExporterUi.prototype.download = function (blob, fileName) {
    const  a = document.createElement("a");
    a.href = URL.createObjectURL(blob);
    a.download = fileName;
    document.body.appendChild(a); 
    a.click(); 
    document.body.removeChild(a);
}

```


### 3. コードについて
これで、PlayCanvasエディター上には、２つのスクリプトが配置されている状態になります。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257048/8b095f5b-9ea4-256a-7d62-856fcb9ccd23.png)

### 4. RootエンティティにScriptコンポーネントを追加して、`exporter-ui`スクリプトを追加
Scriptコンポーネントを作成して、スクリプト (`exporter-ui`)をエディタに追加します。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257048/9715c40f-4738-5c62-deb4-507df2808f5a.png)


### 5. プロジェクトを起動
プロジェクトを起動するとDownload GLBボタンとDonwload USDZボタンが追加されています。
こちらをクリックするとそれぞれの方法でモデルをダウンロードできます。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257048/60f6ca5f-3058-dee9-15ec-5fa44791b496.png)


### 6. ダウンロードしたシーンをBlenderで読み込む
ダウンロードしたモデル(`glb` / `usdz`)は3Dモデリング用のツールで読み込む事ができます。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257048/ff7b52fb-ed52-c9bf-137d-267407b39c17.png)

現在、こちらの`USDZエクスポーター`については[開発中](https://github.com/playcanvas/engine/issues/4644)となっており、今後変更が加えられる可能性が高いです。