-
Notifications
You must be signed in to change notification settings - Fork 202
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
Conversation
…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.
There was a problem hiding this 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.
lib/fileio/utils/meshUtil.cpp
Outdated
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; | ||
} | ||
|
There was a problem hiding this comment.
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
?
There was a problem hiding this comment.
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.
lib/fileio/utils/meshUtil.cpp
Outdated
|
||
MStatus status; | ||
|
||
MFnMesh meshFn(meshObj); |
There was a problem hiding this comment.
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()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please see 7be630d.
#include "../utils/meshUtil.h" | ||
#include "../utils/readUtil.h" |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
…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.
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. |
… name wasn't set properly.
} | ||
|
||
// store the path | ||
m_shapePath = prim.GetPath().AppendChild(TfToken(shapeName)); |
There was a problem hiding this comment.
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.
lib/usd/translators/meshReader.cpp
Outdated
// shape name | ||
const auto& primName = prim.GetName().GetString(); | ||
status = UsdMayaUtil::setName(meshRead.meshObject(), primName); | ||
CHECK_MSTATUS_AND_RETURN(status, false); |
There was a problem hiding this comment.
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()); |
There was a problem hiding this comment.
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.
lib/utils/util.cpp
Outdated
MFnMesh meshFn(meshObj); | ||
meshFn.setName(MString(shapeName.c_str()), false, &status); | ||
|
||
return status; |
There was a problem hiding this comment.
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....
There was a problem hiding this 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) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
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.