Skip to content

Add support for importing and exporting GLB version 3 files#905

Open
aaronfranke wants to merge 6 commits into
KhronosGroup:mainfrom
aaronfranke:support-glb3
Open

Add support for importing and exporting GLB version 3 files#905
aaronfranke wants to merge 6 commits into
KhronosGroup:mainfrom
aaronfranke:support-glb3

Conversation

@aaronfranke

@aaronfranke aaronfranke commented Jun 23, 2026

Copy link
Copy Markdown

This PR adds the ability for UnityGLTF to import and export 64-bit glTF binary format version 3 files. This GLB version 3 format is being defined as part of glTF 2.1, but the format itself is not tied to glTF 2.1: you can use a version 2 file to hold glTF 2.1 data, or use a version 3 file to hold glTF 2.0 data. It's this latter case which this PR supports. KhronosGroup/glTF#2594

This is not all of the changes to the .glb format that will be required for glTF 2.1. There will also be a more flexible chunk layout and support for multiple binary chunks. However, that will require changes to the parsing of the actual glTF JSON data as well, and that part has not yet been standardized, and I want to try and avoid sending in a massive unreviewable blob of all the changes all at once (this PR is already super big as it is), so I am submitting this PR to just add support for GLB version 3 with the same layout.

For easy reviewability, I split this PR into 6 commits. Let me know if you'd like me to open separate PRs for these:

  • Noisy whitespace-only changes

    • There were a lot of whitespace and formatting issues that hindered my ability to work, so I just fixed them and put all those fixes into a single commit. Not very interesting. No functional code changes.
  • Fix a lot of typos

    • There were a lot of typos inhibiting my ability to think clearly (meaning, they annoyed me), so I just fixed them and put all those fixes into a single commit. Almost no behavior changes, except a few things that would've caused compile errors were fixed (such as var vec in arr followed by vect.x, fixed to vec.x).
    • Some examples: childs -> children, remaks -> remarks, desintation -> destination, UNIYT -> UNITY.
  • Rename and relocate several things for clarity

    • Rename ChunkOffset to ChunkDataOffset to clarify that this points to the chunk's data, not the chunk header.
    • Rename ChunkFormat to GLBChunkFormat to clarify it's about GLB specifically.
    • Rename ChunkInfo to GLBChunkInfo to clarify it's about GLB specifically.
    • Move GLBChunkFormat, GLBHeader, and GLBChunkInfo to GLBObject.cs instead of GLBParser.cs.
    • Rename HEADER_SIZE to GLB2_FILE_HEADER_SIZE and move to GLBHeader.
    • Rename CHUNK_HEADER_SIZE to GLB2_CHUNK_HEADER_SIZE and move to GLBHeader.
    • Rename MAGIC_NUMBER to GLTF_MAGIC_NUMBER and move to GLBHeader and deduplicate with other cases of this magic number in 2 other places.
    • Rename local header variables to glbHeader to avoid confusion with the chunk header.
    • Rename ParseJsonChunk to ParseJsonChunkAndFileHeader because it does both of those things.
    • Rename SeekToBinaryChunk to SeekToBinaryChunkData because it seeks past the header.
    • Improve a bit of comments, docs, and exception text. Also each of the later commits improves comments too.
  • Upgrade data type for sizes, lengths, offsets, set to 64-bit long

    • With 64-bit sizes being possible to find in GLB version 3 files, and also text-based .gltf files even with glTF 2.0, we need to use 64-bit values for sizes.
    • The signed long type is preferred over the unsigned variant for general use for several reasons: alignment with C# Stream API, alignment with GLB version 3 having the most-significant bit of the size always zero, avoiding underflow with negative numbers and subtraction, and ability to use -1 as a sentinel value.
    • This commit adds ReadDoubleAsUInt64, adds GetUInt64, and adds a check to GetUInt32.
    • Also, I removed the default value of the pad argument of AlignToBoundary.
  • Support importing GLB version 3 files

    • This is the most interesting commit. Probably worth reading over the entire code, but I'll summarize here too.
    • Replace constants with functions on GLBHeader to allow the version to be taken into consideration.
    • Read different binary layouts depending on version 2 or version 3.
    • Read the chunk encoding field and throw an exception on unrecognized encodings with a friendly error message (I tested that this fails in the correct way with a Zstd-compressed file generated by Godot).
    • Fix the int binaryChunkIndex parameter in SeekToBinaryChunkData to actually use binary chunk indices, not buffer indices under the wrong name. Removed the TODO comment.
    • Some of the GLBObject code is kinda export-related, but I changed it in this commit anyway since it's tied in.
  • Support exporting GLB version 3 files

    • Change the write logic to use a GLBHeader and use its functions instead of constants.
    • Write different binary layouts depending on version 2 or version 3.
    • Automatically switch to version 3 if the file doesn't fit in version 2's limit.
    • I did not add any UI for forcing version 3, it'll use version 2 always unless trying to export a >4GiB file.

I tested both the import and export code with Unity 6000.5.0f1 on macOS. I tested importing test files generated by UnityGLTF, glTFast, and Godot Engine, and all work.

I made a similar PR to glTFast: Unity-Technologies/com.unity.cloud.gltfast#51

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant