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. https://github.com/KhronosGroup/glTF/issues/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 arrfollowed byvect.x, fixed tovec.x). - Some examples:
childs->children,remaks->remarks,desintation->destination,UNIYT->UNITY.
- 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
Rename and relocate several things for clarity
- Rename
ChunkOffsettoChunkDataOffsetto clarify that this points to the chunk's data, not the chunk header. - Rename
ChunkFormattoGLBChunkFormatto clarify it's about GLB specifically. - Rename
ChunkInfotoGLBChunkInfoto clarify it's about GLB specifically. - Move
GLBChunkFormat,GLBHeader, andGLBChunkInfotoGLBObject.csinstead ofGLBParser.cs. - Rename
HEADER_SIZEtoGLB2_FILE_HEADER_SIZEand move toGLBHeader. - Rename
CHUNK_HEADER_SIZEtoGLB2_CHUNK_HEADER_SIZEand move toGLBHeader. - Rename
MAGIC_NUMBERtoGLTF_MAGIC_NUMBERand move toGLBHeaderand deduplicate with other cases of this magic number in 2 other places. - Rename local
headervariables toglbHeaderto avoid confusion with the chunk header. - Rename
ParseJsonChunktoParseJsonChunkAndFileHeaderbecause it does both of those things. - Rename
SeekToBinaryChunktoSeekToBinaryChunkDatabecause it seeks past the header. - Improve a bit of comments, docs, and exception text. Also each of the later commits improves comments too.
- Rename
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
.gltffiles even with glTF 2.0, we need to use 64-bit values for sizes. - The signed
longtype 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, addsGetUInt64, and adds a check toGetUInt32. - Also, I removed the default value of the pad argument of
AlignToBoundary.
- With 64-bit sizes being possible to find in GLB version 3 files, and also text-based
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
GLBHeaderto 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 binaryChunkIndexparameter inSeekToBinaryChunkDatato 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
GLBHeaderand 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.
- Change the write logic to use a
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: https://github.com/Unity-Technologies/com.unity.cloud.gltfast/pull/51