WebGL と JavaScript で学ぶ3D表現

3Dモデリングソフトで制作したモデルデータの読み込み方を説明します。3Dのモデルデータにはさまざまな形式が存在しますが、Three.jsは対応している形式がです。

Three.jsでは外部ソフトを利用して作成した3Dモデリングデータを読み込むことができます。Three.jsではファイルを読み込むときにローダー(ファイルを解析する機能)を使ってモデルデータを読み込みます。

Three.jsが対応するモデルデータの形式

Three.jsでは次の形式の読み込みに対応しています。

  • GLTF形式(ジーエルティーエフ形式) : インターネット向けの3Dファイル形式。2017年に仕様として定められた新しい形式。
  • OBJ形式 : Wavefront社のAdvanced Visualizerというソフト用のファイルフォーマット。テキストデータ。
  • Collada(dae)形式 : 汎用的なデータファイル。XMLで構成されている。
  • FBX形式(バイナリー)
  • 3DMax (.3ds)形式 : Autodesk 3ds Maxの出力フォーマットとして使われるデータ形式。
  • Quake 2 MD2(.md2)形式 : Id Software’sがQuake II用に作成したファイルフォーマット。
  • BlenderからThree.js Exporterを使って出力したJSON形式

Three.jsでの読み込み方

Three.jsでモデルデータを読み込むには、JavaScriptでThree.jsの初期化を済ませたあとで、ローダーを使ってファイルを読み込み、3D空間に追加するという手順をとります。

データ形式ごとにローダークラスが用意されています。ただ、ローダークラスは、Three.jsライブラリの本体に含まれていないので注意が必要です。ローダークラスはscriptタグ等で取り込む必要があります。

GLTFファイルの場合

GLTF(ジーエルティーエフ)はインターネット向けの3Dファイル形式です。クロノスグループによって2017年に仕様として定められました。GLTFの中身はJSONファイルを中心として、そこから参照される画像やメッシュデータ等の関連ファイルで構成されています。

GLTFファイルのサンプルはクロノスグループのGitHubから取得できます。

今回は以下のファイルを利用します。ライセンスがPublic domain (CC0) のファイルです。

https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/ToyCar

gltfファイルの場合を読み込むにはGLTFLoader.jsファイルが必要となります。

<script src="https://unpkg.com/three@0.147.0/examples/js/loaders/GLTFLoader.js"></script>

※Three.js r148(2022年12月リリース)よりexamples/jsフォルダーでの提供はなくなりました。今後はES Modulesでの利用を推奨されますので、本記事もゆくゆく更新します。

読み込む処理は次のように記載します。THREE.GLTFLoaderクラスのインスタンスから、loadAsync()メソッドを利用します。 引数にはファイルパスを指定します。読み込み完了後に3D空間への追加処理をするのがポイントです。GLTFファイルにはシーンの情報の他に、カメラやライトなどさまざまな情報が含まれます。そのため、シーンの情報だけ抜き出すようにしましょう。

// 非同期処理で待機するのでasync function宣言とする
async function init() {
  // ・・・省略

  // GLTF形式のモデルデータを読み込む
  const loader = new THREE.GLTFLoader();
  // GLTFファイルのパスを指定
  const gltf = loader.loadAsync('./models/gltf/glTF/ToyCar.gltf');
  // 読み込み後に3D空間に追加
  const model = gltf.scene;
  scene.add(model);
  
  // ・・・省略
}

このコードの実行結果は次のとなります。

GLTFには、バイナリ形式のGLBがあります。GLTFはテキストデータや関連ファイルがばらけているのに対して、GLBはGLTFを1ファイルにまとめた形式となっています。GLBファイルを読み込む場合もGLTFLoaderクラスを利用します。コードは先ほど紹介したものとほとんど同じです。

