WebGL 1.0 OpenGL ES 2.0 Google Chrome 14.0.835.202 m |
■WebGLで自作のCOLLADローダー [ サンプルページの表示 ] | Prev Top Next | |
|
今回は、COLLADAフォーマット形式のdaeファイルのローダーを自作します。
COLLADAは、XMLベースの3Dアセットデータ( 3Dモデル、テクスチャ、シェーダ、物理パラメータなど )を扱うためのファイルフォーマットです。
XMLベースのため、javascriptからの扱いが容易です。まあ楽だから実装してみようと思ったわけですけどね。
当ページのサンプルでは、3Dモデルとテクスチャのロードに焦点を絞って実装します。
「Canvas 3d JS Library」のソースを参考にしていますが、ライブラリ自体は一切使用せず、すべて自作しています。
なおCOLLADAについて詳細をチェックしたい方は、公式サイトCOLLADA - Digital Asset and FX Exchange Schemaを参照してください。
さてソースの解説ですが、今回はまじめにやります(笑)。
今回は新規で作成した2つのjavascriptファイルを使用します。
Mesh.js | 頂点データの定義クラス |
collada.js | COLLADAのローダークラス |
collada.js内で実装しているColladaLoaderクラスのリファレンスを作ったので見たい人はColladaLoaderクラスのリファレンスを参照してください。
さてColladaLoaderクラス内で最も肝となる parse 関数について解説していきます。 この関数は読み込んだ頂点データをWebGLで描画するための形式に変換します。 実装は基本的に「Canvas 3d JS Library」のソースを参考にしています。 またよくわからんところはCOLLADA DOMを使った3Dモデルデータの読み込みを参照しました。
■Meshクラス
描画用バッファです。daeファイルから読み込んだ頂点情報やテクスチャーファイル名が格納されます。
vertexメンバは連想配列になっています。"VERTEX", "NORMAL", "TEXCOORD" などの頂点エレメントごとに座標値が格納されます。
例えば頂点座標を参照する場合は、
Mesh[0].vertex["VERTEX"][0]
このようにして行います。
連想配列は C++ で使用できないので、あまり使用すべきではないかもしれませんが、拡張性が容易になるので使ってみました。
■ColladaLoaderクラス
1.バージョンチェック
まずCOLLADAフォーマットのバージョンチェックします。バージョンが変わるとCOLLADAフォーマットの仕様が変わる可能性があるためバージョンチェックします。
なお<COLLADA>要素には XML Schema のurlも記述されています。可能であれば XML Schema によるCOLLADAフォーマットの文法チェックも行いたいところですが、 javascriptでのやり方がわからないのでやりません。
2.メッシュの頂点情報が格納されているパスを検索するための識別子を取得する
<instance_geometry>要素にメッシュの頂点情報が格納されているパスを検索するための識別子が格納されています。 1ファイル内に複数のメッシュが設定される場合があるので、複数個取得できるように作成しました。 同じ階層に<translate>要素などがあります。これはメッシュの表示座標や姿勢制御で使用するパラメータだと思いますが、サンプルでは使用しません。3.<polylist>要素のデータを取得するまた子要素の<instance_material>にはテクスチャー情報を検索するための識別子が格納されています。
なおカメラや照明に関するデータはサンプルでは使用しません。
<polylist>要素の子要素には"VERTEX"など各頂点エレメントの実データが格納されているパスを検索するための識別子が格納されています。
他にも1ポリゴン当たりの頂点数( <vcount>要素 )や
インデックスデータ( <p>要素 )が格納されています。なおpolylist以外にもpolygonなどといった形式もありますが、サンプルではpolylistのみ実装しています。
4.インデックスデータを三角ポリゴン用にコンバートする
描画時に使用する関数を1つのみにするため、インデックスデータをすべて三角ポリゴンのみで構成されるようにコンバートします。 1ポリゴン当たりの頂点数は<vcount>要素に格納されているので、半角スペースを区切り文字としてばらして配列に格納し、 <p>要素にインデックスデータが格納されているので、これも同様に半角スペースを区切り文字としてばらして配列に格納してから、 2つの配列を突き合わせて三角ポリゴンにコンバートしていきます。なおインデックスデータは頂点エレメントごとに個別に格納されています。 <p>要素にすべての頂点エレメントのデータがまとめて格納されているので頂点エレメントごとにばらして取得します。
<input semantic="VERTEX" offset="0"/>
<input semantic="NORMAL" offset="1"/>
<input semantic="TEXCOORD" offset="2"/>
<p>0 0 0 1 1 1 2 2 2</p><input>要素のoffset属性値が<p>要素内での各頂点エレメントの出現順番を示します。
上の例の場合、"VERTEX", "NORMAL", "TEXCOORD", "VERTEX", .....
の順番で<p>要素にインデックスデータが格納されています。
5.座標を取得して描画用バッファに格納する
<input>要素のsource属性値を識別子とし各頂点エレメントの座標を取得します。 座標データは、例えば頂点座標の場合、X, Y, Z, X, Y, Z, ... の順番にデータが格納されています。座標データを配列に格納する際注意するべきところがあります。 すでに説明したとおり、COLLADAフォーマットでは頂点エレメントごとに個別にインデックスデータを持っています。 しかし描画時に使用するインデックスバッファは頂点エレメントごとに設定できないので、頂点ごとにまとめる必要があります。
しかしdaeファイルに書き込まれているインデックスデータをみてみると頂点エレメントごとに微妙に違う値を示している個所があったりします。 サンプルではとりあえずテクセル座標で設定されているインデックスデータを使用してまとめることにしました。これだと描画結果が正しいように見えるのでね。
この方法が正しいかは自身ないので、インデックスバッファを使用しない方法で描画用バッファを作成するのもありかと思います。あとテクセル座標の場合、WebGLでは左下隅が原点になるため、縦方法に対して座標を反転します。
6.テクスチャーのファイル名を取得
ソースが長くて嫌になりそうですが、テクスチャーのファイル名を取得します。
さて長々とやってきた WebGL ですが、一通りやった気になったので今回でいったん終了とします。次のネタは未定です。