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

Pixar Mesh read translator/utilities refactoring #343

Merged
merged 9 commits into from
Mar 21, 2020

Conversation

HamedSabri-adsk
Copy link
Contributor

Problem Description and Objectives

Translation between USD and Maya schemas is a key technology to delivering amazing artist experiences across diverse workflows. Unfortunately, there is currently significant duplication of schema translators and relevant utilities across different USD plug-ins. This is hard to maintain and manage.

To enable code reuse across different workflows, accelerate community contributions, ease maintenance, and let others build upon advanced capabilities (e.g., Animal Logic in-context modeling), we are refactoring translation code. The goal is to centralize common functionality into a core library while still allowing individual plug-ins to customize behavior, based on specific needs.

PR Description

To ease reviewing of this work, we’re aiming to split up a large pull request into several smaller pull requests. The below description relates to the first of these pull requests:

This PR is based off of Pixar's Mesh read translators which provides a common set of mesh utilities and translators that can be used by other frameworks/plug-ins.

Specifically, this PR provides utility functions and translators for reading and translating UsdGeomMesh prim into a Maya mesh object. To achieve this, some architectural changes were required for the UsdMayaTranslatorMesh class:

  • Create a new class interfaces with no internal dependency to UsdMayaPrimReaderArgs and UsdMayaPrimReaderContext.

  • Remove private static functions, extract their operations and provide a new set of utilities under meshUtils (e.g., assignPrimvarsToMesh, assignInvisibleFaces, assignSubDivTagsToMesh ).

  • Provide some getter functions to easily get access to Maya Mesh object as well as deforming meshes (e.g blendshape, PointBasedDeformer) objects.

…ons and translator for reading and translating UsdGeomMesh prim into a Maya mesh object.To make this happen I had to make some architectural changes in UsdMayaTranslatorMesh class:

-  Create a new class interfaces with no internal dependency to UsdMayaPrimReaderArgs and UsdMayaPrimReaderContext.

- Remove private static functions, extract their operations and provide as a new set of utilities under meshUtils ( e.g assignPrimvarsToMesh, assignInvisibleFaces, assignSubDivTagsToMesh ).

- Provide getter functions to get access Maya Mesh object as well as deforming meshes (e.g blendshape, PointBasedDeformer) objects.
@HamedSabri-adsk HamedSabri-adsk added import-export Related to Import and/or Export pxr Related to Pixar plugin labels Mar 9, 2020
@kxl-adsk kxl-adsk added core Related to core library and removed pxr Related to Pixar plugin labels Mar 9, 2020
Copy link
Contributor

@mattyjams mattyjams left a comment

Choose a reason for hiding this comment

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

Code review-wise, the changes mostly look good to me, as it's mainly just moving things around. I noticed two things about the point-based deformer node handling that I think need attention though:

  • I think it should probably not be enabled by default when constructing the TranslatorMeshRead.
  • If we succeed in setting up the point-based deformer, we should skip doing any blend shape deformer stuff.

But following that, I ran the unit tests and hit a whole bunch of test failures:

82% tests passed, 15 tests failed out of 85

Total Test time (real) = 397.60 sec

The following tests FAILED:
	 25 - testUsdExportOverImport (Failed)
	 29 - testUsdExportPointInstancer (Failed)
	 41 - testUsdImportAsAssemblies (Failed)
	 43 - testUsdImportColorSets (Failed)
	 46 - testUsdImportMesh (Failed)
	 47 - testUsdImportNestedAssemblyAnimation (Failed)
	 49 - testUsdImportShadingModeDisplayColor (Failed)
	 50 - testUsdImportShadingModePxrRis (Failed)
	 51 - testUsdImportSkeleton (Failed)
	 53 - testUsdImportUVSets (Failed)
	 54 - testUsdImportUVSetsFloat (Failed)
	 55 - testUsdImportXforms (Failed)
	 58 - testUsdMayaAdaptorMetadata (Failed)
	 64 - testUsdMayaProxyShape (Failed)
	 68 - testUsdReferenceAssemblyChangeRepresentations (Failed)

I haven't looked into them in much detail yet, but it seems like some of them may have to do with the node naming and/or transform and shape node handling.

Comment on lines 1122 to 1136
MStatus
UsdMayaMeshUtil::setName(const MObject& meshObj, const std::string& shapeName)
{
if(meshObj.apiType() != MFn::kMesh){
return MS::kFailure;
}

MStatus status;

MFnMesh meshFn(meshObj);
meshFn.setName(MString(shapeName.c_str()), false, &status);

return status;
}

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm a little unsure about how useful this function is generally. As far as I can tell from these changes, it's currently only called in one place in meshReader.cpp?

Maybe it would make more sense if it was moved to UsdMayaUtil::setName() and operated on nodes as MFnDependencyNode?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point. Please see 7be630d

I originally stick this here because it was needed for this PR. I have a larger PR locally for cleaning up the utility functions and didn't want bring those changes here.


MStatus status;

MFnMesh meshFn(meshObj);
Copy link
Contributor

Choose a reason for hiding this comment

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

This constructor can fail and return an error MStatus too, can't it? Should we be capturing and checking that before calling setName()?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Please see 7be630d.

Comment on lines +24 to +25
#include "../utils/meshUtil.h"
#include "../utils/readUtil.h"
Copy link
Contributor

Choose a reason for hiding this comment

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

