USD Export Precision: Why Are Translations Stored as Doubles but Rotations and Scales as Floats?

While exporting scenes from Maya to USD and loading the resulting USD files, I initially tested translations using double precision. However, when I started processing scale and rotation values, I realized that they were defined in single precision floating point rather than double, as was the case for translation values.

I did some research and noticed that even on the official USD pages, this distinction seems to be implicitly the case. For example:

float3 xformOp:rotateXYZ = (30, 60, 90)
float3 xformOp:scale = (2, 2, 2)
double3 xformOp:translate = (0, 100, 0)
double3 xformOp:translate:scalePivot
uniform token[] xformOpOrder = [ "xformOp:translate", "xformOp:rotateXYZ", "xformOp:translate:scalePivot", "xformOp:scale" ]

While I believe (I think I understand this correctly) that you can explicitly specify the precision in which an xformOp stores its values, it seems that USD defaults to double precision for translation values and single precision for scale and rotation when exporting data.

  1. Is this always the case? I’m not sure why there is a difference. Does anyone know? Can I assume this is a convention in USD?

  2. Is this configurable somewhere? Is there some kind of schema or setting that controls this behavior?

  3. And alternatively, while it makes no sense, would USD accept t/r/s values defined as something else than floating point precision? Like Vec3i? Would the specs allow it?

I believe (though I’m not entirely certain) that Maya uses double precision internally for translation, scale, and rotation. If that’s true, I’m unsure why USD doesn’t export all these values consistently—either all as float (for consistency with USD storage) or all as double (for consistency with Maya’s internal format).

I’m also slightly concerned about encountering a situation where this behavior changes unexpectedly—where suddenly all values might be floats, doubles, or some different configuration (e.g., rotation in double precision while the others remain in float).

We can handle these cases in our pipeline, but I’m curious if anyone has background knowledge on why USD handles it this way.

Many thanks!

Hi @msaintourens , the default precisions are not configurable, though as USD’s use expands into many domains outside M&E, that may make sense - though because the precisions are variable, we hope no consumers would be relying on a particular precision.

The current defaults came from trying to balance our experience of where precision was most needed in animation-scale world-building, vs scalability/bandwidth. Because environments can be very large, and sometimes desired to be located far from the origin, we find double-precision necessary. However, we have never encountered a scenario where single-precision scales or rotates were insufficient. It’s definitely a “Pixarism” in that way, though we have not heard of concrete problems folks have run into (which is not to say no-one has).

–spiff

1 Like

Thank you, Spiff. I really appreciate that you took the time to provide such a solid and informed answer. Many thanks.

I understand your argument; it makes sense. Interestingly, while experimenting with some files after posting my original message, I realized that USD doesn’t complain if the input types for translate aren’t double3, or if those for scale and rotate aren’t float3. In fact, it seems that as long as the input is a dimension-3 vector, no error is generated when the file is loaded.

Yes, the idea is that any xformOp (except xformOp:transform) can be in double, float, or half precision - the API defaults are just defaults.