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-113077: componentTag IO to files #1755

Merged
merged 11 commits into from
Oct 27, 2021
1 change: 1 addition & 0 deletions lib/mayaUsd/commands/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ their own purposes, similar to the Alembic export chaser example.
| `-exportSkin` | `-skn` | string | none | Determines how to export skinClusters via the UsdSkel schema. On any mesh where skin bindings are exported, the geometry data is the pre-deformation data. On any mesh where skin bindings are not exported, the geometry data is the final (post-deformation) data. Valid values are: `none` - No skinClusters are exported, `auto` - All skinClusters will be exported for non-root prims. The exporter errors on skinClusters on any root prims. The rootmost prim containing any skinned mesh will automatically be promoted into a SkelRoot, e.g. if `</Model/Mesh>` has skinning, then `</Model>` will be promoted to a SkelRoot, `explicit` - Only skinClusters under explicitly-tagged SkelRoot prims will be exported. The exporter errors if there are nested SkelRoots. To explicitly tag a prim as a SkelRoot, specify a `USD_typeName`attribute on a Maya node. |
| `-exportUVs` | `-uvs` | bool | true | Enable or disable the export of UV sets |
| `-exportVisibility` | `-vis` | bool | true | Export any state and animation on Maya `visibility` attributes |
| `-exportComponentTags` | `-tag` | bool | true | Export component tags |
| `-exportMaterialCollections` | `-mcs` | bool | false | Create collections representing sets of Maya geometry with the same material binding. These collections are created in the `material:` namespace on the prim at the specified `materialCollectionsPath` (see export option `-mcp`). These collections are encoded using the UsdCollectionAPI schema and are authored compactly using the API `UsdUtilsCreateCollections()`. |
| `-eulerFilter` | `-ef` | bool | false | Exports the euler angle filtering that was performed in Maya |
| `-filterTypes` | `-ft` | string (multi) | none | Maya type names to exclude when exporting. If a type is excluded, all inherited types are also excluded, e.g. excluding `surfaceShape` will exclude `mesh` as well. When a node is excluded based on its type name, its subtree hierarchy will be pruned from the export, and its descendants will not be exported. |
Expand Down
4 changes: 4 additions & 0 deletions lib/mayaUsd/commands/baseExportCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ MSyntax MayaUSDExportCommand::createSyntax()
kExportVisibilityFlag,
UsdMayaJobExportArgsTokens->exportVisibility.GetText(),
MSyntax::kBoolean);
syntax.addFlag(
kExportComponentTagsFlag,
UsdMayaJobExportArgsTokens->exportComponentTags.GetText(),
MSyntax::kBoolean);
syntax.addFlag(
kIgnoreWarningsFlag,
UsdMayaJobExportArgsTokens->ignoreWarnings.GetText(),
Expand Down
1 change: 1 addition & 0 deletions lib/mayaUsd/commands/baseExportCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class MAYAUSD_CORE_PUBLIC MayaUSDExportCommand : public MPxCommand
static constexpr auto kExportUVsFlag = "uvs";
static constexpr auto kEulerFilterFlag = "ef";
static constexpr auto kExportVisibilityFlag = "vis";
static constexpr auto kExportComponentTagsFlag = "tag";
static constexpr auto kIgnoreWarningsFlag = "ign";
static constexpr auto kExportInstancesFlag = "ein";
static constexpr auto kMergeTransformAndShapeFlag = "mt";
Expand Down
3 changes: 3 additions & 0 deletions lib/mayaUsd/fileio/jobs/jobArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,7 @@ UsdMayaJobExportArgs::UsdMayaJobExportArgs(
{ UsdMayaJobExportArgsTokens->auto_, UsdMayaJobExportArgsTokens->explicit_ }))
, exportBlendShapes(_Boolean(userArgs, UsdMayaJobExportArgsTokens->exportBlendShapes))
, exportVisibility(_Boolean(userArgs, UsdMayaJobExportArgsTokens->exportVisibility))
, exportComponentTags(_Boolean(userArgs, UsdMayaJobExportArgsTokens->exportComponentTags))
, file(_String(userArgs, UsdMayaJobExportArgsTokens->file))
, ignoreWarnings(_Boolean(userArgs, UsdMayaJobExportArgsTokens->ignoreWarnings))
, materialCollectionsPath(
Expand Down Expand Up @@ -499,6 +500,7 @@ std::ostream& operator<<(std::ostream& out, const UsdMayaJobExportArgs& exportAr
<< "exportSkin: " << TfStringify(exportArgs.exportSkin) << std::endl
<< "exportBlendShapes: " << TfStringify(exportArgs.exportBlendShapes) << std::endl
<< "exportVisibility: " << TfStringify(exportArgs.exportVisibility) << std::endl
<< "exportComponentTags: " << TfStringify(exportArgs.exportComponentTags) << std::endl
<< "file: " << exportArgs.file << std::endl
<< "ignoreWarnings: " << TfStringify(exportArgs.ignoreWarnings) << std::endl
<< "materialCollectionsPath: " << exportArgs.materialCollectionsPath << std::endl
Expand Down Expand Up @@ -589,6 +591,7 @@ const VtDictionary& UsdMayaJobExportArgs::GetDefaultDictionary()
d[UsdMayaJobExportArgsTokens->exportBlendShapes] = false;
d[UsdMayaJobExportArgsTokens->exportUVs] = true;
d[UsdMayaJobExportArgsTokens->exportVisibility] = true;
d[UsdMayaJobExportArgsTokens->exportComponentTags] = true;
d[UsdMayaJobExportArgsTokens->file] = std::string();
d[UsdMayaJobExportArgsTokens->filterTypes] = std::vector<VtValue>();
d[UsdMayaJobExportArgsTokens->ignoreWarnings] = false;
Expand Down
2 changes: 2 additions & 0 deletions lib/mayaUsd/fileio/jobs/jobArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ TF_DECLARE_PUBLIC_TOKENS(
(exportSkin) \
(exportUVs) \
(exportVisibility) \
(exportComponentTags) \
(file) \
(filterTypes) \
(ignoreWarnings) \
Expand Down Expand Up @@ -170,6 +171,7 @@ struct UsdMayaJobExportArgs
const TfToken exportSkin;
const bool exportBlendShapes;
const bool exportVisibility;
const bool exportComponentTags;
const std::string file;
const bool ignoreWarnings;

Expand Down
70 changes: 70 additions & 0 deletions lib/mayaUsd/fileio/utils/meshReadUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,18 @@
#include <pxr/base/tf/token.h>
#include <pxr/base/vt/array.h>
#include <pxr/usd/usdGeom/mesh.h>
#include <pxr/usd/usdGeom/subset.h>
#include <pxr/usd/usdGeom/tokens.h>
#include <pxr/usd/usdUtils/pipeline.h>

#include <maya/MFloatVector.h>
#include <maya/MFloatVectorArray.h>
#include <maya/MFnBlendShapeDeformer.h>
#include <maya/MFnComponentListData.h>
#include <maya/MFnNumericAttribute.h>
#include <maya/MFnPartition.h>
#include <maya/MFnSet.h>
#include <maya/MFnSingleIndexedComponent.h>
#include <maya/MGlobal.h>
#include <maya/MIntArray.h>
#include <maya/MItMeshEdge.h>
Expand Down Expand Up @@ -882,4 +885,71 @@ MStatus UsdMayaMeshReadUtils::assignSubDivTagsToMesh(
return MS::kSuccess;
}

MStatus UsdMayaMeshReadUtils::createComponentTags(const UsdGeomMesh& mesh, const MObject& meshObj)

Choose a reason for hiding this comment

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

Why to make this method available in older versions of Maya?

{
if (meshObj.apiType() != MFn::kMesh) {
return MS::kFailure;
}

MStatus status { MS::kSuccess };

#if MAYA_API_VERSION >= 20220000

MFnDependencyNode depNodeFn;
depNodeFn.setObject(meshObj);
MPlug ctPlug = depNodeFn.findPlug("componentTags", &status);
CHECK_MSTATUS_AND_RETURN_IT(status);

MObject ctAttr = depNodeFn.attribute("componentTags");
MObject ctNameAttr = depNodeFn.attribute("componentTagName");
MObject ctContentsAttr = depNodeFn.attribute("componentTagContents");

MPlug ctName(meshObj, ctNameAttr);
MPlug ctContent(meshObj, ctContentsAttr);

// Find all the prims defining componentTags
TfToken componentTagFamilyName("componentTag");
unsigned int idx = 0;
std::vector<UsdGeomSubset> subsets
= UsdGeomSubset::GetGeomSubsets(mesh, UsdGeomTokens->face, componentTagFamilyName);
for (auto& ss : subsets) {
// Get the tagName out of the subset
MString tagName(ss.GetPrim().GetName().GetText());

// Get the indices out of the subset
VtIntArray faceIndices;
UsdAttribute indicesAttribute = ss.GetIndicesAttr();
indicesAttribute.Get(&faceIndices);

MFnSingleIndexedComponent compFn;
MObject faceComp = compFn.create(MFn::kMeshPolygonComponent, &status);
if (!status) {
TF_RUNTIME_ERROR("Failed to create face component.");
return status;
}

MIntArray mFaces;
TF_FOR_ALL(fIdxIt, faceIndices) { mFaces.append(*fIdxIt); }
compFn.addElements(mFaces);

MFnComponentListData componentListFn;
MObject componentList = componentListFn.create();
status = componentListFn.add(faceComp);
CHECK_MSTATUS_AND_RETURN_IT(status);

// Set the attribute values
ctName.selectAncestorLogicalIndex(idx, ctAttr);
ctContent.selectAncestorLogicalIndex(idx, ctAttr);

ctName.setValue(tagName);
ctContent.setValue(componentList);

idx++;
}

#endif

return status;
}

PXR_NAMESPACE_CLOSE_SCOPE
3 changes: 3 additions & 0 deletions lib/mayaUsd/fileio/utils/meshReadUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ void assignInvisibleFaces(const UsdGeomMesh& mesh, const MObject& meshObj);
MAYAUSD_CORE_PUBLIC
MStatus assignSubDivTagsToMesh(const UsdGeomMesh&, MObject&, MFnMesh&);

MAYAUSD_CORE_PUBLIC
MStatus createComponentTags(const UsdGeomMesh& mesh, const MObject& meshObj);

} // namespace UsdMayaMeshReadUtils

PXR_NAMESPACE_CLOSE_SCOPE
Expand Down
52 changes: 52 additions & 0 deletions lib/mayaUsd/fileio/utils/meshWriteUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,16 @@
#include <pxr/usd/usdGeom/mesh.h>
#include <pxr/usd/usdGeom/pointBased.h>
#include <pxr/usd/usdGeom/primvar.h>
#include <pxr/usd/usdGeom/subset.h>
#include <pxr/usd/usdGeom/tokens.h>
#include <pxr/usd/usdUtils/pipeline.h>

#include <maya/MBoundingBox.h>
#include <maya/MFnAttribute.h>
#include <maya/MFnGeometryData.h>
#include <maya/MFnMesh.h>
#include <maya/MFnSet.h>
#include <maya/MFnSingleIndexedComponent.h>
#include <maya/MGlobal.h>
#include <maya/MIntArray.h>
#include <maya/MItDependencyGraph.h>
Expand Down Expand Up @@ -1369,4 +1372,53 @@ bool UsdMayaMeshWriteUtils::getMeshColorSetData(
return true;
}

MStatus UsdMayaMeshWriteUtils::exportComponentTags(UsdGeomMesh& primSchema, MObject obj)

Choose a reason for hiding this comment

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

Why to even make this method available for older versions of Maya?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I wanted to change Hans code as little as possible, but I can move the #ifdef out and #ifdef atthe caller site too instead of having a do-nothing function in older versions of Maya.

{
MStatus status { MS::kSuccess };

#if MAYA_API_VERSION >= 20220000

MFnDependencyNode dNode(obj, &status);
CHECK_MSTATUS_AND_RETURN_IT(status);

const MFnDependencyNode depNodeFn(obj, &status);
MPlug outShp = depNodeFn.findPlug("outMesh", &status);
CHECK_MSTATUS_AND_RETURN_IT(status);

MDataHandle geomDataHandle = outShp.asMDataHandle();
MObject geomObj = geomDataHandle.data();
if (geomObj.hasFn(MFn::kGeometryData)) {
TfToken componentTagFamilyName("componentTag");
MFnGeometryData fnGeomData(geomObj);
MStringArray keys;
status = fnGeomData.componentTags(keys);

Choose a reason for hiding this comment

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

This status doesn't seem to be checked.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, and it is not the only one, there are others a bit below. In all cases, the code seems to rely on the returned data (for example the set of keys) to be empty. Of course, that could cause silent failures. I'll add more early returns.

for (unsigned int i = 0; i < keys.length(); ++i) {
MFnGeometryData::ComponentTagCategory ctg
= fnGeomData.componentTagCategory(keys[i], &status);
if (ctg == MFnGeometryData::ComponentTagCategory::kFaces) {
MObject contents = fnGeomData.componentTagContents(keys[i], &status);
if (contents.hasFn(MFn::kSingleIndexedComponent)) {
MFnSingleIndexedComponent fnSingleIndexedComponent(contents, &status);
MIntArray curIndices;
status = fnSingleIndexedComponent.getElements(curIndices);
VtIntArray indices;
indices.reserve(curIndices.length());
for (unsigned int j = 0; j < curIndices.length(); ++j)
indices.push_back(curIndices[j]);
UsdGeomSubset ss = UsdGeomSubset::CreateGeomSubset(
primSchema,
TfToken(keys[i].asChar()),
UsdGeomTokens->face,
indices,
componentTagFamilyName);
}
}
}
}

#endif

return status;
}

PXR_NAMESPACE_CLOSE_SCOPE
3 changes: 3 additions & 0 deletions lib/mayaUsd/fileio/utils/meshWriteUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,9 @@ bool getMeshColorSetData(
MFnMesh::MColorRepresentation* colorSetRep,
bool* clamped);

MAYAUSD_CORE_PUBLIC
MStatus exportComponentTags(UsdGeomMesh& primSchema, MObject obj);

} // namespace UsdMayaMeshWriteUtils

PXR_NAMESPACE_CLOSE_SCOPE
Expand Down
3 changes: 3 additions & 0 deletions lib/usd/translators/meshReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@ bool MayaUsdPrimReaderMesh::Read(UsdMayaPrimReaderContext& context)
// assign invisible faces
UsdMayaMeshReadUtils::assignInvisibleFaces(mesh, meshRead.meshObject());

// Read componentTags
UsdMayaMeshReadUtils::createComponentTags(mesh, meshRead.meshObject());

// assign material
assignMaterial(mesh, _GetArgs(), meshRead.meshObject(), &context);

Expand Down
4 changes: 4 additions & 0 deletions lib/usd/translators/meshWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -799,6 +799,10 @@ bool PxrUsdTranslators_MeshWriter::writeMeshAttrs(
_GetSparseValueWriter());
}