Are we ready to stop using relative paths for these includes? I'd love it if we could stop digging ourselves deeper into that hole. I know there are a lot of existing ones to clean up, but it would be great not to be adding more.

Choose a reason for hiding this comment

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

On my TODO to make the final changes we voted on and commit our coding guidelines to the repo. So yes, we should start using them now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@mattyjams Believe me I don't like the dots as much as you don't but I didn't want to spend time doing this in this PR since they are going to be cleanup in a serrate PR.

@@ -252,7 +76,7 @@ UsdMayaTranslatorMesh::Create(
"faceVertexCounts), which isn't currently supported. "
"Skipping...",
prim.GetPath().GetText());
return false;
stat = MS::kFailure;
Copy link
Contributor

Choose a reason for hiding this comment

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

Are we sure we want to continue attempting to translate the mesh after we encounter an error? Seems like we could run into trouble both on the Maya side and maybe the USD side as well if we try to barrel ahead with a degenerate or otherwise invalid mesh.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is covered in 64ccefa. Both faceVertexIndices and faceVertexCounts are passed to UsdGeomMesh::ValidateTopology and if we don't have a valid topology mesh, we simply set the status and return.

_SetupPointBasedDeformerForMayaNode(meshObj, prim, context)) {
return true;
if (m_wantCacheAnimation){
stat = setPointBasedDeformerForMayaNode(m_meshObj, stageNode, prim);
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need to check status here and return if it was successful? The intention of this point based deformer thing was as an alternative to the blend shape deformer, since that can be hugely expensive both in translation and execution time. If we succeeded in setting up the point based deformer, we want to skip setting up a blend shape deformer.

Copy link
Contributor Author

@HamedSabri-adsk HamedSabri-adsk Mar 18, 2020

Choose a reason for hiding this comment

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

Duh... That's definitely an overlook on my part. Sorry about that. See 684c5b4
I also have done some extra clean up around the status in the same commit. If we have a bad USD or Maya mesh, I simply set the status and return. There is no point to do any further operation if the data is bad in a first place.

const MObject& transformObj,
const MObject& stageNode,
const GfInterval& frameRange,
bool wantCacheAnimation = true,
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure whether we want to enable this by default. Turning this on, and using the point based deformer as a result, effectively bypasses doing a bunch of translation, so you then end up with a Maya node in your scene that depends on the USD file you're importing. We never enabled that option by default for usdImport since it seemed like the expected behavior would be that you could import a USD file and then delete the file if you wanted to. There would be no connection between the Maya scene resulting from a usdImport, and the USD file that was imported.

Copy link
Contributor Author

@HamedSabri-adsk HamedSabri-adsk Mar 18, 2020

Choose a reason for hiding this comment

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

Ugh I see... Makes sense. Please see 64ccefa

Hamed Sabri added 3 commits March 18, 2020 12:14
…ed deformer" is selected.

- clean up some of status logics. If a critical operation during the TranslatorMeshRead construction fails, we set the *status and simply return.
@HamedSabri-adsk
Copy link
Contributor Author

Hi @mattyjams , apologies for the late reply. It has been a hectic week here for me :)

I have created 3 separate commits to address some of your feedback.

The unit tests are still failing which I am investigating next. I still don't have full understanding why they fail but I believe I can find out once looking into them in more detail.

}

// store the path
m_shapePath = prim.GetPath().AppendChild(TfToken(shapeName));
Copy link
Contributor Author

Choose a reason for hiding this comment

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

After the mesh function set is created, we set it's name and then store the SdfPath that is created off of it.

// shape name
const auto& primName = prim.GetName().GetString();
status = UsdMayaUtil::setName(meshRead.meshObject(), primName);
CHECK_MSTATUS_AND_RETURN(status, false);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was just wrong! UsdMayaUtil::setName was creating a new object of type MFnMesh and set it's name.

const auto shapeName = TfStringPrintf("%sShape", primName.c_str());
const auto shapePath = prim.GetPath().AppendChild(TfToken(shapeName));
context->RegisterNewMayaNode(shapePath.GetString(), meshRead.meshObject());
context->RegisterNewMayaNode(meshRead.shapePath().GetString(), meshRead.meshObject());
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We now get the path from the meshRead and pass it in to be registered with the Maya mesh object.

MFnMesh meshFn(meshObj);
meshFn.setName(MString(shapeName.c_str()), false, &status);

return status;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was indeed a weird and almost useless function that I introduced. Sigh....

Copy link
Contributor

@mattyjams mattyjams left a comment

Choose a reason for hiding this comment

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

Cool, and all of our tests are now passing internally.

Just one tiny thing to possibly consider is whether the TranslatorMeshRead could be passed nullptr for the status parameter.

Other than that, looks good to me! Thanks @HamedSabri-adsk!

const MObject& stageNode,
const GfInterval& frameRange,
bool wantCacheAnimation,
MStatus * status)
Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like status could be passed nullptr so the sites where we dereference it below should probably check it first?:

if (status != nullptr) {

Or we could store it into the local stat first, and then check before any early return.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Awesome! Thanks @mattyjams

Good point, I initialized the status before passing it in to both meshRead and UsdMayaTranslatorUtil::CreateTransformNode. Please see 11b49c5

@kxl-adsk kxl-adsk merged commit ff90ae5 into dev Mar 21, 2020
@kxl-adsk kxl-adsk deleted the sabrih/MAYA-101846/pxr_mesh_translator_read branch March 21, 2020 17:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core Related to core library import-export Related to Import and/or Export
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants