Skip to content

Commit

Permalink
EMSUSD-280 import relative texture WIP
Browse files Browse the repository at this point in the history
- Refactor out the texture resolution code into a common reusable function.
- Add file system function to make a path absolute but relative to the project folder.
- Add code to make the texture path relative to the project.
- Use the common texture import code for materialX.
- Split the texture handling into multiple helper functions to make each one clearer.
- Add the "importRelativeTextures" flag to the mayaUSDImport command.
- Add handling of the flag.
- Add a "importRelativeTextures" option to the import job arguments class.
- Add handling and validation of the option.
- Wrap the option for Python.
- Update the import command documentation.
- Use the job args option in the import code.
- Properly detect absolute or relative path in automatic mode.
- Add some unit tests.
  • Loading branch information
pierrebai-adsk committed Aug 2, 2023
1 parent 605308a commit 70fc679
Show file tree
Hide file tree
Showing 20 changed files with 988 additions and 239 deletions.
3 changes: 2 additions & 1 deletion lib/mayaUsd/commands/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ Each base command class is documented in the following sections.
| `-verbose` | `-v` | noarg | false | Make the command output more verbose. |
| `-variant` | `-var` | string[2] | none | Set variant key value pairs |
| `-importUSDZTextures` | `-itx` | bool | false | Imports textures from USDZ archives during import to disk. Can be used in conjuction with `-importUSDZTexturesFilePath` to specify an explicit directory to write imported textures to. If not specified, requires a Maya project to be set in the current context. |
| `-importUSDZTexturesFilePath` | `-itf` | string | none | Specifies an explicit directory to write imported textures to from a USDZ archive. Has no effect if `-importUSDZTextures` is not specified.
| `-importUSDZTexturesFilePath` | `-itf` | string | none | Specifies an explicit directory to write imported textures to from a USDZ archive. Has no effect if `-importUSDZTextures` is not specified. |
| `-importRelativeTextures` | `-rtx` | string | automatic | Selects how textures filenames are generated: absolute, relative or automatic. When automatic, the filename is relative if the source filename of the texture being imported is relative |

### Return Value

Expand Down
4 changes: 4 additions & 0 deletions lib/mayaUsd/commands/baseImportCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ MSyntax MayaUSDImportCommand::createSyntax()
kImportUSDZTexturesFilePathFlag,
UsdMayaJobImportArgsTokens->importUSDZTexturesFilePath.GetText(),
MSyntax::kString);
syntax.addFlag(
kImportRelativeTexturesFlag,
UsdMayaJobImportArgsTokens->importRelativeTextures.GetText(),
MSyntax::kString);
syntax.addFlag(kMetadataFlag, UsdMayaJobImportArgsTokens->metadata.GetText(), MSyntax::kString);
syntax.makeFlagMultiUse(kMetadataFlag);
syntax.addFlag(
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 @@ -45,6 +45,7 @@ class MAYAUSD_CORE_PUBLIC MayaUSDImportCommand : public MPxCommand
static constexpr auto kImportInstancesFlag = "ii";
static constexpr auto kImportUSDZTexturesFlag = "itx";
static constexpr auto kImportUSDZTexturesFilePathFlag = "itf";
static constexpr auto kImportRelativeTexturesFlag = "rtx";
static constexpr auto kMetadataFlag = "md";
static constexpr auto kApiSchemaFlag = "api";
static constexpr auto kJobContextFlag = "jc";
Expand Down
11 changes: 11 additions & 0 deletions lib/mayaUsd/fileio/jobs/jobArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1151,6 +1151,13 @@ UsdMayaJobImportArgs::UsdMayaJobImportArgs(
UsdMayaPreferredMaterialTokens->allTokens))
, importUSDZTexturesFilePath(UsdMayaJobImportArgs::GetImportUSDZTexturesFilePath(userArgs))
, importUSDZTextures(extractBoolean(userArgs, UsdMayaJobImportArgsTokens->importUSDZTextures))
, importRelativeTextures(extractToken(
userArgs,
UsdMayaJobImportArgsTokens->importRelativeTextures,
UsdMayaJobImportArgsTokens->automatic,
{ UsdMayaJobImportArgsTokens->automatic,
UsdMayaJobImportArgsTokens->absolute,
UsdMayaJobImportArgsTokens->relative }))
, importInstances(extractBoolean(userArgs, UsdMayaJobImportArgsTokens->importInstances))
, useAsAnimationCache(extractBoolean(userArgs, UsdMayaJobImportArgsTokens->useAsAnimationCache))
, importWithProxyShapes(importWithProxyShapes)
Expand Down Expand Up @@ -1209,6 +1216,8 @@ const VtDictionary& UsdMayaJobImportArgs::GetDefaultDictionary()
d[UsdMayaJobImportArgsTokens->importInstances] = true;
d[UsdMayaJobImportArgsTokens->importUSDZTextures] = false;
d[UsdMayaJobImportArgsTokens->importUSDZTexturesFilePath] = "";
d[UsdMayaJobImportArgsTokens->importRelativeTextures]
= UsdMayaJobImportArgsTokens->automatic.GetString();
d[UsdMayaJobImportArgsTokens->pullImportStage] = UsdStageRefPtr();
d[UsdMayaJobImportArgsTokens->useAsAnimationCache] = false;
d[UsdMayaJobImportArgsTokens->preserveTimeline] = false;
Expand Down Expand Up @@ -1289,6 +1298,7 @@ const VtDictionary& UsdMayaJobImportArgs::GetGuideDictionary()
d[UsdMayaJobImportArgsTokens->importInstances] = _boolean;
d[UsdMayaJobImportArgsTokens->importUSDZTextures] = _boolean;
d[UsdMayaJobImportArgsTokens->importUSDZTexturesFilePath] = _string;
d[UsdMayaJobImportArgsTokens->importRelativeTextures] = _string;
d[UsdMayaJobImportArgsTokens->pullImportStage] = _usdStageRefPtr;
d[UsdMayaJobImportArgsTokens->useAsAnimationCache] = _boolean;
d[UsdMayaJobImportArgsTokens->preserveTimeline] = _boolean;
Expand Down Expand Up @@ -1377,6 +1387,7 @@ std::ostream& operator<<(std::ostream& out, const UsdMayaJobImportArgs& importAr
<< "importInstances: " << TfStringify(importArgs.importInstances) << std::endl
<< "importUSDZTextures: " << TfStringify(importArgs.importUSDZTextures) << std::endl
<< "importUSDZTexturesFilePath: " << TfStringify(importArgs.importUSDZTexturesFilePath)
<< "importRelativeTextures: " << TfStringify(importArgs.importRelativeTextures) << std::endl
<< "pullImportStage: " << TfStringify(importArgs.pullImportStage) << std::endl
<< std::endl
<< "timeInterval: " << importArgs.timeInterval << std::endl
Expand Down
6 changes: 6 additions & 0 deletions lib/mayaUsd/fileio/jobs/jobArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,13 @@ TF_DECLARE_PUBLIC_TOKENS(
(importInstances) \
(importUSDZTextures) \
(importUSDZTexturesFilePath) \
(importRelativeTextures) \
(pullImportStage) \
(preserveTimeline) \
/* values for import relative textures */ \
(automatic) \
(absolute) \
(relative) \
/* assemblyRep values */ \
(Collapsed) \
(Full) \
Expand Down Expand Up @@ -348,6 +353,7 @@ struct UsdMayaJobImportArgs
const TfToken preferredMaterial;
const std::string importUSDZTexturesFilePath;
const bool importUSDZTextures;
const std::string importRelativeTextures;
const bool importInstances;
const bool useAsAnimationCache;
const bool importWithProxyShapes;
Expand Down
1 change: 1 addition & 0 deletions lib/mayaUsd/python/wrapPrimReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,7 @@ void wrapJobImportArgs()
.def_readonly("importUSDZTextures", &UsdMayaJobImportArgs::importUSDZTextures)
.def_readonly(
"importUSDZTexturesFilePath", &UsdMayaJobImportArgs::importUSDZTexturesFilePath)
.def_readonly("importRelativeTextures", &UsdMayaJobImportArgs::importRelativeTextures)
.def_readonly("importWithProxyShapes", &UsdMayaJobImportArgs::importWithProxyShapes)
.add_property(
"includeAPINames",
Expand Down
31 changes: 27 additions & 4 deletions lib/mayaUsd/utils/utilFileSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,20 @@ std::pair<std::string, bool> UsdMayaUtilFileSystem::makePathRelativeTo(
return std::make_pair(relativePath.generic_string(), true);
}

std::string UsdMayaUtilFileSystem::getProjectPath()
{
MString projectPath = MGlobal::executeCommandStringResult("workspace -q -rd");
return projectPath.asChar();
}

std::string UsdMayaUtilFileSystem::getPathRelativeToProject(const std::string& fileName)
{
if (fileName.empty())
return {};

MString projectPath = MGlobal::executeCommandStringResult("workspace -q -rd");
// Note: don't use isEmpty() because it is not available in Maya 2022 and earlier.
if (projectPath.length() == 0)
const std::string projectPath = getProjectPath();
if (projectPath.empty())
return {};

// Note: we do *not* use filesystem function to attempt to make the
Expand All @@ -191,18 +197,35 @@ std::string UsdMayaUtilFileSystem::getPathRelativeToProject(const std::string& f
// preserve paths entered manually with relative folder ("..")
// by keping an absolute path with ".." embedded in them,
// so this works even in this situation.
const auto pos = fileName.find(projectPath.asChar());
const auto pos = fileName.find(projectPath);
if (pos != 0)
return {};

auto relativePathAndSuccess = makePathRelativeTo(fileName, projectPath.asChar());
auto relativePathAndSuccess = makePathRelativeTo(fileName, projectPath);

if (!relativePathAndSuccess.second)
return {};

return relativePathAndSuccess.first;
}

std::string UsdMayaUtilFileSystem::makeProjectRelatedPath(const std::string& fileName)
{
const std::string projectPath = UsdMayaUtilFileSystem::getProjectPath();
if (projectPath.empty())
return {};

// Attempt to create a relative path relative to the project folder.
// If that fails, we cannot create the project-relative path.
const auto pathAndSuccess = UsdMayaUtilFileSystem::makePathRelativeTo(fileName, projectPath);
if (!pathAndSuccess.second)
return {};

// Make the path absolute but relative to the project folder. That is an absolute
// path that starts with the project path.
return UsdMayaUtilFileSystem::appendPaths(projectPath, pathAndSuccess.first);
}

std::string UsdMayaUtilFileSystem::getPathRelativeToDirectory(
const std::string& fileName,
const std::string& relativeToDir)
Expand Down
11 changes: 11 additions & 0 deletions lib/mayaUsd/utils/utilFileSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,17 @@ getPathRelativeToDirectory(const std::string& fileName, const std::string& relat
MAYAUSD_CORE_PUBLIC
std::string getPathRelativeToProject(const std::string& fileName);

/*! \brief returns the path to the Maya scene project folder.
*/
MAYAUSD_CORE_PUBLIC
std::string getProjectPath();

/*! \brief returns the absolute path of a file but relative to the Maya scene project folder.
Returns an empty string if the path cannot be made relative to the project.
*/
MAYAUSD_CORE_PUBLIC
std::string makeProjectRelatedPath(const std::string& fileName);

/*! \brief returns parent directory of a maya scene file opened by reference
*/
MAYAUSD_CORE_PUBLIC
Expand Down
1 change: 1 addition & 0 deletions lib/usd/translators/shading/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# -----------------------------------------------------------------------------
target_sources(${TARGET_NAME}
PRIVATE
shadingAsset.cpp
shadingTokens.cpp
usdBlinnReader.cpp
usdBlinnWriter.cpp
Expand Down
36 changes: 6 additions & 30 deletions lib/usd/translators/shading/mtlxImageReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// limitations under the License.
//
#include "mtlxBaseReader.h"
#include "shadingAsset.h"
#include "shadingTokens.h"

#include <mayaUsd/fileio/shaderReader.h>
Expand Down Expand Up @@ -118,34 +119,8 @@ bool MtlxUsd_ImageReader::Read(UsdMayaPrimReaderContext& context)
}

// File
VtValue val;
MPlug mayaAttr = depFn.findPlug(TrMayaTokens->fileTextureName.GetText(), true, &status);

UsdShadeInput usdInput = shaderSchema.GetInput(TrMtlxTokens->file);
if (status == MS::kSuccess && usdInput && usdInput.Get(&val) && val.IsHolding<SdfAssetPath>()) {
std::string filePath = val.UncheckedGet<SdfAssetPath>().GetResolvedPath();
if (!filePath.empty() && !ArIsPackageRelativePath(filePath)) {
// Maya has issues with relative paths, especially if deep inside a
// nesting of referenced assets. Use absolute path instead if USD was
// able to resolve. A better fix will require providing an asset
// resolver to Maya that can resolve the file correctly using the
// MPxFileResolver API. We also make sure the path is not expressed
// as a relationship like texture paths inside USDZ assets.
val = SdfAssetPath(filePath);
}

// NOTE: Will need UDIM support and potentially USDZ support. When that happens, consider
// refactoring existing code from usdUVTextureReader.cpp as shared utilities.
UsdMayaReadUtil::SetMayaAttr(mayaAttr, val);

// colorSpace:
if (usdInput.GetAttr().HasColorSpace()) {
MString colorSpace = usdInput.GetAttr().GetColorSpace().GetText();
mayaAttr = depFn.findPlug(TrMayaTokens->colorSpace.GetText(), true, &status);
if (status == MS::kSuccess) {
mayaAttr.setString(colorSpace);
}
}
if (!ResolveTextureAssetPath(prim, shaderSchema, depFn, _GetArgs().GetJobArguments())) {
return false;
}

// Default color
Expand All @@ -158,8 +133,9 @@ bool MtlxUsd_ImageReader::Read(UsdMayaPrimReaderContext& context)
}

// Filter type:
mayaAttr = depFn.findPlug(TrMayaTokens->filterType.GetText(), true, &status);
usdInput = shaderSchema.GetInput(TrMtlxTokens->filtertype);
MPlug mayaAttr = depFn.findPlug(TrMayaTokens->filterType.GetText(), true, &status);
UsdShadeInput usdInput = shaderSchema.GetInput(TrMtlxTokens->filtertype);
VtValue val;
if (status == MS::kSuccess && usdInput && usdInput.Get(&val) && val.IsHolding<std::string>()) {
std::string filterType = val.UncheckedGet<std::string>();
if (filterType == TrMtlxTokens->closest.GetString()) {
Expand Down
Loading

0 comments on commit 70fc679

Please sign in to comment.