メインコンテンツまでスキップ

VRMフォーマット

VRM は、Khronos の開発している 3D Format である glTF の version 2.0 をベースにしています。

VRM file

VRM は、glTF の バイナリーバージョンである glb のファイル拡張子を .vrm に変更します。

.vrm.glb に戻すことで vrm 未対応の glTF 対応アプリケーションでも、3D Model としてロードできることが期待できます。

vrm-0.x

vrm-1.0

VRM と 並用することが想定される他の glTF extension

vrma

glb フォーマット概説

シーンヒエラルキーをJSONで記述するテキスト部と、画像や頂点配列を記録するバイナリ部の2つの部分からなります。

glTFヘッダ + JSON CHUNk + BINARY CHUNKという構成です。

glTFヘッダ部

長さ内容
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())