fix(usdc): decode integer-compressed float arrays#126
Merged
Conversation
`read_floats` treated the `i` (compressed-integers) branch of a float array's value rep as plain LZ4-compressed `i32`s and cast them straight to `f32`. Pixar's crateFile.cpp `_ReadCompressedInts` (see https://github.com/PixarAnimationStudios/OpenUSD/blob/release/pxr/usd/usd/crateFile.cpp) additionally runs the decompressed buffer through `Usd_IntegerCompression` decoding before returning the integers, because the `i` code is USD's compact encoding for arrays whose values happen to all be integral, not a marker for "raw i32 dump". Skipping that decode step silently produces garbage floats. This only reproduces when every element of a `float[]`/`double[]` array is an integral value (e.g. joint weights that are all `0.0`/`1.0`), which is exactly the case where the crate writer picks the `i` array encoding. A 16-element all-integral `float[]` written by `usdcat` decoded to values such as `269505630.0` and `-16646399.0` instead of the original `0.0`/`1.0` before this fix. Fix by routing the `i` branch through `read_encoded_ints`, the same Usd_IntegerCompression-aware decoder already used elsewhere in this file for token/path/spec integer sections, instead of the raw `read_compressed` LZ4-only path. Adds a regression fixture (`fixtures/integer_compressed_floats.usdc`, generated with upstream `usdcat` from the paired `.usda`) plus two tests: one exercising the fixture through the public field-reading API and one asserting the fixture actually triggers the `i` array-value-rep code path, so a future refactor can't silently drop coverage of this branch.
mxpv
force-pushed
the
fix/usdc-integer-compressed-floats
branch
from
July 23, 2026 03:45
77d7d80 to
c56469a
Compare
Owner
|
Thanks! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Hello! I’ve been following your progress over the past six months. Thank you for your excellent work—it has made it possible for me to incorporate it into my own projects as well.
I’m developing my own 3D model viewer, and I’d like to report a bug I found.
read_floatstreated thei(compressed-integers) branch of a float array's value rep as plain LZ4-compressedi32s and cast them straight tof32. Pixar's crateFile.cpp_ReadCompressedInts(see https://github.com/PixarAnimationStudios/OpenUSD/blob/release/pxr/usd/usd/crateFile.cpp) additionally runs the decompressed buffer throughUsd_IntegerCompressiondecoding before returning the integers, because theicode is USD's compact encoding for arrays whose values happen to all be integral, not a marker for "raw i32 dump". Skipping that decode step silently produces garbage floats.This only reproduces when every element of a
float[]/double[]array is an integral value (e.g. joint weights that are all0.0/1.0), which is exactly the case where the crate writer picks theiarray encoding. A 16-element all-integralfloat[]written byusdcatdecoded to values such as269505630.0and-16646399.0instead of the original0.0/1.0before this fix.Fix by routing the
ibranch throughread_encoded_ints, the same Usd_IntegerCompression-aware decoder already used elsewhere in this file for token/path/spec integer sections, instead of the rawread_compressedLZ4-only path.Adds a regression fixture (
fixtures/integer_compressed_floats.usdc, generated with upstreamusdcatfrom the paired.usda) plus two tests: one exercising the fixture through the public field-reading API and one asserting the fixture actually triggers theiarray-value-rep code path, so a future refactor can't silently drop coverage of this branch.