From 29fc39c44762e3c6b1a34c3b65671924a5fdc2de Mon Sep 17 00:00:00 2001 From: Dan McGarry Date: Fri, 17 May 2024 14:35:50 -0700 Subject: [PATCH 1/2] Add remapUVSetsTo option to UsdImport Our users have requested that UV Sets that were renamed on export round trip cleanly on import. The Maya:name metadata accomplishes this, but only for assets that were exported after the introduction of this code. This allows us to specify a remapping for UV Set names on import so older assets work. --- lib/mayaUsd/commands/Readme.md | 1 + lib/mayaUsd/commands/baseImportCommand.cpp | 7 ++ lib/mayaUsd/commands/baseImportCommand.h | 1 + lib/mayaUsd/fileio/jobs/jobArgs.cpp | 22 +++-- lib/mayaUsd/fileio/jobs/jobArgs.h | 3 + lib/mayaUsd/fileio/primReaderArgs.cpp | 5 ++ lib/mayaUsd/fileio/primReaderArgs.h | 3 + .../fileio/translators/translatorMaterial.cpp | 38 ++++++--- lib/mayaUsd/fileio/utils/meshReadUtils.cpp | 24 ++++-- lib/mayaUsd/fileio/utils/meshReadUtils.h | 9 +- lib/mayaUsd/fileio/utils/readUtil.cpp | 16 ++++ lib/mayaUsd/fileio/utils/readUtil.h | 10 +++ lib/mayaUsd/python/wrapPrimReader.cpp | 10 +++ lib/usd/translators/meshReader.cpp | 3 +- .../translators/testUsdImportUVSetMappings.py | 2 +- .../usd/translators/testUsdImportUVSets.py | 83 ++++++++++++++++++- 16 files changed, 203 insertions(+), 34 deletions(-) diff --git a/lib/mayaUsd/commands/Readme.md b/lib/mayaUsd/commands/Readme.md index 05a073b20a..6de0caa537 100644 --- a/lib/mayaUsd/commands/Readme.md +++ b/lib/mayaUsd/commands/Readme.md @@ -46,6 +46,7 @@ Each base command class is documented in the following sections. | `-preferredMaterial` | `-prm` | string | `lambert` | Indicate a preference towards a Maya native surface material for importers that can resolve to multiple Maya materials. Allowed values are `none` (prefer plugin nodes like pxrUsdPreviewSurface and aiStandardSurface) or one of `lambert`, `standardSurface`, `blinn`, `phong`. In displayColor shading mode, a value of `none` will default to `lambert`. | `-primVariant` | `-pv` | string (multi) | none | Specifies variant choices to be imported on a prim. The variant specified will be the one to be imported, otherwise, the default variant will be imported. This flag is repeatable. Repeating the flag allows for extra prims and variant choices to be imported.| | `-readAnimData` | `-ani` | bool | false | Read animation data from prims while importing the specified USD file. If the USD file being imported specifies `startTimeCode` and/or `endTimeCode`, Maya's MinTime and/or MaxTime will be expanded if necessary to include that frame range. **Note**: Only some types of animation are currently supported, for example: animated visibility, animated transforms, animated cameras, mesh and NURBS surface animation via blend shape deformers. Other types are not yet supported, for example: time-varying curve points, time-varying mesh points/normals, time-varying NURBS surface points | +| `-remapUVSetsTo` | `-ruv` | string[2](multi) | none | Specify UV sets by name to rename on import. Each argument should be a pair of the form: (``, ``). | | `-shadingMode` | `-shd` | string[2] multi| `useRegistry` `UsdPreviewSurface` | Ordered list of shading mode importers to try when importing materials. The search stops as soon as one valid material is found. Allowed values for the first parameter are: `none` (stop search immediately, must be used to signal no material import), `displayColor` (if there are bound materials in the USD, create corresponding Lambertian shaders and bind them to the appropriate Maya geometry nodes), `pxrRis` (attempt to reconstruct a Maya shading network from (presumed) Renderman RIS shading networks in the USD), `useRegistry` (attempt to reconstruct a Maya shading network from (presumed) UsdShade shading networks in the USD) the second item in the parameter pair is a convertMaterialFrom flag which allows specifying which one of the registered USD material sources to explore. The full list of registered USD material sources can be found via the `mayaUSDListShadingModesCommand` command. | | `-useAsAnimationCache` | `-uac` | bool | false | Imports geometry prims with time-sampled point data using a point-based deformer node that references the imported USD file. When this parameter is enabled, `MayaUSDImportCommand` will create a `pxrUsdStageNode` for the USD file that is being imported. Then for each geometry prim being imported that has time-sampled points, a `pxrUsdPointBasedDeformerNode` will be created that reads the points for that prim from USD and uses them to deform the imported Maya geometry. This provides better import and playback performance when importing time-sampled geometry from USD, and it should reduce the weight of the resulting Maya scene since it will bypass creating blend shape deformers with per-object, per-time sample geometry. Only point data from the geometry prim will be computed by the deformer from the referenced USD. Transform data from the geometry prim will still be imported into native Maya form on the Maya shape's transform node. **Note**: This means that a link is created between the resulting Maya scene and the USD file that was imported. With this parameter off (as is the default), the USD file that was imported can be freely changed or deleted post-import. With the parameter on, however, the Maya scene will have a dependency on that USD file, as well as other layers that it may reference. Currently, this functionality is only implemented for Mesh prims/Maya mesh nodes. | | `-verbose` | `-v` | noarg | false | Make the command output more verbose. | diff --git a/lib/mayaUsd/commands/baseImportCommand.cpp b/lib/mayaUsd/commands/baseImportCommand.cpp index fda256e113..9fe5d4cdd1 100644 --- a/lib/mayaUsd/commands/baseImportCommand.cpp +++ b/lib/mayaUsd/commands/baseImportCommand.cpp @@ -104,6 +104,13 @@ MSyntax MayaUSDImportCommand::createSyntax() MSyntax::kString); syntax.makeFlagMultiUse(kImportChaserArgsFlag); + syntax.addFlag( + kRemapUVSetsToFlag, + UsdMayaJobImportArgsTokens->remapUVSetsTo.GetText(), + MSyntax::kString, + MSyntax::kString); + syntax.makeFlagMultiUse(kRemapUVSetsToFlag); + syntax.addFlag( kApplyEulerFilterFlag, UsdMayaJobImportArgsTokens->applyEulerFilter.GetText(), diff --git a/lib/mayaUsd/commands/baseImportCommand.h b/lib/mayaUsd/commands/baseImportCommand.h index 9316d8ff29..69d18fe99d 100644 --- a/lib/mayaUsd/commands/baseImportCommand.h +++ b/lib/mayaUsd/commands/baseImportCommand.h @@ -54,6 +54,7 @@ class MAYAUSD_CORE_PUBLIC MayaUSDImportCommand : public MPxCommand static constexpr auto kUseAsAnimationCacheFlag = "uac"; static constexpr auto kImportChaserFlag = "chr"; static constexpr auto kImportChaserArgsFlag = "cha"; + static constexpr auto kRemapUVSetsToFlag = "ruv"; static constexpr auto kApplyEulerFilterFlag = "aef"; // Short and Long forms of flags defined by this command itself: diff --git a/lib/mayaUsd/fileio/jobs/jobArgs.cpp b/lib/mayaUsd/fileio/jobs/jobArgs.cpp index 31dcc978a8..415fc4c3eb 100644 --- a/lib/mayaUsd/fileio/jobs/jobArgs.cpp +++ b/lib/mayaUsd/fileio/jobs/jobArgs.cpp @@ -1207,6 +1207,7 @@ UsdMayaJobImportArgs::UsdMayaJobImportArgs( , timeInterval(timeInterval) , chaserNames(extractVector(userArgs, UsdMayaJobImportArgsTokens->chaser)) , allChaserArgs(_ChaserArgs(userArgs, UsdMayaJobImportArgsTokens->chaserArgs)) + , remapUVSetsTo(_UVSetRemaps(userArgs, UsdMayaJobImportArgsTokens->remapUVSetsTo)) { } @@ -1301,8 +1302,9 @@ const VtDictionary& UsdMayaJobImportArgs::GetDefaultDictionary() d[UsdMayaJobImportArgsTokens->pullImportStage] = UsdStageRefPtr(); d[UsdMayaJobImportArgsTokens->useAsAnimationCache] = false; d[UsdMayaJobImportArgsTokens->preserveTimeline] = false; - d[UsdMayaJobExportArgsTokens->chaser] = std::vector(); - d[UsdMayaJobExportArgsTokens->chaserArgs] = std::vector(); + d[UsdMayaJobImportArgsTokens->chaser] = std::vector(); + d[UsdMayaJobImportArgsTokens->chaserArgs] = std::vector(); + d[UsdMayaJobImportArgsTokens->remapUVSetsTo] = std::vector(); d[UsdMayaJobImportArgsTokens->applyEulerFilter] = false; // plugInfo.json site defaults. @@ -1361,9 +1363,9 @@ const VtDictionary& UsdMayaJobImportArgs::GetGuideDictionary() const auto _usdStageRefPtr = VtValue(nullptr); const auto _string = VtValue(std::string()); const auto _stringVector = VtValue(std::vector({ _string })); - const auto _stringTuplet = VtValue(std::vector({ _string, _string, _string })); + const auto _stringPair = VtValue(std::vector({ _string, _string })); + const auto _stringPairVector = VtValue(std::vector({ _stringPair })); const auto _stringTriplet = VtValue(std::vector({ _string, _string, _string })); - const auto _stringTupletVector = VtValue(std::vector({ _stringTuplet })); const auto _stringTripletVector = VtValue(std::vector({ _stringTriplet })); // Provide guide types for the parser: @@ -1373,7 +1375,7 @@ const VtDictionary& UsdMayaJobImportArgs::GetGuideDictionary() d[UsdMayaJobImportArgsTokens->excludePrimvarNamespace] = _stringVector; d[UsdMayaJobImportArgsTokens->jobContext] = _stringVector; d[UsdMayaJobImportArgsTokens->metadata] = _stringVector; - d[UsdMayaJobImportArgsTokens->shadingMode] = _stringTupletVector; + d[UsdMayaJobImportArgsTokens->shadingMode] = _stringTripletVector; d[UsdMayaJobImportArgsTokens->preferredMaterial] = _string; d[UsdMayaJobImportArgsTokens->importInstances] = _boolean; d[UsdMayaJobImportArgsTokens->importUSDZTextures] = _boolean; @@ -1382,8 +1384,9 @@ const VtDictionary& UsdMayaJobImportArgs::GetGuideDictionary() d[UsdMayaJobImportArgsTokens->pullImportStage] = _usdStageRefPtr; d[UsdMayaJobImportArgsTokens->useAsAnimationCache] = _boolean; d[UsdMayaJobImportArgsTokens->preserveTimeline] = _boolean; - d[UsdMayaJobExportArgsTokens->chaser] = _stringVector; - d[UsdMayaJobExportArgsTokens->chaserArgs] = _stringTripletVector; + d[UsdMayaJobImportArgsTokens->chaser] = _stringVector; + d[UsdMayaJobImportArgsTokens->chaserArgs] = _stringTripletVector; + d[UsdMayaJobImportArgsTokens->remapUVSetsTo] = _stringPairVector; d[UsdMayaJobImportArgsTokens->applyEulerFilter] = _boolean; }); @@ -1497,6 +1500,11 @@ std::ostream& operator<<(std::ostream& out, const UsdMayaJobImportArgs& importAr } } + out << "remapUVSetsTo (" << importArgs.remapUVSetsTo.size() << ")" << std::endl; + for (const auto& remapIt : importArgs.remapUVSetsTo) { + out << " " << remapIt.first << " -> " << remapIt.second << std::endl; + } + return out; } diff --git a/lib/mayaUsd/fileio/jobs/jobArgs.h b/lib/mayaUsd/fileio/jobs/jobArgs.h index 8f8def5016..95d981561b 100644 --- a/lib/mayaUsd/fileio/jobs/jobArgs.h +++ b/lib/mayaUsd/fileio/jobs/jobArgs.h @@ -170,6 +170,7 @@ TF_DECLARE_PUBLIC_TOKENS( (importRelativeTextures) \ (pullImportStage) \ (preserveTimeline) \ + (remapUVSetsTo) \ /* values for import relative textures */ \ (automatic) \ (absolute) \ @@ -393,6 +394,8 @@ struct UsdMayaJobImportArgs const std::vector chaserNames; const std::map allChaserArgs; + const std::map remapUVSetsTo; + /// Get the current material conversion. MAYAUSD_CORE_PUBLIC TfToken GetMaterialConversion() const; diff --git a/lib/mayaUsd/fileio/primReaderArgs.cpp b/lib/mayaUsd/fileio/primReaderArgs.cpp index f00ec094c5..a326cd6f70 100644 --- a/lib/mayaUsd/fileio/primReaderArgs.cpp +++ b/lib/mayaUsd/fileio/primReaderArgs.cpp @@ -50,4 +50,9 @@ const TfToken::Set& UsdMayaPrimReaderArgs::GetExcludePrimvarNamespaces() const bool UsdMayaPrimReaderArgs::GetUseAsAnimationCache() const { return _jobArgs.useAsAnimationCache; } +const std::map& UsdMayaPrimReaderArgs::GetUVSetNameRemappings() const +{ + return _jobArgs.remapUVSetsTo; +} + PXR_NAMESPACE_CLOSE_SCOPE diff --git a/lib/mayaUsd/fileio/primReaderArgs.h b/lib/mayaUsd/fileio/primReaderArgs.h index d6649f2f0d..e5bc819af5 100644 --- a/lib/mayaUsd/fileio/primReaderArgs.h +++ b/lib/mayaUsd/fileio/primReaderArgs.h @@ -65,6 +65,9 @@ class UsdMayaPrimReaderArgs MAYAUSD_CORE_PUBLIC bool GetUseAsAnimationCache() const; + MAYAUSD_CORE_PUBLIC + const std::map& GetUVSetNameRemappings() const; + bool ShouldImportUnboundShaders() const { // currently this is disabled. diff --git a/lib/mayaUsd/fileio/translators/translatorMaterial.cpp b/lib/mayaUsd/fileio/translators/translatorMaterial.cpp index 5b084dc984..b16af5724b 100644 --- a/lib/mayaUsd/fileio/translators/translatorMaterial.cpp +++ b/lib/mayaUsd/fileio/translators/translatorMaterial.cpp @@ -214,9 +214,10 @@ _GetUVBindingsFromMaterial(const UsdShadeMaterial& material, UsdMayaPrimReaderCo } static void _BindUVs( - const UsdGeomGprim& primSchema, - const MDagPath& shapeDagPath, - const _UVBindings& uvBindings) + const UsdMayaJobImportArgs& jobArguments, + const UsdGeomGprim& primSchema, + const MDagPath& shapeDagPath, + const _UVBindings& uvBindings) { if (uvBindings.empty()) { return; @@ -241,6 +242,14 @@ static void _BindUVs( || (UsdMayaReadUtil::ReadFloat2AsUV() && typeName == SdfValueTypeNames->Float2Array)) { TfToken originalName = UsdMayaRoundTripUtil::GetPrimVarMayaName(primvar); + if (originalName.IsEmpty()) { + // If we have no roundtripped original name, see if there + // were any UVSet name remappings applied on import. We will + // want to ignore that remapping here + originalName = TfToken(UsdMayaReadUtil::UVSetImportedName( + primvar.GetPrimvarName(), jobArguments.remapUVSetsTo) + .asChar()); + } if (!originalName.IsEmpty()) { for (unsigned int uvSetIndex = 1; uvSetIndex < uvSets.length(); uvSetIndex++) { if (uvSets[uvSetIndex] == originalName.GetText()) { @@ -274,11 +283,12 @@ static void _BindUVs( } // namespace static bool _AssignMaterialFaceSet( - const MObject& shadingEngine, - const UsdGeomGprim& primSchema, - const MDagPath& shapeDagPath, - const VtIntArray& faceIndices, - const _UVBindings& faceUVBindings) + const UsdMayaJobImportArgs& jobArguments, + const MObject& shadingEngine, + const UsdGeomGprim& primSchema, + const MDagPath& shapeDagPath, + const VtIntArray& faceIndices, + const _UVBindings& faceUVBindings) { MStatus status; @@ -303,7 +313,7 @@ static bool _AssignMaterialFaceSet( "Could not add component to shadingEngine %s.", seFnSet.name().asChar()); return false; } - _BindUVs(primSchema, shapeDagPath, faceUVBindings); + _BindUVs(jobArguments, primSchema, shapeDagPath, faceUVBindings); } return true; @@ -355,7 +365,7 @@ bool UsdMayaTranslatorMaterial::AssignMaterial( TF_RUNTIME_ERROR( "Could not add shadingEngine for '%s'.", shapeDagPath.fullPathName().asChar()); } - _BindUVs(primSchema, shapeDagPath, uvBindings); + _BindUVs(jobArguments, primSchema, shapeDagPath, uvBindings); } return true; @@ -402,7 +412,12 @@ bool UsdMayaTranslatorMaterial::AssignMaterial( geom, UsdGeomTokens->face, UsdShadeTokens->materialBind); #endif if (!_AssignMaterialFaceSet( - shadingEngine, primSchema, shapeDagPath, unassignedIndices, uvBindings)) { + jobArguments, + shadingEngine, + primSchema, + shapeDagPath, + unassignedIndices, + uvBindings)) { return false; } } @@ -431,6 +446,7 @@ bool UsdMayaTranslatorMaterial::AssignMaterial( subset.GetIndicesAttr().Get(&indices, UsdTimeCode::EarliestTime()); if (!_AssignMaterialFaceSet( + jobArguments, faceSubsetShadingEngine, primSchema, shapeDagPath, diff --git a/lib/mayaUsd/fileio/utils/meshReadUtils.cpp b/lib/mayaUsd/fileio/utils/meshReadUtils.cpp index bc8a7c33a7..03fe3c9f0f 100644 --- a/lib/mayaUsd/fileio/utils/meshReadUtils.cpp +++ b/lib/mayaUsd/fileio/utils/meshReadUtils.cpp @@ -196,7 +196,11 @@ MIntArray getMayaFaceVertexAssignmentIds( return valueIds; } -bool assignUVSetPrimvarToMesh(const UsdGeomPrimvar& primvar, MFnMesh& meshFn, bool& firstUVPrimvar) +bool assignUVSetPrimvarToMesh( + const UsdGeomPrimvar& primvar, + MFnMesh& meshFn, + bool& firstUVPrimvar, + const std::map& uvSetNameRemappings) { const TfToken& primvarName = primvar.GetPrimvarName(); @@ -214,7 +218,12 @@ bool assignUVSetPrimvarToMesh(const UsdGeomPrimvar& primvar, MFnMesh& meshFn, bo MString uvSetName(primvarName.GetText()); TfToken originalName = UsdMayaRoundTripUtil::GetPrimVarMayaName(primvar); - if (!originalName.IsEmpty()) { + if (originalName.IsEmpty()) { + // Only honor the UVSet name remapping preferences if we did not find a + // cached value for the original Maya-based name, otherwise use that + // cached value + uvSetName = UsdMayaReadUtil::UVSetImportedName(primvarName, uvSetNameRemappings); + } else { uvSetName = originalName.GetText(); } @@ -594,10 +603,11 @@ void UsdMayaMeshReadUtils::setEmitNormalsTag(MFnMesh& meshFn, const bool emitNor } void UsdMayaMeshReadUtils::assignPrimvarsToMesh( - const UsdGeomMesh& mesh, - const MObject& meshObj, - const TfToken::Set& excludePrimvarSet, - const TfToken::Set& excludePrivarNamespaceSet) + const UsdGeomMesh& mesh, + const MObject& meshObj, + const TfToken::Set& excludePrimvarSet, + const TfToken::Set& excludePrivarNamespaceSet, + const std::map& uvSetNameRemappings) { if (meshObj.apiType() != MFn::kMesh) { return; @@ -663,7 +673,7 @@ void UsdMayaMeshReadUtils::assignPrimvarsToMesh( // Otherwise, if env variable for reading Float2 // as uv sets is turned on, we assume that Float2Array primvars // are UV sets. - if (!assignUVSetPrimvarToMesh(primvar, meshFn, firstUVPrimvar)) { + if (!assignUVSetPrimvarToMesh(primvar, meshFn, firstUVPrimvar, uvSetNameRemappings)) { TF_WARN( "Unable to retrieve and assign data for UV set <%s> on " "mesh <%s>", diff --git a/lib/mayaUsd/fileio/utils/meshReadUtils.h b/lib/mayaUsd/fileio/utils/meshReadUtils.h index 06f1389b31..7d625920ff 100644 --- a/lib/mayaUsd/fileio/utils/meshReadUtils.h +++ b/lib/mayaUsd/fileio/utils/meshReadUtils.h @@ -80,10 +80,11 @@ void setEmitNormalsTag(MFnMesh& meshFn, const bool emitNormals); MAYAUSD_CORE_PUBLIC void assignPrimvarsToMesh( - const UsdGeomMesh& mesh, - const MObject& meshObj, - const TfToken::Set& excludePrimvarSet, - const TfToken::Set& excludePrimvarNamespaceSet); + const UsdGeomMesh& mesh, + const MObject& meshObj, + const TfToken::Set& excludePrimvarSet, + const TfToken::Set& excludePrimvarNamespaceSet, + const std::map& uvSetNameRemappings); MAYAUSD_CORE_PUBLIC void assignInvisibleFaces(const UsdGeomMesh& mesh, const MObject& meshObj); diff --git a/lib/mayaUsd/fileio/utils/readUtil.cpp b/lib/mayaUsd/fileio/utils/readUtil.cpp index bfd5228ecd..bb618f03ad 100644 --- a/lib/mayaUsd/fileio/utils/readUtil.cpp +++ b/lib/mayaUsd/fileio/utils/readUtil.cpp @@ -67,6 +67,22 @@ bool UsdMayaReadUtil::ReadFloat2AsUV() return readFloat2AsUV; } +/* static */ +MString UsdMayaReadUtil::UVSetImportedName( + const TfToken& originalName, + const std::map& uvSetRemaps) +{ + MString setName(originalName.GetText()); + + auto it = uvSetRemaps.find(setName.asChar()); + if (it != uvSetRemaps.end()) { + // Remap the UV set as specified + setName = it->second.c_str(); + } + + return setName; +} + MObject UsdMayaReadUtil::FindOrCreateMayaAttr( const SdfValueTypeName& typeName, const SdfVariability variability, diff --git a/lib/mayaUsd/fileio/utils/readUtil.h b/lib/mayaUsd/fileio/utils/readUtil.h index 15372ff9a6..ebdd795392 100644 --- a/lib/mayaUsd/fileio/utils/readUtil.h +++ b/lib/mayaUsd/fileio/utils/readUtil.h @@ -42,6 +42,16 @@ struct UsdMayaReadUtil MAYAUSD_CORE_PUBLIC static bool ReadFloat2AsUV(); + /// Returns the imported name of a UV set at \p uvIndex according to the renaming rule and the + /// current set of options. + /// + /// \p originalName is the USD UV primvar name. + /// \p uvSetRemaps is as defined by the -remapUVSetsTo import option and stored in + /// UsdMayaJobImportArgs::remapUVSetsTo. + static MString UVSetImportedName( + const TfToken& originalName, + const std::map& uvSetRemaps); + /// Given the \p typeName and \p variability, try to create a Maya attribute /// on \p depNode with the name \p attrName. /// If the \p typeName isn't supported by this function, raises a runtime diff --git a/lib/mayaUsd/python/wrapPrimReader.cpp b/lib/mayaUsd/python/wrapPrimReader.cpp index 49e2227acb..6a338dcd38 100644 --- a/lib/mayaUsd/python/wrapPrimReader.cpp +++ b/lib/mayaUsd/python/wrapPrimReader.cpp @@ -425,6 +425,15 @@ boost::python::object get_allChaserArgs(UsdMayaJobImportArgs& self) return boost::python::object(allChaserArgs); } +boost::python::object get_remapUVSetsTo(UsdMayaJobImportArgs& self) +{ + boost::python::dict uvSetRemaps; + for (auto&& remap : self.remapUVSetsTo) { + uvSetRemaps[remap.first] = remap.second; + } + return boost::python::object(uvSetRemaps); +} + } // namespace //---------------------------------------------------------------------------------------------------------------------- @@ -458,6 +467,7 @@ void wrapJobImportArgs() make_getter( &UsdMayaJobImportArgs::excludePrimvarNamespaces, return_value_policy())) + .add_property("remapUVSetsTo", ::get_remapUVSetsTo) .def_readonly("importInstances", &UsdMayaJobImportArgs::importInstances) .def_readonly("importUSDZTextures", &UsdMayaJobImportArgs::importUSDZTextures) .def_readonly( diff --git a/lib/usd/translators/meshReader.cpp b/lib/usd/translators/meshReader.cpp index 782f0eb3f7..69ff3a3a59 100644 --- a/lib/usd/translators/meshReader.cpp +++ b/lib/usd/translators/meshReader.cpp @@ -136,7 +136,8 @@ bool MayaUsdPrimReaderMesh::Read(UsdMayaPrimReaderContext& context) mesh, meshRead.meshObject(), _GetArgs().GetExcludePrimvarNames(), - _GetArgs().GetExcludePrimvarNamespaces()); + _GetArgs().GetExcludePrimvarNamespaces(), + _GetArgs().GetUVSetNameRemappings()); // assign invisible faces UsdMayaMeshReadUtils::assignInvisibleFaces(mesh, meshRead.meshObject()); diff --git a/test/lib/usd/translators/testUsdImportUVSetMappings.py b/test/lib/usd/translators/testUsdImportUVSetMappings.py index b4a47f5d65..2a38c05815 100644 --- a/test/lib/usd/translators/testUsdImportUVSetMappings.py +++ b/test/lib/usd/translators/testUsdImportUVSetMappings.py @@ -46,6 +46,7 @@ def testImportUVSetMappings(self): ''' usd_path = os.path.join(self.test_dir, "UsdImportUVSetMappings.usda") options = ["shadingMode=[[useRegistry,UsdPreviewSurface]]", + "remapUVSetsTo=[['','']]", "primPath=/"] cmds.file(usd_path, i=True, type="USD Import", ignoreVersion=True, ra=True, mergeNamespacesOnClash=False, @@ -89,6 +90,5 @@ def testImportUVSetMappings(self): links = set(links) self.assertEqual(set(cmds.uvLink(texture=file_name)), links) - if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/test/lib/usd/translators/testUsdImportUVSets.py b/test/lib/usd/translators/testUsdImportUVSets.py index b052107b06..bdcb065ac7 100644 --- a/test/lib/usd/translators/testUsdImportUVSets.py +++ b/test/lib/usd/translators/testUsdImportUVSets.py @@ -61,7 +61,7 @@ def _AssertUVSet(self, mesh, uvSetName, expectedValues, actualUV = itMeshFV.getUV(uvSetName) self.assertAlmostEqual(expectedUV, actualUV) - itMeshFV.next() + itMeshFV.next() # pylint: disable=next-method-called fvi += 1 if expectedNumUVShells is not None: @@ -79,7 +79,7 @@ def setUpClass(cls): else: usdFile = os.path.join(cls.inputPath, "UsdImportUVSetsTest", "UsdImportUVSetsTest.usda") - cmds.usdImport(file=usdFile, shadingMode=[["none", "default"], ]) + cmds.usdImport(file=usdFile, shadingMode=[["none", "default"], ], remapUVSetsTo=[['','']]) @classmethod def tearDownClass(cls): @@ -358,7 +358,7 @@ def testImportUVSetForMeshWithCreases(self): # We also need to load it using the Maya file import command because # going through the usdImport command works fine but using the file # translator caused a crash. - cmds.file(usdFile, i=True) + cmds.file(usdFile, i=True, options="remapUVSetsTo=[['','']]") mayaCubeMesh = testUsdImportUVSets._GetMayaMesh('CreasedCubeShape') @@ -393,6 +393,83 @@ def testImportUVSetForMeshWithCreases(self): self._AssertUVSet(mayaCubeMesh, "st", expectedValues, expectedNumValues=14) + def testImportUVSetWithNameRemapping(self): + """ + Tests the importing a mesh honors specified UVSet name remappings + """ + if self.asFloat2: + usdFile = os.path.join(self.inputPath, "UsdImportUVSetsFloatTest", "UsdImportUVSetsTest_Float.usda") + else: + usdFile = os.path.join(self.inputPath, "UsdImportUVSetsTest", "UsdImportUVSetsTest.usda") + cmds.file(new=True, force=True) + cmds.usdImport(file=usdFile, shadingMode=[["none", "default"], ], remapUVSetsTo=[['st','sst'],['map1','mmap1']]) + + mayaCubeMesh = testUsdImportUVSets._GetMayaMesh('DefaultUVSetCubeShape') + + # These are the default UV values for a regular Maya polycube. + expectedValues = { + 0: Gf.Vec2f(0.375, 0.0), + 1: Gf.Vec2f(0.625, 0.0), + 2: Gf.Vec2f(0.625, 0.25), + 3: Gf.Vec2f(0.375, 0.25), + 4: Gf.Vec2f(0.375, 0.25), + 5: Gf.Vec2f(0.625, 0.25), + 6: Gf.Vec2f(0.625, 0.5), + 7: Gf.Vec2f(0.375, 0.5), + 8: Gf.Vec2f(0.375, 0.5), + 9: Gf.Vec2f(0.625, 0.5), + 10: Gf.Vec2f(0.625, 0.75), + 11: Gf.Vec2f(0.375, 0.75), + 12: Gf.Vec2f(0.375, 0.75), + 13: Gf.Vec2f(0.625, 0.75), + 14: Gf.Vec2f(0.625, 1.0), + 15: Gf.Vec2f(0.375, 1.0), + 16: Gf.Vec2f(0.625, 0.0), + 17: Gf.Vec2f(0.875, 0.0), + 18: Gf.Vec2f(0.875, 0.25), + 19: Gf.Vec2f(0.625, 0.25), + 20: Gf.Vec2f(0.125, 0.0), + 21: Gf.Vec2f(0.375, 0.0), + 22: Gf.Vec2f(0.375, 0.25), + 23: Gf.Vec2f(0.125, 0.25) + } + + self._AssertUVSet(mayaCubeMesh, "sst", expectedValues, + expectedNumValues=14, expectedNumUVShells=1) + + mayaCubeMesh = testUsdImportUVSets._GetMayaMesh('Map1UVSetCubeShape') + + # These are the default UV values for a regular Maya polycube. + expectedValues = { + 0: Gf.Vec2f(0.375, 0.0), + 1: Gf.Vec2f(0.625, 0.0), + 2: Gf.Vec2f(0.625, 0.25), + 3: Gf.Vec2f(0.375, 0.25), + 4: Gf.Vec2f(0.375, 0.25), + 5: Gf.Vec2f(0.625, 0.25), + 6: Gf.Vec2f(0.625, 0.5), + 7: Gf.Vec2f(0.375, 0.5), + 8: Gf.Vec2f(0.375, 0.5), + 9: Gf.Vec2f(0.625, 0.5), + 10: Gf.Vec2f(0.625, 0.75), + 11: Gf.Vec2f(0.375, 0.75), + 12: Gf.Vec2f(0.375, 0.75), + 13: Gf.Vec2f(0.625, 0.75), + 14: Gf.Vec2f(0.625, 1.0), + 15: Gf.Vec2f(0.375, 1.0), + 16: Gf.Vec2f(0.625, 0.0), + 17: Gf.Vec2f(0.875, 0.0), + 18: Gf.Vec2f(0.875, 0.25), + 19: Gf.Vec2f(0.625, 0.25), + 20: Gf.Vec2f(0.125, 0.0), + 21: Gf.Vec2f(0.375, 0.0), + 22: Gf.Vec2f(0.375, 0.25), + 23: Gf.Vec2f(0.125, 0.25) + } + + self._AssertUVSet(mayaCubeMesh, "mmap1", expectedValues, + expectedNumValues=14, expectedNumUVShells=1) + if __name__ == '__main__': unittest.main(verbosity=2) From 31da870e5bf98450ef96acf5a22a0f5c677e51c6 Mon Sep 17 00:00:00 2001 From: dj-mcg <48066546+dj-mcg@users.noreply.github.com> Date: Fri, 24 May 2024 09:42:48 -0700 Subject: [PATCH 2/2] Update readUtil.h Correcting the comment to match the updated function parameters --- lib/mayaUsd/fileio/utils/readUtil.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/mayaUsd/fileio/utils/readUtil.h b/lib/mayaUsd/fileio/utils/readUtil.h index ebdd795392..b6da406376 100644 --- a/lib/mayaUsd/fileio/utils/readUtil.h +++ b/lib/mayaUsd/fileio/utils/readUtil.h @@ -42,8 +42,8 @@ struct UsdMayaReadUtil MAYAUSD_CORE_PUBLIC static bool ReadFloat2AsUV(); - /// Returns the imported name of a UV set at \p uvIndex according to the renaming rule and the - /// current set of options. + /// Returns the imported name of a USD UV set with primvar name \p originalName + /// according to the renaming rule and the current set of options. /// /// \p originalName is the USD UV primvar name. /// \p uvSetRemaps is as defined by the -remapUVSetsTo import option and stored in