Merge pull request #3061 from LouRohanNV:fixUsdMaterialInterfaces
PiperOrigin-RevId: 868177637 Change-Id: I2de8f2af3b5fc126d103256b1ea00c5f8c7a8955
This commit is contained in:
@@ -15,6 +15,7 @@
|
|||||||
#include "material_parsing.h"
|
#include "material_parsing.h"
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <filesystem>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -24,15 +25,13 @@
|
|||||||
#include <pxr/base/tf/staticData.h>
|
#include <pxr/base/tf/staticData.h>
|
||||||
#include <pxr/base/tf/staticTokens.h>
|
#include <pxr/base/tf/staticTokens.h>
|
||||||
#include <pxr/base/tf/token.h>
|
#include <pxr/base/tf/token.h>
|
||||||
#include <pxr/usd/ar/asset.h>
|
|
||||||
#include <pxr/usd/ar/resolvedPath.h>
|
|
||||||
#include <pxr/usd/ar/resolver.h>
|
|
||||||
#include <pxr/usd/usd/prim.h>
|
#include <pxr/usd/usd/prim.h>
|
||||||
#include <pxr/usd/usdShade/input.h>
|
#include <pxr/usd/usdShade/input.h>
|
||||||
#include <pxr/usd/usdShade/material.h>
|
#include <pxr/usd/usdShade/material.h>
|
||||||
#include <pxr/usd/usdShade/shader.h>
|
#include <pxr/usd/usdShade/shader.h>
|
||||||
#include <pxr/usd/usdShade/types.h>
|
#include <pxr/usd/usdShade/types.h>
|
||||||
#include <pxr/usd/usdShade/udimUtils.h>
|
#include <pxr/usd/usdShade/udimUtils.h>
|
||||||
|
#include <pxr/usd/usdShade/utils.h>
|
||||||
|
|
||||||
// Using to satisfy TF_DEFINE_PRIVATE_TOKENS macro below and avoid operating in
|
// Using to satisfy TF_DEFINE_PRIVATE_TOKENS macro below and avoid operating in
|
||||||
// PXR_NS.
|
// PXR_NS.
|
||||||
@@ -119,69 +118,59 @@ ResolvedShaderInput<T> ReadUsdUVTexture(mjSpec* spec,
|
|||||||
texture->colorspace = mjtColorSpace::mjCOLORSPACE_AUTO;
|
texture->colorspace = mjtColorSpace::mjCOLORSPACE_AUTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
pxr::ArResolver& resolver = pxr::ArGetResolver();
|
|
||||||
pxr::SdfAssetPath resolved_texture_asset_path;
|
pxr::SdfAssetPath resolved_texture_asset_path;
|
||||||
|
|
||||||
if (auto file_input = shader.GetInput(kTokens->file)) {
|
if (auto file_input = shader.GetInput(kTokens->file)) {
|
||||||
file_input.Get(&resolved_texture_asset_path);
|
// Use GetValueProducingAttributes to follow all connections including
|
||||||
|
// material interfaces.
|
||||||
|
auto value_attrs =
|
||||||
|
pxr::UsdShadeUtils::GetValueProducingAttributes(file_input);
|
||||||
|
for (const auto& attr : value_attrs) {
|
||||||
|
if (attr.Get(&resolved_texture_asset_path) &&
|
||||||
|
!resolved_texture_asset_path.GetAssetPath().empty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
mju_error("UsdUVTexture missing inputs:file.");
|
mju_error("UsdUVTexture missing inputs:file.");
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string resolved_texture_path =
|
// Use the resolved path from USD, fall back to asset path if not resolved
|
||||||
resolved_texture_asset_path.GetResolvedPath();
|
std::string resolved_path_str = resolved_texture_asset_path.GetResolvedPath();
|
||||||
|
if (resolved_path_str.empty()) {
|
||||||
|
resolved_path_str = resolved_texture_asset_path.GetAssetPath();
|
||||||
|
}
|
||||||
|
|
||||||
if (pxr::UsdShadeUdimUtils::IsUdimIdentifier(resolved_texture_path)) {
|
if (resolved_path_str.empty()) {
|
||||||
|
mju_warning("UsdUVTexture %s: No texture file path specified.",
|
||||||
|
shader.GetPath().GetAsString().c_str());
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pxr::UsdShadeUdimUtils::IsUdimIdentifier(resolved_path_str)) {
|
||||||
mju_error("MuJoCo does not support UDIM textures: %s",
|
mju_error("MuJoCo does not support UDIM textures: %s",
|
||||||
resolved_texture_path.c_str());
|
resolved_path_str.c_str());
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto extension = resolver.GetExtension(resolved_texture_path);
|
if (!std::filesystem::exists(resolved_path_str)) {
|
||||||
|
mju_warning(
|
||||||
FILE* fp = fopen(resolved_texture_path.c_str(), "r");
|
|
||||||
if (fp == nullptr) {
|
|
||||||
mju_error(
|
|
||||||
"USD decoder only supports assets that are available on the file "
|
"USD decoder only supports assets that are available on the file "
|
||||||
"system");
|
"system. Could not open: %s",
|
||||||
|
resolved_path_str.c_str());
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
texture->nchannel = nchannels;
|
texture->nchannel = nchannels;
|
||||||
mjs_setString(texture->file, resolved_texture_path.c_str());
|
mjs_setString(texture->file, resolved_path_str.c_str());
|
||||||
out.sampler = texture;
|
out.sampler = texture;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Given an input to a shader, attempts to bake the shader and it's inputs
|
|
||||||
// into a singular value or texture sampler (ResolvedShaderInput).
|
|
||||||
template <typename T>
|
|
||||||
ResolvedShaderInput<T> ReadShaderInput(
|
|
||||||
mjSpec* spec, const pxr::UsdShadeConnectableAPI source,
|
|
||||||
const pxr::TfToken source_name,
|
|
||||||
const pxr::UsdShadeAttributeType source_type) {
|
|
||||||
ResolvedShaderInput<T> out;
|
|
||||||
pxr::UsdShadeShader shader(source.GetPrim());
|
|
||||||
pxr::TfToken shader_id = GetShaderId(shader);
|
|
||||||
if (shader_id == kTokens->UsdUVTexture) {
|
|
||||||
unsigned nchannels = -1;
|
|
||||||
if (source_name == kTokens->rgb) {
|
|
||||||
nchannels = 3;
|
|
||||||
} else if (source_name == kTokens->r) {
|
|
||||||
nchannels = 1;
|
|
||||||
} else {
|
|
||||||
mju_error("Unsupported texture channel: %s", source_name.GetText());
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ReadUsdUVTexture<T>(spec, shader, nchannels);
|
|
||||||
} else {
|
|
||||||
mju_warning("Unsupported shader type: %s", shader_id.GetText());
|
|
||||||
}
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reads UsdShadeInput as a value of type T or a texture sampler.
|
// Reads UsdShadeInput as a value of type T or a texture sampler.
|
||||||
|
// Uses GetValueProducingAttributes to follow all connections including
|
||||||
|
// material interfaces.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
ResolvedShaderInput<T> ReadShaderInput(mjSpec* spec, pxr::UsdShadeInput input) {
|
ResolvedShaderInput<T> ReadShaderInput(mjSpec* spec, pxr::UsdShadeInput input) {
|
||||||
ResolvedShaderInput<T> out;
|
ResolvedShaderInput<T> out;
|
||||||
@@ -189,14 +178,44 @@ ResolvedShaderInput<T> ReadShaderInput(mjSpec* spec, pxr::UsdShadeInput input) {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
pxr::UsdShadeConnectableAPI source;
|
// GetValueProducingAttributes follows connections recursively, including
|
||||||
pxr::TfToken source_name;
|
// through material interfaces, and returns the attributes that produce
|
||||||
pxr::UsdShadeAttributeType source_type;
|
// values.
|
||||||
if (input.GetConnectedSource(&source, &source_name, &source_type)) {
|
auto value_attrs = pxr::UsdShadeUtils::GetValueProducingAttributes(input);
|
||||||
out = ReadShaderInput<T>(spec, source, source_name, source_type);
|
|
||||||
} else {
|
for (const auto& attr : value_attrs) {
|
||||||
out.value = ReadInput<T>(input);
|
// Check if this attribute belongs to a UsdUVTexture shader (for textures)
|
||||||
|
pxr::UsdPrim prim = attr.GetPrim();
|
||||||
|
pxr::UsdShadeShader shader(prim);
|
||||||
|
if (shader) {
|
||||||
|
pxr::TfToken shader_id = GetShaderId(shader);
|
||||||
|
if (shader_id == kTokens->UsdUVTexture) {
|
||||||
|
// Determine channel count from the output name
|
||||||
|
pxr::TfToken attr_name = attr.GetBaseName();
|
||||||
|
unsigned nchannels = 3; // default
|
||||||
|
if (attr_name == kTokens->rgb) {
|
||||||
|
nchannels = 3;
|
||||||
|
} else if (attr_name == kTokens->r) {
|
||||||
|
nchannels = 1;
|
||||||
|
}
|
||||||
|
out = ReadUsdUVTexture<T>(spec, shader, nchannels);
|
||||||
|
if (out.sampler.has_value()) {
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// For other shader types, fall through to try reading as a value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to read as a direct value
|
||||||
|
out.value = ReadInput<T>(pxr::UsdShadeInput(attr));
|
||||||
|
if (out.value.has_value()) {
|
||||||
|
return out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If no value-producing attributes found, try reading the input directly
|
||||||
|
// (for non-connected inputs with authored values)
|
||||||
|
out.value = ReadInput<T>(input);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user