About GLTF

2018-04-16 16:30:00 +0900 +0900
Last modified September 15, 2020: tags(unity, detail, api, gltf...) (cdaf1eb)

glTF is a 3D format created by Khronos Group, which is developing openGL specifications. glTF 2.0 was released in 2017. VRM is based on glTF 2.0.

What kind of information can be recorded by glTF?

  • Mesh (Vertex array、index array)
    • Morph target
    • Skinning (4weight)
  • Texture
  • Material (PBR)
  • Scene
  • Animation1
  • Camera1
  • Light source1

An entire 3D scene can be recorded.

  • OpenGL right-handed, Y-UP coordinate system
  • Meter (unit)
  • Little endian

glTF format outline

glTF format comprises two parts: a JSON scene description part and a binary part that records images and vertex arrays. External binary data can be accessed by referencing Url or path. For glb format, it combines a JSON part and a binary part into one file. The binary data can be accessed via the offset into the buffer (byteOffset). For a program, it is easier to handle the glb format which is no need to access external files2.

glb format

A structure that hasHeader part + Chunk parts. More specifically, it isHeader part + JSON CHUNk + BINARY CHUNK.

Header part

4glTF versionint322
4file sizeint32

Chunk part

4chunk sizeint32
4chunk typeascii“JSON” or “BIN\x00”
chunk sizechunk bodybyte array

Example of parsing with 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:

        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
            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())

VRM extension

Information of VRM extension is stored injson['extensions']['VRM'].

  1. Not supported in VRM ↩︎

  2. glb is adopted in VRM. ↩︎

VRM - humanoid 3d avatar format for VR