glTF 覚え書き
最近 glTF のコンバータを書いたので,少しまとめておきます.
あくまで備忘録のような内容なので,悪しからず.
📌 フォーマットについて
📌 ツール
📌 エクスポータ/インポータ
📌 コンバータ
📌 その他
- JsonGrid - glTF の中身を見るのに便利な JSON ビューア
- GltfBrowser - こちらも glTF の中身を解析できるビューア.公式のサンプルデータを手軽に確認できます.3D ビューアも内蔵されていて便利です.
📌 クイックリファレンス
glTF の公式サイトにはチートシートがあって,有志が日本語版を公開してくれています.このチートシートはわかりやすいのですが,入門という感じで,リファレンスとしては情報が不足しています.公式サイトに完全な仕様があるので,そちらを参照してもいいのですが,手元にあると便利なクリックリファレンス的なものが欲しかったので作成しました.
pdf 版や最新版は以下の場所にあります.
📌 アニメーション
- ノードの TRS および,モーフィング用のウェイトのみ対応
- 将来的にはマテリアルなど他のパラメータに対しても対応できるようになるらしい
- マトリクスのアニメーションは対応していない
- マテリアル関連はまだまだ仕様が固まっていない感じ(個人的な意見)
📌 accessor, bufferView, buffer
glTF を扱う上でこの3つが重要.最終的にデータは accessors と bufferViews の配列サイズが巨大になる.インターリーブ形式を上手くつかえば bufferViews の数は抑えられますが,上手くいった試しがありません.
buffer
バイナリデータ.バイナリデータは base64 形式で埋め込むことが出来るし,バイナリファイルとして別のファイルにすることもできる.buffer ごとにバイナリファイルを別々にすることも可能.
bufferView
1つの buffer を参照し,どの場所からどれくらいのサイズをマッピングするかを指定します.参照したデータは頂点データ用(ELEMENT_BUFFER)か,描画インデックス用(ELEMENT_ARRAY_BUFFER),それ以外かも指定します.インターリーブデータを扱うためのストライドもここで指定します.
accessor
1つの bufferView を参照し,そこにどのような要素が,いくつ格納されているかを指定します.例えば componentType に VEC3 とし,type が 5126 ,count が 100 とすると,bufferView で指定した場所には3次元ベクトルの浮動小数点データが100個配置されていることになります.
📌 スキンアニメーション
glTF の単純なモデルの解説は多いので,ここではスキンアニメーションに関することをまとめておきます.
頂点データにジョイントインデックスとウェイト値を含める
primitive の attributes にジョイントインデックス JOINTS と ウェイト値 WEIGHTS が必要です.JOINTS や WEIGHTS はセマンティクスと呼ばれ,1つの頂点データに同じセマンティクスのデータを複数入れることができます.これはセマンティクス名の後ろにインデックスを追加して指定します.例えば JOINTS_0 や WEIGHTS_0 などです.ちなみに TEXCOORD_0 や COLOR_0 といったテクスチャ座標,カラーにも指定することが出来ます.ジョイントインデックスやウェイト値は1つのインデックスで4つのデータを持ちます.glTF ではそれぞれ指定できる型が限られています.
| semantics | 指定できる型 |
|---|---|
| JOINTS | 5121 (UNSIGNED BYTE), 5123 (UNSIGNED SHORT) |
| WEIGHTS | 5126 (FLOAT), 5121 (UNSIGNED BYTE) normalized, 5123 (UNSIGNED SHORT) normalized |
一般的には JOINTS は UNSIGNED SHORT,WEIGHTS には FLOAT が使われていると思います.
skins
skins には骨構造を記述します.逆バインド行列 inverseBindMatrices,ジョイント配列 joints ,骨構造のルートノード skeleton を設定します.
"skins": [{
"inverseBindMatrices": (index of accessors),
"joints" : [ (index of nodes)...],
"skeleton": (index of nodes)
}]
このデータは node から skin で参照されます.
"nodes": [{
"mesh": (index of meshes),
"skin": (index of skins)
...
}]
animations
animations には channels と samplers があります.
"animations": [{
"channels": [...],
"samplers": [...]
}]
channels ではアニメーション対象 target と,適用するアニメーションのキー情報 samplers を指定します.target の node で対象となるノードを,path で変更する値の種類を,sampler で,キー情報の参照を指定します.
{
"channels": [{
"target": {
"node": (index of nodes),
"path": "translation", "rotation", "scale" or "weights"
},
"sampler": (index of samplers")
}]
}
samplers にはアニメーションのキー情報を指定します.input ではキーフレーム時間(秒),output ではキーフレーム値,interpolation では補間方法を指定します.
{
"samplers": [{
"input": (index of accessors),
"output": (index of accessors),
"interpolation": "LINEAR", "STEP" or "CUBICSPLINE"
}]
}
Discussion