Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MAYA-114979 MAYA-114731 Fix correctness issues #1937

Merged
merged 3 commits into from
Jan 3, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 22 additions & 13 deletions lib/mayaUsd/fileio/shading/shadingModeExporterContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ TF_DEFINE_PRIVATE_TOKENS(
(volumeShader)
(displacementShader)
(varname)
(varnameStr)
(map1)
);
// clang-format on
Expand Down Expand Up @@ -480,8 +481,8 @@ UsdPrim UsdMayaShadingModeExportContext::MakeStandardMaterialPrim(
}

namespace {
/// We can have multiple mesh with differing UV channel names and we need to make sure the
/// exported material has varname inputs that match the texcoords exported by the shape
/// We can have multiple mesh with differing UV channel names and we need to make sure the exported
/// material has varname or varnameStr inputs that match the texcoords exported by the shape
class _UVMappingManager
{
public:
Expand All @@ -496,6 +497,7 @@ class _UVMappingManager
// shader nodes contained in the material that have UV inputs that requires mapping:
//
// token inputs:node_with_uv_input:varname = "st"
// string inputs:node_with_uv_input:varnameStr = "st"
//
// The "node_with_uv_input" is a dependency node which is a valid target for the Maya
// "uvLink" command, which describes UV linkage for all shapes in the scene that reference
Expand All @@ -506,7 +508,8 @@ class _UVMappingManager
for (const UsdShadeInput& input : material.GetInputs()) {
const UsdAttribute& usdAttr = input.GetAttr();
std::vector<std::string> splitName = usdAttr.SplitName();
if (splitName.back() != _tokens->varname.GetString()) {
if (splitName.back() != _tokens->varname.GetString()
&& splitName.back() != _tokens->varnameStr.GetString()) {
continue;
}

Expand Down Expand Up @@ -602,13 +605,17 @@ class _UVMappingManager
TfTokenVector::const_iterator itNode = _nodesWithUVInput.cbegin();
TfTokenVector::const_iterator itName = largestSet.cbegin();
for (; itNode != _nodesWithUVInput.cend(); ++itNode, ++itName) {
TfToken inputName(
TfStringPrintf("%s:%s", itNode->GetText(), _tokens->varname.GetText()));
UsdShadeInput materialInput = material.GetInput(inputName);
TF_VERIFY(itName != largestSet.cend());
if (materialInput.GetTypeName() == SdfValueTypeNames->Token) {
std::string inputName(
TfStringPrintf("%s:%s", itNode->GetText(), _tokens->varname.GetText()));
UsdShadeInput materialInput = material.GetInput(TfToken(inputName.c_str()));
if (materialInput) {
materialInput.Set(*itName);
} else if (materialInput.GetTypeName() == SdfValueTypeNames->String) {
}
inputName
= TfStringPrintf("%s:%s", itNode->GetText(), _tokens->varnameStr.GetText());
materialInput = material.GetInput(TfToken(inputName.c_str()));
if (materialInput) {
materialInput.Set((*itName).GetString());
}
}
Expand Down Expand Up @@ -649,13 +656,15 @@ class _UVMappingManager
TfTokenVector::const_iterator itNode = _nodesWithUVInput.cbegin();
TfTokenVector::const_iterator itName = uvNames.cbegin();
for (; itNode != _nodesWithUVInput.cend(); ++itNode, ++itName) {
TfToken inputName(
std::string inputName(
TfStringPrintf("%s:%s", itNode->GetText(), _tokens->varname.GetText()));
UsdShadeInput materialInput
= newMaterial.CreateInput(inputName, SdfValueTypeNames->Token);
if (materialInput.GetTypeName() == SdfValueTypeNames->Token) {
UsdShadeInput materialInput = newMaterial.GetInput(TfToken(inputName.c_str()));
if (materialInput) {
materialInput.Set(*itName);
} else if (materialInput.GetTypeName() == SdfValueTypeNames->String) {
}
inputName = TfStringPrintf("%s:%s", itNode->GetText(), _tokens->varnameStr.GetText());
materialInput = newMaterial.GetInput(TfToken(inputName.c_str()));
if (materialInput) {
materialInput.Set((*itName).GetString());
}
}
Expand Down
12 changes: 12 additions & 0 deletions lib/mayaUsd/fileio/shading/shadingModeUseRegistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,9 @@ class UseRegistryShadingModeExporter : public UsdMayaShadingModeExporter
if (context.GetExportArgs().allMaterialConversions.size() > 1) {
// Write each material in its own scope
materialExportPath = materialExportPath.AppendChild(currentMaterialConversion);

// This path needs to be a NodeGraph:
UsdShadeNodeGraph::Define(context.GetUsdStage(), materialExportPath);
}

UsdShadeShader surfaceShaderSchema = _ExportShadingDepGraph(
Expand All @@ -364,6 +367,15 @@ class UseRegistryShadingModeExporter : public UsdMayaShadingModeExporter
materialExportPath, context.GetDisplacementShaderPlug(), context);
UsdMayaShadingUtil::CreateShaderOutputAndConnectMaterial(
displacementShaderSchema, material, UsdShadeTokens->displacement, renderContext);

// Clean-up nodegraph if nothing was exported:
if (context.GetExportArgs().allMaterialConversions.size() > 1) {
UsdPrim nodeGraphPrim(context.GetUsdStage()->GetPrimAtPath(materialExportPath));

if (nodeGraphPrim.GetAllChildren().empty()) {
context.GetUsdStage()->RemovePrim(materialExportPath);
}
}
}
context.BindStandardMaterialPrim(materialPrim, assignments, boundPrimPaths);
}
Expand Down
12 changes: 8 additions & 4 deletions lib/mayaUsd/fileio/translators/translatorMaterial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ TF_DEFINE_PRIVATE_TOKENS(

(inputs)
(varname)
(varnameStr)
);
// clang-format on

Expand Down Expand Up @@ -101,14 +102,15 @@ bool _IsMergeableMaterial(const UsdShadeMaterial& shadeMaterial)
return false;
}

// Check that the only properties authored are varname inputs.
// Check that the only properties authored are varname and varnameStr inputs.
for (const SdfPropertySpecHandle& propSpec : primSpec->GetProperties()) {
const SdfPath propPath = propSpec->GetPath();

const std::vector<std::string> splitName = SdfPath::TokenizeIdentifier(propPath.GetName());
// We allow only ["inputs", "<texture_name>", "varname"]
// We allow only ["inputs", "<texture_name>", "varname" or "varnameStr"]
if (splitName.size() != 3u || splitName[0u] != _tokens->inputs.GetString()
|| splitName[2u] != _tokens->varname.GetString()) {
|| (splitName[2u] != _tokens->varname.GetString()
&& splitName[2u] != _tokens->varnameStr.GetString())) {
return false;
}
}
Expand Down Expand Up @@ -178,7 +180,9 @@ _GetUVBindingsFromMaterial(const UsdShadeMaterial& material, UsdMayaPrimReaderCo
for (const UsdShadeInput& input : material.GetInputs()) {
const UsdAttribute& usdAttr = input.GetAttr();
std::vector<std::string> splitName = usdAttr.SplitName();
if (splitName.size() != 3 || splitName[2] != _tokens->varname.GetString()) {
if (splitName.size() != 3
|| (splitName[2] != _tokens->varname.GetString()
&& splitName[2] != _tokens->varnameStr.GetString())) {
continue;
}
VtValue val;
Expand Down
13 changes: 12 additions & 1 deletion lib/mayaUsd/fileio/utils/shadingUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,18 @@ UsdShadeOutput UsdMayaShadingUtil::CreateShaderOutputAndConnectMaterial(

UsdShadeOutput shaderOutput = shader.CreateOutput(terminalName, materialOutput.GetTypeName());

materialOutput.ConnectToSource(shaderOutput);
UsdPrim parentPrim = shader.GetPrim().GetParent();
if (parentPrim == material.GetPrim()) {
materialOutput.ConnectToSource(shaderOutput);
} else {
// If the surface is inside a multi-material node graph, then we must create an intermediate
// output on the NodeGraph
UsdShadeNodeGraph parentNodeGraph(parentPrim);
UsdShadeOutput parentOutput
= parentNodeGraph.CreateOutput(terminalName, materialOutput.GetTypeName());
parentOutput.ConnectToSource(shaderOutput);
materialOutput.ConnectToSource(parentOutput);
}

return shaderOutput;
}
Expand Down
120 changes: 84 additions & 36 deletions lib/usd/translators/shading/mtlxFileTextureWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ class MtlxUsd_FileWriter : public MtlxUsd_BaseWriter
const SdfValueTypeName& typeName) override;

private:
SdfPath _GetPlace2DTexturePath(const MFnDependencyNode& depNodeFn);

int _numChannels = 4;
};

Expand All @@ -80,8 +82,8 @@ PXRUSDMAYA_REGISTER_SHADER_WRITER(file, MtlxUsd_FileWriter);
TF_DEFINE_PRIVATE_TOKENS(
_tokens,

// Prefix for helper nodes:
((PrimvarReaderPrefix, "MayaGeomPropValue"))
// Shared primvar writer (when no place2dTexture found):
((PrimvarReaderShaderName, "shared_MayaGeomPropValue"))
);
// clang-format on

Expand Down Expand Up @@ -148,45 +150,67 @@ MtlxUsd_FileWriter::MtlxUsd_FileWriter(
}

// Now create a geompropvalue reader that the image shader will use.
TfToken primvarReaderName(
TfStringPrintf("%s_%s", _tokens->PrimvarReaderPrefix.GetText(), depNodeFn.name().asChar()));
const SdfPath primvarReaderPath = nodegraphPath.AppendChild(primvarReaderName);
UsdShadeShader primvarReaderSchema = UsdShadeShader::Define(GetUsdStage(), primvarReaderPath);

primvarReaderSchema.CreateIdAttr(VtValue(TrMtlxTokens->ND_geompropvalue_vector2));

UsdShadeInput varnameInput
= primvarReaderSchema.CreateInput(TrMtlxTokens->geomprop, SdfValueTypeNames->String);

// We expose the primvar reader varname attribute to the material to allow
// easy specialization based on UV mappings to geometries:
SdfPath materialPath = GetUsdPath().GetParentPath();
UsdShadeMaterial materialSchema(GetUsdStage()->GetPrimAtPath(materialPath));
while (!materialSchema && !materialPath.IsEmpty()) {
materialPath = materialPath.GetParentPath();
materialSchema = UsdShadeMaterial(GetUsdStage()->GetPrimAtPath(materialPath));
}
SdfPath primvarReaderPath = _GetPlace2DTexturePath(depNodeFn);

if (!GetUsdStage()->GetPrimAtPath(primvarReaderPath)) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly indentation since we now detect shared place2dTexture nodes. Similar to what was done in usdFileTextureWriter.cpp in the first PR of the series.

UsdShadeShader primvarReaderSchema
= UsdShadeShader::Define(GetUsdStage(), primvarReaderPath);
primvarReaderSchema.CreateIdAttr(VtValue(TrMtlxTokens->ND_geompropvalue_vector2));
UsdShadeInput varnameInput
= primvarReaderSchema.CreateInput(TrMtlxTokens->geomprop, SdfValueTypeNames->String);

if (materialSchema) {
TfToken inputName(
TfStringPrintf("%s:%s", depNodeFn.name().asChar(), TrUsdTokens->varname.GetText()));
UsdShadeInput materialInput
= materialSchema.CreateInput(inputName, SdfValueTypeNames->String);
materialInput.Set(UsdUtilsGetPrimaryUVSetName().GetString());
varnameInput.ConnectToSource(materialInput);
} else {
varnameInput.Set(UsdUtilsGetPrimaryUVSetName());
}
TfStringPrintf("%s:%s", depNodeFn.name().asChar(), TrMtlxTokens->varnameStr.GetText()));

// We expose the primvar reader varnameStr attribute to the material to allow
// easy specialization based on UV mappings to geometries:
UsdPrim materialPrim = primvarReaderSchema.GetPrim().GetParent();
UsdShadeMaterial materialSchema(materialPrim);
while (!materialSchema && materialPrim) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we make sure to properly connect the NodeGraph.

UsdShadeNodeGraph intermediateNodeGraph(materialPrim);
if (intermediateNodeGraph) {
UsdShadeInput intermediateInput
= intermediateNodeGraph.CreateInput(inputName, SdfValueTypeNames->String);
varnameInput.ConnectToSource(intermediateInput);
varnameInput = intermediateInput;
}

UsdShadeOutput primvarReaderOutput
= primvarReaderSchema.CreateOutput(TrMtlxTokens->out, SdfValueTypeNames->Float2);
materialPrim = materialPrim.GetParent();
materialSchema = UsdShadeMaterial(materialPrim);
}

// TODO: Handle UV SRT with a ND_place2d_vector2 node.
if (materialSchema) {
UsdShadeInput materialInput
= materialSchema.CreateInput(inputName, SdfValueTypeNames->String);
materialInput.Set(UsdUtilsGetPrimaryUVSetName().GetString());
varnameInput.ConnectToSource(materialInput);
} else {
varnameInput.Set(UsdUtilsGetPrimaryUVSetName());
}

UsdShadeOutput primvarReaderOutput
= primvarReaderSchema.CreateOutput(TrMtlxTokens->out, SdfValueTypeNames->Float2);

// TODO: Handle UV SRT with a ND_place2d_vector2 node. Make sure the name derives from the
// place2dTexture node if there is one (see usdFileTextureWriter for details)

// Connect the output of the primvar reader to the texture coordinate
// input of the UV texture.
texSchema.CreateInput(TrMtlxTokens->texcoord, SdfValueTypeNames->Float2)
.ConnectToSource(primvarReaderOutput);
} else {
// Re-using an existing primvar reader:
UsdShadeShader primvarReaderShaderSchema(GetUsdStage()->GetPrimAtPath(primvarReaderPath));
UsdShadeOutput primvarReaderOutput = primvarReaderShaderSchema.GetOutput(TrMtlxTokens->out);

// Connect the output of the primvar reader to the texture coordinate
// input of the UV texture.
texSchema.CreateInput(TrMtlxTokens->texcoord, SdfValueTypeNames->Float2)
.ConnectToSource(primvarReaderOutput);
// TODO: Handle UV SRT with a ND_place2d_vector2 node. Make sure the name derives from the
// place2dTexture node if there is one (see usdFileTextureWriter for details)

// Connect the output of the primvar reader to the texture coordinate
// input of the UV texture.
texSchema.CreateInput(TrMtlxTokens->texcoord, SdfValueTypeNames->Float2)
.ConnectToSource(primvarReaderOutput);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line 206-212 could be taken out of the if/else block instead of having a duplication of code.

}
}

/* virtual */
Expand Down Expand Up @@ -422,4 +446,28 @@ UsdAttribute MtlxUsd_FileWriter::GetShadingAttributeForMayaAttrName(
return UsdAttribute();
}

SdfPath MtlxUsd_FileWriter::_GetPlace2DTexturePath(const MFnDependencyNode& depNodeFn)
{
MStatus status;
std::string usdUvTextureName;
const MPlug plug = depNodeFn.findPlug(
TrMayaTokens->uvCoord.GetText(),
/* wantNetworkedPlug = */ true,
&status);
if (status == MS::kSuccess && plug.isDestination(&status)) {
MPlug source = plug.source(&status);
if (status == MS::kSuccess && !source.isNull()) {
MFnDependencyNode sourceNode(source.node());
usdUvTextureName = sourceNode.name().asChar();
}
}

if (usdUvTextureName.empty()) {
// We want a single UV reader for all file nodes not connected to a place2DTexture node
usdUvTextureName = _tokens->PrimvarReaderShaderName.GetString();
}

return GetNodeGraph().GetPath().AppendChild(TfToken(usdUvTextureName.c_str()));
}

PXR_NAMESPACE_CLOSE_SCOPE
17 changes: 10 additions & 7 deletions lib/usd/translators/shading/mtlxPreviewSurfaceWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,7 @@ MtlxUsd_PreviewSurfaceWriter::MtlxUsd_PreviewSurfaceWriter(

shaderSchema.CreateIdAttr(VtValue(TrMtlxTokens->ND_UsdPreviewSurface_surfaceshader));

UsdShadeNodeGraph nodegraphSchema(GetNodeGraph());
if (!TF_VERIFY(
nodegraphSchema,
"Could not define UsdShadeNodeGraph at path '%s'\n",
GetUsdPath().GetText())) {
return;
}
UsdShadeNodeGraph nodegraphSchema;

for (const TfToken& mayaAttrName : PxrMayaUsdPreviewSurfaceTokens->allTokens) {

Expand Down Expand Up @@ -135,6 +129,15 @@ MtlxUsd_PreviewSurfaceWriter::MtlxUsd_PreviewSurfaceWriter(

// All connections go directly to the node graph:
if (attrPlug.isConnected()) {
if (!nodegraphSchema) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just-in-time creation to reduce number of empty NodeGraph generated.

nodegraphSchema = UsdShadeNodeGraph(GetNodeGraph());
if (!TF_VERIFY(
nodegraphSchema,
"Could not define UsdShadeNodeGraph at path '%s'\n",
GetUsdPath().GetText())) {
return;
}
}
UsdShadeOutput ngOutput = nodegraphSchema.CreateOutput(mayaAttrName, valueTypeName);
input.ConnectToSource(ngOutput);
}
Expand Down
17 changes: 10 additions & 7 deletions lib/usd/translators/shading/mtlxStandardSurfaceWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,7 @@ MaterialXTranslators_StandardSurfaceWriter::MaterialXTranslators_StandardSurface

shaderSchema.CreateIdAttr(VtValue(TrMtlxTokens->ND_standard_surface_surfaceshader));

UsdShadeNodeGraph nodegraphSchema(GetNodeGraph());
if (!TF_VERIFY(
nodegraphSchema,
"Could not define UsdShadeNodeGraph at path '%s'\n",
GetUsdPath().GetText())) {
return;
}
UsdShadeNodeGraph nodegraphSchema;

for (unsigned int i = 0u; i < depNodeFn.attributeCount(); ++i) {
const MObject attrObj = depNodeFn.reorderedAttribute(i);
Expand Down Expand Up @@ -188,6 +182,15 @@ MaterialXTranslators_StandardSurfaceWriter::MaterialXTranslators_StandardSurface

// All connections go directly to the node graph:
if (attrPlug.isConnected()) {
if (!nodegraphSchema) {
nodegraphSchema = UsdShadeNodeGraph(GetNodeGraph());
if (!TF_VERIFY(
nodegraphSchema,
"Could not define UsdShadeNodeGraph at path '%s'\n",
GetUsdPath().GetText())) {
return;
}
}
UsdShadeOutput ngOutput = nodegraphSchema.CreateOutput(mayaAttrName, valueTypeName);
input.ConnectToSource(ngOutput);
}
Expand Down
1 change: 1 addition & 0 deletions lib/usd/translators/shading/shadingTokens.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ TF_DECLARE_PUBLIC_TOKENS(
(cubic)

#define TR_MTLX_ATTRIBUTES \
(varnameStr) \
(geomprop) \
(channels) \
(in) \
Expand Down
Loading