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

Add remapUVSetsTo option to UsdImport #3776

Merged
merged 2 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions lib/mayaUsd/commands/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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: (`<from set name>`, `<to set name>`). |
| `-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. |
Expand Down
7 changes: 7 additions & 0 deletions lib/mayaUsd/commands/baseImportCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
1 change: 1 addition & 0 deletions lib/mayaUsd/commands/baseImportCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
22 changes: 15 additions & 7 deletions lib/mayaUsd/fileio/jobs/jobArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1207,6 +1207,7 @@ UsdMayaJobImportArgs::UsdMayaJobImportArgs(
, timeInterval(timeInterval)
, chaserNames(extractVector<std::string>(userArgs, UsdMayaJobImportArgsTokens->chaser))
, allChaserArgs(_ChaserArgs(userArgs, UsdMayaJobImportArgsTokens->chaserArgs))
, remapUVSetsTo(_UVSetRemaps(userArgs, UsdMayaJobImportArgsTokens->remapUVSetsTo))
{
}

Expand Down Expand Up @@ -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<VtValue>();
d[UsdMayaJobExportArgsTokens->chaserArgs] = std::vector<VtValue>();
d[UsdMayaJobImportArgsTokens->chaser] = std::vector<VtValue>();
d[UsdMayaJobImportArgsTokens->chaserArgs] = std::vector<VtValue>();
d[UsdMayaJobImportArgsTokens->remapUVSetsTo] = std::vector<VtValue>();
d[UsdMayaJobImportArgsTokens->applyEulerFilter] = false;

// plugInfo.json site defaults.
Expand Down Expand Up @@ -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<VtValue>({ _string }));
const auto _stringTuplet = VtValue(std::vector<VtValue>({ _string, _string, _string }));
const auto _stringPair = VtValue(std::vector<VtValue>({ _string, _string }));
const auto _stringPairVector = VtValue(std::vector<VtValue>({ _stringPair }));
const auto _stringTriplet = VtValue(std::vector<VtValue>({ _string, _string, _string }));
const auto _stringTupletVector = VtValue(std::vector<VtValue>({ _stringTuplet }));
const auto _stringTripletVector = VtValue(std::vector<VtValue>({ _stringTriplet }));

// Provide guide types for the parser:
Expand All @@ -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;
Expand All @@ -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;
});

Expand Down Expand Up @@ -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;
}

Expand Down
3 changes: 3 additions & 0 deletions lib/mayaUsd/fileio/jobs/jobArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ TF_DECLARE_PUBLIC_TOKENS(
(importRelativeTextures) \
(pullImportStage) \
(preserveTimeline) \
(remapUVSetsTo) \
/* values for import relative textures */ \
(automatic) \
(absolute) \
Expand Down Expand Up @@ -393,6 +394,8 @@ struct UsdMayaJobImportArgs
const std::vector<std::string> chaserNames;
const std::map<std::string, ChaserArgs> allChaserArgs;

const std::map<std::string, std::string> remapUVSetsTo;

/// Get the current material conversion.
MAYAUSD_CORE_PUBLIC
TfToken GetMaterialConversion() const;
Expand Down
5 changes: 5 additions & 0 deletions lib/mayaUsd/fileio/primReaderArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,9 @@ const TfToken::Set& UsdMayaPrimReaderArgs::GetExcludePrimvarNamespaces() const

bool UsdMayaPrimReaderArgs::GetUseAsAnimationCache() const { return _jobArgs.useAsAnimationCache; }

const std::map<std::string, std::string>& UsdMayaPrimReaderArgs::GetUVSetNameRemappings() const
{
return _jobArgs.remapUVSetsTo;
}

PXR_NAMESPACE_CLOSE_SCOPE
3 changes: 3 additions & 0 deletions lib/mayaUsd/fileio/primReaderArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ class UsdMayaPrimReaderArgs
MAYAUSD_CORE_PUBLIC
bool GetUseAsAnimationCache() const;

MAYAUSD_CORE_PUBLIC
const std::map<std::string, std::string>& GetUVSetNameRemappings() const;

bool ShouldImportUnboundShaders() const
{
// currently this is disabled.
Expand Down
38 changes: 27 additions & 11 deletions lib/mayaUsd/fileio/translators/translatorMaterial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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()) {
Expand Down Expand Up @@ -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;

Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -431,6 +446,7 @@ bool UsdMayaTranslatorMaterial::AssignMaterial(
subset.GetIndicesAttr().Get(&indices, UsdTimeCode::EarliestTime());

if (!_AssignMaterialFaceSet(
jobArguments,
faceSubsetShadingEngine,
primSchema,
shapeDagPath,
Expand Down
24 changes: 17 additions & 7 deletions lib/mayaUsd/fileio/utils/meshReadUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::string, std::string>& uvSetNameRemappings)
{
const TfToken& primvarName = primvar.GetPrimvarName();

Expand All @@ -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();
}

Expand Down Expand Up @@ -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<std::string, std::string>& uvSetNameRemappings)
{
if (meshObj.apiType() != MFn::kMesh) {
return;
Expand Down Expand Up @@ -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>",
Expand Down
9 changes: 5 additions & 4 deletions lib/mayaUsd/fileio/utils/meshReadUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::string, std::string>& uvSetNameRemappings);

MAYAUSD_CORE_PUBLIC
void assignInvisibleFaces(const UsdGeomMesh& mesh, const MObject& meshObj);
Expand Down
16 changes: 16 additions & 0 deletions lib/mayaUsd/fileio/utils/readUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,22 @@ bool UsdMayaReadUtil::ReadFloat2AsUV()
return readFloat2AsUV;
}

/* static */
MString UsdMayaReadUtil::UVSetImportedName(
const TfToken& originalName,
const std::map<std::string, std::string>& 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,
Expand Down
10 changes: 10 additions & 0 deletions lib/mayaUsd/fileio/utils/readUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ struct UsdMayaReadUtil
MAYAUSD_CORE_PUBLIC
static bool ReadFloat2AsUV();

/// 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
/// UsdMayaJobImportArgs::remapUVSetsTo.
static MString UVSetImportedName(
const TfToken& originalName,
const std::map<std::string, std::string>& 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
Expand Down
10 changes: 10 additions & 0 deletions lib/mayaUsd/python/wrapPrimReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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

//----------------------------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -458,6 +467,7 @@ void wrapJobImportArgs()
make_getter(
&UsdMayaJobImportArgs::excludePrimvarNamespaces,
return_value_policy<TfPySequenceToSet>()))
.add_property("remapUVSetsTo", ::get_remapUVSetsTo)
.def_readonly("importInstances", &UsdMayaJobImportArgs::importInstances)
.def_readonly("importUSDZTextures", &UsdMayaJobImportArgs::importUSDZTextures)
.def_readonly(
Expand Down
3 changes: 2 additions & 1 deletion lib/usd/translators/meshReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
Loading