Skip to content

Commit 7ef3ae6

Browse files
Merge pull request #3061 from LouRohanNV:fixUsdMaterialInterfaces
PiperOrigin-RevId: 868177637 Change-Id: I2de8f2af3b5fc126d103256b1ea00c5f8c7a8955
2 parents 4fa062c + c6e982c commit 7ef3ae6

File tree

1 file changed

+71
-52
lines changed

1 file changed

+71
-52
lines changed

plugin/usd_decoder/material_parsing.cc

Lines changed: 71 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "material_parsing.h"
1616

1717
#include <cstdio>
18+
#include <filesystem>
1819
#include <optional>
1920
#include <string>
2021

@@ -24,15 +25,13 @@
2425
#include <pxr/base/tf/staticData.h>
2526
#include <pxr/base/tf/staticTokens.h>
2627
#include <pxr/base/tf/token.h>
27-
#include <pxr/usd/ar/asset.h>
28-
#include <pxr/usd/ar/resolvedPath.h>
29-
#include <pxr/usd/ar/resolver.h>
3028
#include <pxr/usd/usd/prim.h>
3129
#include <pxr/usd/usdShade/input.h>
3230
#include <pxr/usd/usdShade/material.h>
3331
#include <pxr/usd/usdShade/shader.h>
3432
#include <pxr/usd/usdShade/types.h>
3533
#include <pxr/usd/usdShade/udimUtils.h>
34+
#include <pxr/usd/usdShade/utils.h>
3635

3736
// Using to satisfy TF_DEFINE_PRIVATE_TOKENS macro below and avoid operating in
3837
// PXR_NS.
@@ -119,84 +118,104 @@ ResolvedShaderInput<T> ReadUsdUVTexture(mjSpec* spec,
119118
texture->colorspace = mjtColorSpace::mjCOLORSPACE_AUTO;
120119
}
121120

122-
pxr::ArResolver& resolver = pxr::ArGetResolver();
123121
pxr::SdfAssetPath resolved_texture_asset_path;
122+
124123
if (auto file_input = shader.GetInput(kTokens->file)) {
125-
file_input.Get(&resolved_texture_asset_path);
124+
// Use GetValueProducingAttributes to follow all connections including
125+
// material interfaces.
126+
auto value_attrs =
127+
pxr::UsdShadeUtils::GetValueProducingAttributes(file_input);
128+
for (const auto& attr : value_attrs) {
129+
if (attr.Get(&resolved_texture_asset_path) &&
130+
!resolved_texture_asset_path.GetAssetPath().empty()) {
131+
break;
132+
}
133+
}
126134
} else {
127135
mju_error("UsdUVTexture missing inputs:file.");
128136
return out;
129137
}
130138

131-
std::string resolved_texture_path =
132-
resolved_texture_asset_path.GetResolvedPath();
139+
// Use the resolved path from USD, fall back to asset path if not resolved
140+
std::string resolved_path_str = resolved_texture_asset_path.GetResolvedPath();
141+
if (resolved_path_str.empty()) {
142+
resolved_path_str = resolved_texture_asset_path.GetAssetPath();
143+
}
133144

