Skip to content

fix(usdc): reorder quat bytes to match USDA convention#64

Merged
mxpv merged 4 commits intomxpv:mainfrom
bresilla:fix/usdc-quat-byte-order
May 3, 2026
Merged

fix(usdc): reorder quat bytes to match USDA convention#64
mxpv merged 4 commits intomxpv:mainfrom
bresilla:fix/usdc-quat-byte-order

Conversation

@bresilla
Copy link
Copy Markdown
Contributor

@bresilla bresilla commented May 1, 2026

Closes #63

usdc/reader.rs + usdc/writer.rs: when reading/writing Quath / Quatf / Quatd (single + array), reorder between the on-disk [x, y, z, w] (Pixar GfQuat memory layout) and the in-memory (w, x, y, z) convention that this crate's USDA parser already uses. After the patch all Value::Quat* values are in one convention regardless of source format, and Pixar-authored USDC files (Isaac Sim, Omniverse, anything saved by usdcat) load with rotations intact.

Background is in the linked issue. tl;dr: Pixar's GfQuat<T> is [imag, real] in memory and USDC bitwise-copies that, while USDA text + this crate's parser use (real, imag) order. Same Rust type, two conventions — the agilebot Isaac Sim robot was the canary that surfaced this.

Tests:

  • 3 test_read_quat_* had their expected arrays locked to the on-disk byte order — updated to the post-reorder values with a comment so it doesn't regress.
  • binary_writer_roundtrip keeps passing because reader + writer both reorder, so write → read is identity for Value::Quat*.

(First push had the writer untouched, which broke round-trip CI. Second commit applies the matching reorder to the writer.)

Copilot AI review requested due to automatic review settings May 1, 2026 21:50
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes quaternion component ordering inconsistencies between USDA and USDC so that Value::Quath/Quatf/Quatd are returned in a single consistent convention across formats (addressing #63).

Changes:

  • Reorders USDC quaternion scalar and array reads from on-disk [x, y, z, w] into (w, x, y, z) in the USDC reader.
  • Updates USDC reader tests’ expected quaternion values to match the normalized (w, x, y, z) convention and documents why.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
src/usdc/reader.rs Normalizes quaternion component ordering when decoding USDC quat values.
src/usdc/mod.rs Updates quat read tests to assert the normalized ordering and adds explanatory comments.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/usdc/reader.rs Outdated
Comment on lines +1054 to +1067
// Pixar's GfQuat<T> declares `_imaginary: GfVec3<T>` then
// `_real: T`, so on-disk bytes are `[imag_x, imag_y, imag_z,
// real]` = `[x, y, z, w]`. The USDA textual form is
// `(real, i, j, k)` = `(w, x, y, z)`, which the USDA parser
// stores verbatim. Reorder USDC bytes here so `Value::Quat*`
// values are consistently `(w, x, y, z)` regardless of source
// — without this, binary USDC quats from real production
// assets (Isaac Sim Agilebot, Omniverse robotics scenes)
// come out with axes scrambled.
Type::Quath if value.is_array() => Value::QuathVec(
self.read_vec_array::<f16, 4>(value)?
.into_iter()
.map(|q| [q[3], q[0], q[1], q[2]])
.collect(),
Comment thread src/usdc/reader.rs Outdated
Comment on lines +1063 to +1067
Type::Quath if value.is_array() => Value::QuathVec(
self.read_vec_array::<f16, 4>(value)?
.into_iter()
.map(|q| [q[3], q[0], q[1], q[2]])
.collect(),
Comment thread src/usdc/mod.rs
Comment on lines 270 to 283
#[test]
fn test_read_quat_floats() -> Result<()> {
let data = read_file("fixtures/fields.usdc")?;

let quat = data
.get(&sdf::path("/World.quatfSingle")?, "default")?
.into_owned()
.try_as_quatf()
.unwrap();

assert_eq!(quat, [2.9, 8.5, 4.6, 1.4]);
// USDC bytes are `[x, y, z, w]` (Pixar GfQuat layout); the
// reader reorders to `(w, x, y, z)` to match USDA convention.
assert_eq!(quat, [1.4, 2.9, 8.5, 4.6]);

bresilla and others added 3 commits May 1, 2026 23:54
Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
@mxpv
Copy link
Copy Markdown
Owner

mxpv commented May 3, 2026

Great find! Thanks!

@mxpv mxpv merged commit b74638e into mxpv:main May 3, 2026
5 checks passed
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.

USDC quat values come out with axes scrambled (byte-order mismatch with USDA)

3 participants