GLTFのファイルをGLTF Loderで読み込もうとしたとき、「No DRACOLoader instance provided.」のエラーが出てDRACO圧縮というものあることを知り、
そこから、Webpackを用いたbuild環境でDRACO Loderを使用する設定に一苦労したので、その時の記録
Three.jsのDRACO Loderを使うと、DRACO圧縮されたファイルの解凍とLoadを同時に行ってくれるらしいです。
Dracoはオープンソースの3Dデータの圧縮方式で、Zip圧縮よりも高い圧縮率を実現している圧縮形式です。ファイルを圧縮した状態で保存することができるので、Webサイトのアクセス速度などにも影響してくるのでしょうか?
Doraco Loder関連のエラー
今回はまったエラーは以下の2つです。
Draco Loderを適用していない場合のエラー
app.ts:55 Error: THREE.GLTFLoader: No DRACOLoader instance provided.
at new GLTFDracoMeshCompressionExtension (GLTFLoader.js:1742:10)
at GLTFLoader.parse (GLTFLoader.js:329:37)
at Object.eval [as onLoad] (GLTFLoader.js:167:11)
at eval (three.module.js:42311:38)
単純にDoraco圧縮されていたファイルであったにもかかわらず、通常のGLTFLoderでロードしようとしたのがまずかったようです。
webpackを適切に設定していない場合エラー
draco/draco_decoder.wasm:1
draco/draco_wasm_wrapper.js:1
Failed to load resource: the server responded with a status of 404 (Not Found)
Uncaught (in promise) Error: fetch for "http://127.0.0.1:5501/dist/draco/draco_wasm_wrapper.js" responded with 404: Not Found
at eval (three.module.js:42248:12)
次に、DRACOLoderをコード内にインポートしてコードに組み込み、webpackでbuildした時にこれらのようなエラーが出ました。
Not Foundなので「draco_wasm_wrapper.js」などが見つけられないといった内容のエラーです。Webpackでビルドした後の配布用ディレクトリである「/dist」などに「draco_wasm_wrapper.js」を含むディレクトリを上手く配置してやる設定をWebpackのコンフィギュレーションファイルで行わなければいけません。
TypeScriptでのDRACOLoder記述
TypeScriptでDracoLoderを使用する場合の記述について、抜粋したものを示します。
typescript:
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
let scene: THREE.Scene; // シーン定義
/* glbファイルの読み込み */
const loader: GLTFLoader = new GLTFLoader();
const dracoLoader: DRACOLoader = new DRACOLoader();
dracoLoader.setDecoderPath('draco/');
loader.setDRACOLoader(dracoLoader);
loader.load ('/assets/models/gltf/model_name.gltf', function(gltf){
gltf.scene.scale.set(2, 2, 2); // モデルスケール変更
gltf.scene.position.set(0, 0, 0); // モデル位置変更
gltf.scene.rotation.set(0, (0 * Math.PI /180), 0); // モデル向き変更
scene.add(gltf.scene); // モデルをシーンに追加
}, undefined, function (error) {
console.error(error);
});
3行目でDRACOLoderをインポートして、8行目でインスタンス化しています。
9行目には、「draco_wasm_wrapper.js」を含むdracoディレクトリの場所を示すパスを入力します。このパスについては、下のwebpackの設定で指定した場所を指すようにします。
「/assets/models/gltf/model_name.gltf」には、表示したいGLTF形式のファイルか、GLB形式のファイルを指定してください。
webpackのDraco設定方法
「draco_wasm_wrapper.js」を含むdracoディレクトリはnode_modulesディレクトリ内にあります。
ですが、node_modulesを配信用のディレクトリ(distなど)に入れておくわけにもいかないので、dracoディレクトリをwebpackで自動で配信用ディレクトリにコピーするようにします。
■ ファイルのコピーを行うプラグインの追加
コマンド:
npm install copy-webpack-plugin --save-dev
■ webpack.configの設定
webpack.config.js:
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
plugins: [
// ファイルをコピーするプラグイン
new CopyWebpackPlugin({
patterns: [
// dracoのLoaderもdist内に含める記述の追加
{
from: './node_modules/three/examples/jsm/libs/draco/',
to: 'draco',
},
],
})
]
};
CopyWebpackPluginを用いて、10行目でdracoディレクトリのある場所を指定し、ここから11行目のディレクトリにdracoディレクトリの中身をコピーします。
webpackのoutput先として指定しているディレクトリ以下に11行目で指定したディレクトリが作成されます。
Draco圧縮のコマンド
ついでに、GLTFおよびGLBファイルのDraco圧縮方法をまとめておきます。
ツールインストール:
sudo npm install -g gltf-pipeline
gltf-pipeline -i model_name.gltf -o modelDraco.gltf -d
参考:
- https://threejs.org/docs/#examples/en/loaders/DRACOLoader
- https://threejs.org/docs/#examples/en/loaders/GLTFLoader
- https://qiita.com/takavfx/items/aa05a313ef9e450b3731
- https://codelabo.com/posts/20200830135244
以上