134-
if (pxr::UsdShadeUdimUtils::IsUdimIdentifier(resolved_texture_path)) {
135-
mju_error("MuJoCo does not support UDIM textures: %s",
136-
resolved_texture_path.c_str());
145+
if (resolved_path_str.empty()) {
146+
mju_warning("UsdUVTexture %s: No texture file path specified.",
147+
shader.GetPath().GetAsString().c_str());
137148
return out;
138149
}
139150

140-
auto extension = resolver.GetExtension(resolved_texture_path);
151+
if (pxr::UsdShadeUdimUtils::IsUdimIdentifier(resolved_path_str)) {
152+
mju_error("MuJoCo does not support UDIM textures: %s",
153+
resolved_path_str.c_str());
154+
return out;
155+
}
141156

142-
FILE* fp = fopen(resolved_texture_path.c_str(), "r");
143-
if (fp == nullptr) {
144-
mju_error(
157+
if (!std::filesystem::exists(resolved_path_str)) {
158+
mju_warning(
145159
"USD decoder only supports assets that are available on the file "
146-
"system");
160+
"system. Could not open: %s",
161+
resolved_path_str.c_str());
147162
return out;
148163
}
164+
149165
texture->nchannel = nchannels;
150-
mjs_setString(texture->file, resolved_texture_path.c_str());
166+
mjs_setString(texture->file, resolved_path_str.c_str());
151167
out.sampler = texture;
152168
return out;
153169
}
154170

155-
// Given an input to a shader, attempts to bake the shader and it's inputs
156-
// into a singular value or texture sampler (ResolvedShaderInput).
157-
template <typename T>
158-
ResolvedShaderInput<T> ReadShaderInput(
159-
mjSpec* spec, const pxr::UsdShadeConnectableAPI source,
160-
const pxr::TfToken source_name,
161-
const pxr::UsdShadeAttributeType source_type) {
162-
ResolvedShaderInput<T> out;
163-
pxr::UsdShadeShader shader(source.GetPrim());
164-
pxr::TfToken shader_id = GetShaderId(shader);
165-
if (shader_id == kTokens->UsdUVTexture) {
166-
unsigned nchannels = -1;
167-
if (source_name == kTokens->rgb) {
168-
nchannels = 3;
169-
} else if (source_name == kTokens->r) {
170-
nchannels = 1;
171-
} else {
172-
mju_error("Unsupported texture channel: %s", source_name.GetText());
173-
return out;
174-
}
175-
176-
return ReadUsdUVTexture<T>(spec, shader, nchannels);
177-
} else {
178-
mju_warning("Unsupported shader type: %s", shader_id.GetText());
179-
}
180-
181-
return out;
182-
}
183-
184171
// Reads UsdShadeInput as a value of type T or a texture sampler.
172+
// Uses GetValueProducingAttributes to follow all connections including
173+
// material interfaces.
185174
template <typename T>
186175
ResolvedShaderInput<T> ReadShaderInput(mjSpec* spec, pxr::UsdShadeInput input) {
187176
ResolvedShaderInput<T> out;
188177
if (!input.GetPrim().IsValid()) {
189178
return out;
190179
}
191180

192-
pxr::UsdShadeConnectableAPI source;
193-
pxr::TfToken source_name;
194-
pxr::UsdShadeAttributeType source_type;
195-
if (input.GetConnectedSource(&source, &source_name, &source_type)) {
196-
out = ReadShaderInput<T>(spec, source, source_name, source_type);
197-
} else {
198-
out.value = ReadInput<T>(input);
181+
// GetValueProducingAttributes follows connections recursively, including
182+
// through material interfaces, and returns the attributes that produce
183+
// values.
184+
auto value_attrs = pxr::UsdShadeUtils::GetValueProducingAttributes(input);
185+
186+
for (const auto& attr : value_attrs) {
187+
// Check if this attribute belongs to a UsdUVTexture shader (for textures)
188+
pxr::UsdPrim prim = attr.GetPrim();
189+
pxr::UsdShadeShader shader(prim);
190+
if (shader) {
191+
pxr::TfToken shader_id = GetShaderId(shader);
192+
if (shader_id == kTokens->UsdUVTexture) {
193+
// Determine channel count from the output name
194+
pxr::TfToken attr_name = attr.GetBaseName();
195+
unsigned nchannels = 3; // default
196+
if (attr_name == kTokens->rgb) {
197+
nchannels = 3;
198+
} else if (attr_name == kTokens->r) {
199+
nchannels = 1;
200+
}
201+
out = ReadUsdUVTexture<T>(spec, shader, nchannels);
202+
if (out.sampler.has_value()) {
203+
return out;
204+
}
205+
}
206+
// For other shader types, fall through to try reading as a value
207+
}
208+
209+
// Try to read as a direct value
210+
out.value = ReadInput<T>(pxr::UsdShadeInput(attr));
211+
if (out.value.has_value()) {
212+
return out;
213+
}
199214
}
215+
216+
// If no value-producing attributes found, try reading the input directly
217+
// (for non-connected inputs with authored values)
218+
out.value = ReadInput<T>(input);
200219
return out;
201220
}
202221

0 commit comments

Comments
 (0)