// 非同期処理で待機するのでasync function宣言とする
async function init() {
  // ・・・省略

  // GLTF形式のモデルデータを読み込む
  const loader = new THREE.GLTFLoader();
  // GLTFファイルのパスを指定
  const objects = loader.loadAsync('./models/gltf/binary/ToyCar.glb');
  // 読み込み後に3D空間に追加
  const model = objects.scene;
  scene.add(model);
  
  // ・・・省略
}

昔のThree.jsにloadAsync()メソッドは存在せず、load()メソッドのみ提供されていました。ネット上の記事では、load()メソッドで説明されているものが多いですが、Promiseによる非同期処理が苦手でなければawaitasyncを使って制御するといいでしょう。

3dsファイルの場合

3dsファイルの場合を読み込むにはTDSLoader.jsファイルが必要となります。CDNで読み込む場合は以下のscriptタグをHTMLに記述します。

<script src="https://unpkg.com/three@0.147.0/examples/js/loaders/TDSLoader.js"></script>

※Three.js r148(2022年12月リリース)よりexamples/jsフォルダーでの提供はなくなりました。今後はES Modulesでの利用を推奨されますので、本記事もゆくゆく更新します。

読み込む処理は次のように記載します。THREE.TDSLoaderクラスのインスタンスから、loadAsync()メソッドを利用します。戻り値としてPromiseオブジェクトを返すのでawaitasyncで待機します。 引数にはファイルパスを指定します。

なお、3dsファイルのテクスチャーのパスがずれないように、setResourcePathメソッドを使って、明示的にテクスチャーが含まれるフォルダーのパスを指定します。

// 非同期処理で待機するのでasync function宣言とする
async function init() {
  // ・・・省略

  // 3DS形式のモデルデータを読み込む
  const loader = new THREE.TDSLoader();
  // テクスチャーのパスを指定
  loader.setResourcePath('models/3ds/portalgun/textures/');
  // 3dsファイルのパスを指定
  const object = loader.loadAsync('models/3ds/portalgun/portalgun.3ds');
  // 読み込み後に3D空間に追加
  scene.add(object);

  // ・・・省略
}

このコードの実行結果は次のとなります。

Colladaファイルの場合

Colladaファイル(拡張子は.dae)の場合を読み込むにはColladaLoader.jsファイルが必要となります。

<script src="https://unpkg.com/three@0.147.0/examples/js/loaders/ColladaLoader.js"></script>

※Three.js r148(2022年12月リリース)よりexamples/jsフォルダーでの提供はなくなりました。今後はES Modulesでの利用を推奨されますので、本記事もゆくゆく更新します。

読み込む処理は次のように記載します。THREE.ColladaLoaderクラスのインスタンスから、loadAsync()メソッドを利用します。 引数にはファイルパスを指定します。読み込み完了後に3D空間への配置処理をするのがポイントです。Colladaファイルにはシーンの情報の他に、カメラやライトなどさまざまな情報が含まれます。そのため、シーンの情報だけ抜き出すようにしましょう。

// 非同期処理で待機するのでasync function宣言とする
async function init() {
  // ・・・省略

  // Collada形式のモデルデータを読み込む
  const loader = new THREE.ColladaLoader();
  // Colladaファイルのパスを指定
  const collada = await loader.loadAsync('./models/collada/elf/elf.dae');
  // 読み込み後に3D空間に追加
  const model = collada.scene;
  scene.add(model);
  // ・・・省略
}

このコードの実行結果は次のとなります。

まとめ

今回はモデルデータの読み込み方について説明しました。JavaScriptだけのコードだとどうしても表現がプログラミングアートよりになってしまうため、モデルデータを使った方が表現のバリエーションを増やせます。とくにキャラクターや建築物、物体の表示にはモデルデータの読み込みがかかせません。

関連

Node.js関連のバンドルツールで各種ローダーを利用する場合は、以下の解説を参照ください。

公開日 : / 最終更新日 :
※Three.jsの2022年11月現在のリビジョン147で解説内容が正しく動作することを確認しています。