Usdstitch attribute interpolation bug?

Hello USD people,

We have run into what seems like should be a simple issue when using usdstitch to combine the animated output from several individual usd files, each exported from maya over a series of consecutive frame ranges. It appears to be related to the export process authoring the time-sampled attributes with the sparse attribute value writer to eliminate any redundant time-samples where the values do not change. The problem occurs when the last sample written into one of the frame range batches is NOT on the last frame in the batch (meaning that the attribute value remains constant for several frames at the end of that batch), BUT the first frame of the following batch has a different value. In this case, the value of the attribute in the usdstitch output is interpolated incorrectly from the last sample (NOT the last frame) in the previous batch to the new value in the following batch, which does not match the original animated values.

Is this the expected behaviour for usdstitch? There is nothing in the docs that suggest any limitation relating to using sparse time-sampled attribute values in the input files – and in fact, this is more a natural consequence of the standard attribute interpolation logic itself.

It is of course possible to imagine a number of potential workarounds to deal with this situation, but I’m not sure it makes sense for us to do so if it were able to be handled correctly by usdstitch out of the box. I’m curious to hear whether anyone else has encountered this problem and whether this is something we might expect to see a fix for at some point.

Hi @ocastle ,
Good catch, I think your expectation is correct, and it is the behavior you would get if you used usdstichclips to alternately generate a clipSet instead of usdstitch (unless you used the optional interpolateMissingClipValues feature). There are questions of where exactly the switch should happen (i.e. previous frame to next layer in sequence, or firstFrame - epsilon of next layer?), but we can follow whatever we’re doing when we flatten value clips onto a stage.

We also need to update usdstitch to support splines; not sure when exactly the fix you’re looking for would land yet, but we’re in agreement the behavior should change.

An expectations note: today usdstitch does not really adhere to a notion of one layer/clip ending and another beginning, i.e. where the boundaries are. It just keeps taking samples from earlier layers in the sequence until they run out, and then moves on to the next (I think).

To make this work reasonably, I think we’ll need to make it aware of boundaries, as value clips do. The obvious/easy choice is to make it only consume data from within each layer’s startTimeCode/endTimeCode range, as that’s the playback range you’d get in usdview when viewing each layer independently. If ranges overlap, earlier clip’s data “wins”, as is the program’s current behavior for overlaps.

If more flexibillity is needed, we’d be getting into the same specification-space as what goes into Value Clips’s clipSet metadata.

… and after examining current code usage, also need to state that:

  • usdstitch is built atop UsdUtilsStitchLayers, and would make use of its “advanced” stitchValueFn form to make these behavior changes.
  • However, Solaris, MayaUSD, and internal code both here and at WDAS instead make direct use of UsdUtilsStitchLayers…

So client code will need to be updated to call augmented API’s to get the new behavior, and to protect existing clients we may want to deploy the behavior even in usdstitch itself with a new command-line arg.

Hi @spiff,

Thanks for considering this as something that could be fixed internally in USD – please let me know if there is there an issue for this we can track from our end, it would be good to understand where this fits in your development priorities and when we might reasonably expect an update to be released.

Following up on this, I have put together a candidate fix in this branch which adds a new command-line option to usdstitch that implements a workaround for this problem directly in UsdUtilsStitchLayers itself.

Setting this new option ensures that all time-sampled attributes in each input layer have a sample value explicitly authored for the layer endTimeCode. If none is found, we explicitly author a new time-sample at this timecode with a value matching the preceding time-sample, the idea being that this acts as a placeholder that prevents the unwanted premature interpolation observed in the original bug report. This relies on the following assumptions:

  1. all time-sampled attributes in the layer are authored using the SparseAttrValueWriter
  2. the last timecode set using the SparseAttrValueWriter on each time-sampled attribute is known (and here is equal to the endTimeCode metadata on the layer)

While these assumptions are valid with the version of the usd_maya exporter we are using today, it is not clear whether they are likely to be robust in a wider context. In particular, there is no way to tell whether a given attribute has been authored using the SparseAttrValueWriter, while the USD user guide indicates that the timecode range is intended primarily as a guide for application UI purposes rather than as any kind of promise about the time-sampled content authored in the layer.

For these reasons, I have been exploring alternative approaches that allow us to validate these assumptions internally (or avoid them entirely). The most promising alternative is to essentially migrate the workaround outlined above to the exporter logic itself – in usd_maya, all time-sampled attributes use the SparseAttrValueWriter and the authored timecode range is known explicitly internally, satisfying both assumptions identified above. A candidate change for this is implemented in this branch.

The other advantage of this alternative approach is that no changes to UsdUtilsStitchLayers or usdstitch are necessary at all, which keeps it independent of existing pipelines that take advantage of the “advanced” custom stitchValueFn.

Any thoughts @spiff?