はじめに
3Dモデルの表現形式は非常に種類が多く、
使用できるアプリ、できること、できないことをはっきりさせておかないと大変です。
この記事では最近出てきた表現のglTFについて紹介します。
glTFとは
- 3Dモデルを配布するためのフォーマットで、主にjsonで記述される.拡張子gltf。
- 頂点などのデータは分離してバイナリに格納される。
- 当然、ボーンやテクスチャも表現できる。
COLLADAと比較してみた
colladaから変換する方法がいくつかありますが、今回はblenderから同じ立体を出力して比較してみます。
条件
- Ubuntu 16.04 64bit
- Blender 2.79b (公式サイトよりDL)
- Blender-Exporter from github
- Blender起動時の状態からカメラとランプを削除し、cubeだけexportしてみる。
ファイル形式、容量
生成されるファイルはcolladaがdae単体、gltfが.gltfと.binの2つです。
容量については以下の通りで、colladaのほうが当然ながら大きくなります。
gltf_collada$ ls -lh ./
合計 12K
-rw-rw-r-- 1 h-yaguchi h-yaguchi 612 4月 17 22:13 default_cube.bin
-rw-rw-r-- 1 h-yaguchi h-yaguchi 4.0K 4月 17 22:13 default_cube.dae
-rw-rw-r-- 1 h-yaguchi h-yaguchi 2.7K 4月 17 22:13 default_cube.gltf
マテリアルの記述
colladaではマテリアルの記述はかなり複雑で、
library_effects
に詳細を記述し、
<library_effects>
<effect id="Material-effect">
<profile_COMMON>
<technique sid="common">
<phong>
<emission>
<color sid="emission">0 0 0 1</color>
</emission>
<ambient>
<color sid="ambient">0 0 0 1</color>
</ambient>
<diffuse>
<color sid="diffuse">0.64 0.64 0.64 1</color>
</diffuse>
<specular>
<color sid="specular">0.5 0.5 0.5 1</color>
</specular>
<shininess>
<float sid="shininess">50</float>
</shininess>
<index_of_refraction>
<float sid="index_of_refraction">1</float>
</index_of_refraction>
</phong>
</technique>
</profile_COMMON>
</effect>
</library_effects>
library_material
でeffectを指定し、
<library_materials>
<material id="Material-material" name="Material">
<instance_effect url="#Material-effect"/>
</material>
</library_materials>
形状情報を書くところで指定し、
<triangles material="Material-material" count="12">
さらにvisual_scene
でbind_material
します。
<bind_material>
<technique_common>
<instance_material symbol="Material-material" target="#Material-material"/>
</technique_common>
</bind_material>
gltfはmaterial
に記述してmesh
で指定します。
"materials" : [
{
"name" : "Material",
"pbrMetallicRoughness" : {
"baseColorFactor" : [
0.6400000190734865,
0.6400000190734865,
0.6400000190734865,
1.0
],
"metallicFactor" : 0.0
}
}
],
"meshes" : [
{
"name" : "Cube",
"primitives" : [
{
"attributes" : {
"NORMAL" : 2,
"POSITION" : 1
},
"indices" : 0,
"material" : 0
}
]
}
],
データ格納
colladaはxmlにベタ書きです。
頂点の例を見てみましょう。
<source id="Cube-mesh-positions">
<float_array id="Cube-mesh-positions-array" count="24">1 1 -1 1 -1 -1 -1 -0.9999998 -1 -0.9999997 1 -1 1 0.9999995 1 0.9999994 -1.000001 1 -1 -0.9999997 1 -1 1 1</float_array>
<technique_common>
<accessor source="#Cube-mesh-positions-array" count="8" stride="3">
<param name="X" type="float"/>
<param name="Y" type="float"/>
<param name="Z" type="float"/>
</accessor>
</technique_common>
</source>
一方、gltfの場合はバイナリ形式で保存されており、アクセス方法をjsonで指定します。
"accessors" : [
{
"bufferView" : 0,
"componentType" : 5121,
"count" : 36,
"max" : [
23
],
"min" : [
0
],
"type" : "SCALAR"
},
{
"bufferView" : 1,
"componentType" : 5126,
"count" : 24,
"max" : [
1.0000004768371582,
1.0,
1.0000005960464478
],
"min" : [
-1.0000003576278687,
-1.0,
-1.0000003576278687
],
"type" : "VEC3"
},
{
"bufferView" : 2,
"componentType" : 5126,
"count" : 24,
"max" : [
1.0,
1.0,
1.0
],
"min" : [
-1.0,
-1.0,
-1.0
],
"type" : "VEC3"
}
],
これのバッファへの格納法は次のように書かれているようです。
"bufferViews" : [
{
"buffer" : 0,
"byteLength" : 36,
"byteOffset" : 0,
"target" : 34963
},
{
"buffer" : 0,
"byteLength" : 288,
"byteOffset" : 36,
"target" : 34962
},
{
"buffer" : 0,
"byteLength" : 288,
"byteOffset" : 324,
"target" : 34962
}
],
"buffers" : [
{
"byteLength" : 612,
"uri" : "default_cube.bin"
}
],
.binファイルもわけられそうな雰囲気ですね。
ここから立体を出力しているのは
"meshes" : [
{
"name" : "Cube",
"primitives" : [
{
"attributes" : {
"NORMAL" : 2,
"POSITION" : 1
},
"indices" : 0,
"material" : 0
}
]
}
],
bufferView
のインデックスでしょうか。
ここで、気になるところがありますね。
バイナリファイルにアクセスするには格納方法がもっと詳細に記述されていないといけません。
具体的には、何バイトの、符号ありなしの、浮動小数点型もしくは整数型がわからなければ読めません。
それらしきものは、componentType
ですが、5121
と5126
とあります。
これだけだとわからないので困ったら公式を読みましょう。
5121 = UNSIGNED BYTE
,5126 = FLOAT
と出てきました。
ええ…
おわりに
COLLADAとの比較を通して見ましたが、
glTFはjsonで書かれている分すっきりしていて、表現の仕方もスマートだと感じました。
一方で、実用上はソフトの対応状況がネックになります。
現時点(2018.4)のblender最新版では、別途プラグインをインストールする必要がありました。