if (exportArgs.exportComponentTags) {
UsdMayaMeshWriteUtils::exportComponentTags(primSchema, GetMayaObject());
}

return true;
}

Expand Down
1 change: 0 additions & 1 deletion plugin/adsk/plugin/exportTranslator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ MStatus UsdMayaExportTranslator::writer(
const MString& optionsString,
MPxFileTranslator::FileAccessMode mode)
{

// If we are in neither of these modes then there won't be anything to do
if (mode != MPxFileTranslator::kExportActiveAccessMode
&& mode != MPxFileTranslator::kExportAccessMode) {
Expand Down
5 changes: 5 additions & 0 deletions plugin/adsk/scripts/mayaUsdTranslatorExport.mel
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ global proc int mayaUsdTranslatorExport (string $parent,
string $eulerFilterAnn = "Exports the euler angle filtering that was performed in Maya.";
string $staticSingleSampleAnn = "Converts animated values with a single time sample to be static instead.";
string $visibilityAnn = "Exports Maya visibility attributes as USD metadata.";
string $componentTagsAnn = "Exports Maya component tags as USD metadata.";

Choose a reason for hiding this comment

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

Did you run this by design? FWIW. We are writing out component tags as UsdGeomSubset, not as metadata.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No, you're right I did not ask design.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Removed the new UI.

string $mergeShapesAnn = "Merges Maya transform and shape nodes into a single USD prim.";
string $namespacesAnn = "By default, namespaces are exported to the USD file in the following format: nameSpaceExample_pPlatonic1";
string $instancesAnn = "Exports Maya instances as USD instanceable references.";
Expand Down Expand Up @@ -323,6 +324,7 @@ global proc int mayaUsdTranslatorExport (string $parent,
separator -style "none";

checkBoxGrp -l "Visibility:" -annotation $visibilityAnn exportVisibilityCheckBox;
checkBoxGrp -l "Component Tags:" -annotation $componentTagsAnn exportComponentTagsCheckBox;

optionMenuGrp -l "Instances:" -annotation $instancesAnn exportInstancesPopup;
menuItem -l "Flatten";
Expand Down Expand Up @@ -410,6 +412,8 @@ global proc int mayaUsdTranslatorExport (string $parent,
mayaUsdTranslatorExport_SetOptionMenuByBool($optionBreakDown[1], "exportInstancesPopup");
} else if ($optionBreakDown[0] == "exportVisibility") {
mayaUsdTranslatorExport_SetCheckbox($optionBreakDown[1], "exportVisibilityCheckBox");
} else if ($optionBreakDown[0] == "exportComponentTags") {
mayaUsdTranslatorExport_SetCheckbox($optionBreakDown[1], "exportComponentTagsCheckBox");
} else if ($optionBreakDown[0] == "mergeTransformAndShape") {
mayaUsdTranslatorExport_SetCheckbox($optionBreakDown[1], "mergeTransformAndShapeCheckBox");
} else if ($optionBreakDown[0] == "stripNamespaces") {
Expand Down Expand Up @@ -440,6 +444,7 @@ global proc int mayaUsdTranslatorExport (string $parent,
$currentOptions = mayaUsdTranslatorExport_AppendFromMaterialPopup($currentOptions);
$currentOptions = mayaUsdTranslatorExport_AppendFromBoolPopup($currentOptions, "exportInstances", "exportInstancesPopup");
$currentOptions = mayaUsdTranslatorExport_AppendFromCheckbox($currentOptions, "exportVisibility", "exportVisibilityCheckBox");
$currentOptions = mayaUsdTranslatorExport_AppendFromCheckbox($currentOptions, "exportComponentTags", "exportComponentTagsCheckBox");
$currentOptions = mayaUsdTranslatorExport_AppendFromCheckbox($currentOptions, "mergeTransformAndShape", "mergeTransformAndShapeCheckBox");
$currentOptions = mayaUsdTranslatorExport_AppendOppositeFromCheckbox($currentOptions, "stripNamespaces", "includeNamespacesCheckBox");

Expand Down
1 change: 1 addition & 0 deletions plugin/pxr/doc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ Short flag | Long flag | Type | Default | Description
`-skn` | `-exportSkin` | string | none | Determines how to export skinClusters via the UsdSkel schema. On any mesh where skin bindings are exported, the geometry data is the pre-deformation data. On any mesh where skin bindings are not exported, the geometry data is the final (post-deformation) data. Valid values are: `none` - No skinClusters are exported, `auto` - All skinClusters will be exported for non-root prims. The exporter errors on skinClusters on any root prims. The rootmost prim containing any skinned mesh will automatically be promoted into a SkelRoot, e.g. if `</Model/Mesh>` has skinning, then `</Model>` will be promoted to a SkelRoot, `explicit` - Only skinClusters under explicitly-tagged SkelRoot prims will be exported. The exporter errors if there are nested SkelRoots. To explicitly tag a prim as a SkelRoot, specify a `USD_typeName`attribute on a Maya node.
`-uvs` | `-exportUVs` | bool | true | Enable or disable the export of UV sets
`-vis` | `-exportVisibility` | bool | true | Export any state and animation on Maya `visibility` attributes
`-tag` | `-exportComponentTags` | bool | true | Export component tags
`-mcs` | `-exportMaterialCollections` | bool | false | Create collections representing sets of Maya geometry with the same material binding. These collections are created in the `material:` namespace on the prim at the specified `materialCollectionsPath` (see export option `-mcp`). These collections are encoded using the UsdCollectionAPI schema and are authored compactly using the API `UsdUtilsCreateCollections()`.
`-ft` | `-filterTypes` | string (multi) | none | Maya type names to exclude when exporting. If a type is excluded, all inherited types are also excluded, e.g. excluding `surfaceShape` will exclude `mesh` as well. When a node is excluded based on its type name, its subtree hierarchy will be pruned from the export, and its descendants will not be exported.
`-mcp` | `-materialCollectionsPath` | string | none | Path to the prim where material collections must be exported.
Expand Down
1 change: 1 addition & 0 deletions test/lib/mayaUsd/fileio/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ set(TEST_SCRIPT_FILES
testShaderWriter.py
testExportChaser.py
testImportChaser.py
testComponentTags.py
)

add_custom_target(${TARGET_NAME} ALL)
Expand Down
Loading