Skip to main content

glbフォーマット概説

JSON記述部と、画像や頂点配列を記録するバイナリ部の2つの部分からなります。

gltf形式では、URLやパスで参照する方法で外部のバイナリデータにアクセスします。 glb形式ではJSON部とバイナリ部をひとつのファイルにまとめていて、バイト列のオフセットでバイナリデータにアクセスします。 プログラムから扱うには外部ファイルへのアクセスが無いglb形式の方が簡単1です。

glb形式

ヘッダ部 + チャンク部繰り返しという構造になっています。 実質的には、 ヘッダ部 + JSON CHUNk + BINARY CHUNKとなります。

ヘッダ部

長さ内容
4ascii"glTF"
4gltfバージョンint322
4file sizeint32

チャンク部

長さ内容
4chunk sizeint32
4chunk typeascii"JSON" or "BIN\x00"
chunk sizechunk bodyバイト列

python3によるパース例

import struct
import json

class Reader:
def __init__(self, data: bytes)->None:
self.data = data
self.pos = 0

def read_str(self, size):
result = self.data[self.pos: self.pos + size]
self.pos += size
return result.strip()

def read(self, size):
result = self.data[self.pos: self.pos + size]
self.pos += size
return result

def read_uint(self):
result = struct.unpack('I', self.data[self.pos:self.pos + 4])[0]
self.pos += 4
return result


def parse_glb(data: bytes):
reader = Reader(data)
magic = reader.read_str(4)
if magic != b'glTF':
raise Exception(f'magic not found: #{magic}')

version = reader.read_uint()
if version != 2:
raise Exception(f'version:#{version} is not 2')

size = reader.read_uint()
size -= 12

json_str = None
body = None
while size > 0:
#print(size)

chunk_size = reader.read_uint()
size -= 4

chunk_type = reader.read_str(4)
size -= 4

chunk_data = reader.read(chunk_size)
size -= chunk_size

if chunk_type == b'BIN\x00':
body = chunk_data
elif chunk_type == b'JSON':
json_str = chunk_data
else:
raise Exception(f'unknown chunk_type: {chunk_type}')

return json.loads(json_str), body


with open('AliciaSolid.vrm', 'rb') as f:
parsed, body = parse_glb(f.read())

Footnotes

  1. VRMではglbを採用しています。