OpenUSD icon indicating copy to clipboard operation
OpenUSD copied to clipboard

Autodesk: Enable MaterialX unit attributes in USD

Open erikaharrison-adsk opened this issue 1 year ago • 7 comments

Description of Change(s)

MaterialX spec allows nodes inputs to have a unittype and unit attribute that is converted to scene units at runtime. This workflow is crucial for many MFG and AEC workflows where textures have real world units applied.

These attributes were currently ignored by USD and Hydra. With this change, we capture the units information as USD's SdfDimension type. This allows us to consolidate unittype and unit attribute into one SdfDimension. e.g. unittype="distance" and unit="centimeter" becomes SdfLengthCentimeter enum. These are represented in USD as displayUnit

               def Shader "total_scale"
                {
                    uniform token info:id = "ND_multiply_vector2FA"
                    float2 inputs:in1 = (1, 1)
                    float inputs:in2 = 10 (
                        displayUnit = cm
                    )
                    float2 outputs:out
                }

Similar to colorspace, these attributes are encoded to Hydra and recomposed into MaterialX in Storm. Three unit tests are added to demonstrate the behavior.

Known limitations: 1- The scene unit space or target unit space is currently defined via an env var similar to other Mtlx options. e.g. PXR_MTLX_SCENE_UNIT=foot implies destination unit space is foot. The current USD metadata metersPerUnit is not used.

2 - Since MaterialX currently supports defining distance target unit space option, this PR only handles "distance" units.

Fixes Issue(s)

  • N/A
  • [X] I have verified that all unit tests pass with the proposed changes
  • [X] I have submitted a signed Contributor License Agreement

erikaharrison-adsk avatar Jun 21 '24 22:06 erikaharrison-adsk

Filed as internal issue #USD-9791

jesschimein avatar Jun 24 '24 16:06 jesschimein

/AzurePipelines run

jesschimein avatar Jun 24 '24 16:06 jesschimein

Azure Pipelines successfully started running 1 pipeline(s).

azure-pipelines[bot] avatar Jun 24 '24 16:06 azure-pipelines[bot]

Hi @ashwinbhat , awhile back we had discussed adding new namespaced inputs to the Mtlx Sdr node definitions where needed, when we need to encode per-property unit information. Not only are we wary of adding new metadata for every single shader input to need to query in Hydra (still concerned about colorSpace) for scalability reasons, but the SdfSchema's displayUnits field is not only one that we don't even actually have a legitimate use for in Presto AFAWK (it was a speculative thing from very early Presto design days, we think), and we'd actually like to deprecate it (it is not being added to the Core Specification). But even if it were, it is, as documented, only to be used for GUI presentation, not to encode anything intrinsic about the data.

What do you think: can we instead do something like:

               def Shader "total_scale"
                {
                    uniform token info:id = "ND_multiply_vector2FA"
                    float2 inputs:in1 = (1, 1)
                    float inputs:in2 = 10 
                    token inputs:in2:units = "cm"
                    float2 outputs:out
                }

spiffmon avatar Jun 26 '24 22:06 spiffmon

Hi @spiffmon thanks for the feedback. I'm happy to rework this. I recall the discussion adding new namespaced inputs to the Mtlx Sdr node definitions and we can certainly adopt your suggestion. Would you recommend doing this for colorSpace as well? I would prefer if colorspace and units were represented consistently. Regarding, SdfSchema's displayUnits I did not realize it will be removed. I like how it encodes the unit type and unit in one enum and thought it has more use then only for UI.

ashwinbhat avatar Jun 27 '24 16:06 ashwinbhat

Hi @klucknav @JGamache-autodesk and I were thinking about what might be the best way to represent the @spiffmon's proposed change in Storm?

float inputs:in2 = 10 
token inputs:in2:units = "cm"

In Storm would this still be represented as units:in2 similar to the current approach of capturing metadata? Similar to Colorspace, Units are not inputs

ashwinbhat avatar Jun 27 '24 21:06 ashwinbhat

Hi @spiffmon thanks for the feedback. I'm happy to rework this. I recall the discussion adding new namespaced inputs to the Mtlx Sdr node definitions and we can certainly adopt your suggestion. Would you recommend doing this for colorSpace as well? I would prefer if colorspace and units were represented consistently. Regarding, SdfSchema's displayUnits I did not realize it will be removed. I like how it encodes the unit type and unit in one enum and thought it has more use then only for UI.

I understand the desire for consistency, however, for better or worse (I won't weigh this thread down with justifications for now :-) ), USD has taken the position that colorSpace is acknowledged to potentially need to vary per-property in a scene, and therefore property metadata is the (many years-existing) preferred encoding.

For linear units, however, we expect documents to be internally consistent, with the prim-level corrections described in the recent layer metadata proposal providing a way to adapt referenced assets. We hope to propose a concrete GeomMetricsAPI within the next year...

Given that expectation, the hope for MaterialX documents would be that each document would contain a uniform equivalent of metersPerUnit for all floating point spatial data encoded in the document, and/or UsdMtlx would convert all such data into a single space. But understandably that still leaves (essentially) a scale-factor per external texture providing linear data that cannot be reasonably transformed. In theory, the unit/scale could be part of the basic Mtlx Image reader node definition... however, we would run into the need to have more than one such specification when building a NodeGraph that contains multiple texture readers, exposing the asset-paths as part of the NodeGraph interface, which then brings us back to the limited (to shading networks) need for expressing units at a granularity finer than per-prim.

Ideally the implementation will not depend on any env vars declaring units, and rather than needing to pass in a stage's metersPerUnit to UsdMtlx, we could accomplish the needed transformations by adding the forthcoming GeomMetricsAPI on each Material prim ... however, there's going to be a bit of stuff to work out there, since a) Material is not Xformable, we'll need to ensure Hydra notices and transmits the composed localToWorld that includes the Material's metrics and "does the right thing" with that information.

spiffmon avatar Jun 28 '24 00:06 spiffmon