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

Added Blendshape export functionality #1016

Merged
merged 34 commits into from
Jan 17, 2021
Merged

Conversation

ysiewappl
Copy link
Contributor

@ysiewappl ysiewappl commented Dec 17, 2020

Hi all:

This is a continuation of the PR originally submitted at #952. Please refer to that one for more comments and previous discussion. This update fixes both "baked" blendshape targets and also an issue that sees blendshape offsets being doubled-up if the first frame being exported has any of the blendshape targets activated as well.

This PR adds support for exporting blendshapes out of Maya in line with the UsdSkelBlendShape schema for a variety of scenarios, including single base - single target, single base - multiple targets (incl. inbetween), multiple base - multiple targets, "baked" blendshape targets (i.e. no explicit target meshes in the scene), writing out combined extents, and writing out animation. Some limitations include:

Currently no support for "chained" blendshape deformations or other intermediate deformers in the deform stack.
"Layered" blendshape deformers will end up having individual shapes baked out individually.
Combined extents only take blendshapes into account and no other deformers.
I ran into an issue while implementing this, which can be summarized by the following:

Maya does not evaluate certain plugs on a blendshape node until evaluation of the node is forced. This is a problem because certain information like the indices of components on a blendshape cannot be determined unless the blendshape node itself is evaluated.

Steps to Reproduce:

Create a cube and a blendshape for it with one vertex moved.

Run the following code:

import maya.OpenMaya as om
sl = om.MSelectionList()
p = om.MPlug()
sl.add('blendShape1.inputTarget[0].inputTargetGroup[0].inputTargetItem[6000].inputComponentsTarget')
sl.getPlug(0, p)

dh = p.asMDataHandle()
d= dh.data()
fn = om.MFnComponentListData(d)
print fn.length()

You should have gotten an error when attempting to attach the function set. Now twiddle the weight on the blendshape deformer and twiddle it back and then run the same code again.
The code suddenly works without any other modifications to the scene or its data.
We're currently working around this by basically twiddling the blendshape node's weights through OpenMaya prior to export, which is not ideal since that could potentially be expensive for denser meshes. Hopefully someone from ADSK could help advise here on any possible remedies.

Please review and raise any concerns.

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.

Just a few cosmetic notes from me, but otherwise looks good.

I noticed that there are still a fair number of TF_VERIFYs that execution will plow right through where maybe we'd want to check its return value and return/continue/etc if the check fails.

I'll defer again to @williamkrick to approve though, since he's far more knowledgeable on the details of this than me.

Thanks @ysiewappl!

#include <unordered_map>
#include <vector>

#define MAYA_BLENDSHAPE_EVAL_HOTFIX 1
Copy link
Contributor

Choose a reason for hiding this comment

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

constexpr int or bool here?

I see this gets used to compile out the call to mayaBlendShapeTriggerAllTargets() below, but if we set this to 0/false, I would guess we'd see complaints from the compiler about the function being unused. Any reason not to make that just a regular if()?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I just realized that this isn't my intention; it's meant to actually make sure the code isn't included at all in the final plugin if the #define is on. I've gone ahead and enclosed the function under that #define as well.

unsigned int numInTgtGrps = plgInTgtGrps.numElements();
if (numInTgtGrps == 0) {
continue;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I think what you have written here will work, but please test a scene were you have a weight value for a non-existent target group. Maya can handle that case (by ignoring the entry which I think you are successfully doing here) so there could be scenes out there with more weights then targets.

// TODO: (yliangsiew) For multiple blend shape deformers, what do we do?
// Do we collapse the shapes from multiple blend targets together, or just
// write out only the "closest" blendshape deformer's targets? Or just write all
// of them and print this warning to end-users?
Copy link
Contributor

Choose a reason for hiding this comment

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

I think eventually we'll want a 1 to 1 mapping between deformer nodes in Maya and UsdSkel compute items written to USD. Doing a special case to merge two blend shapes in a row won't help when there's a wrap deformer between them. We'll eventually have to support writing a graph of UsdSkel compute items to the USD file.

I think this change, even though it has a bunch of limitations, is a good step towards that final goal.

// NOTE: (yliangsiew) Because UsdSkelBlendShape does not
// support animated targets (the `normalOffsets` and
// `offsets` attributes are defined as uniforms), we cannot
// fully support it in the exporter either.
Copy link
Contributor

Choose a reason for hiding this comment

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

Ah that is an interesting limitation. We'd need UsdSkelBlendShape targets to accept the same data type that the input & output geometry are to have a more general solution where we can connect a graph of computes together.

@williamkrick
Copy link
Contributor

@ysiewappl there is some discussion we need to have before this change is merged.

It was my understanding from in December that after the original commit for blend shape support you would be continuing on with more work. Is all the work you have planned now included in this pull request or is more work coming?

If you are planning to do more work then I am fine with the minor style comments I've made here being fixed in the next change. If this is the end of the work then I'd like to see those loose ends tied off before this is merged.

After the changes get merged our MayaUSD QAs will test this functionality and be logging bugs for things that don't work. I need you to provide a list of what is expected to work and what is not expected to work for our QAs to validate. Clearly everything in Maya is not supported, so we need to clearly state the limitations of the blend shape export so we know what to expect, and so that other users of MayaUSD know what to expect. Something like what are the supported deformation setups (blendShape->skinCluster->mesh ?) would be perfect.

@dgovil
Copy link
Collaborator

dgovil commented Jan 7, 2021

@williamkrick just as a heads up, Yi Liang is out for a little bit longer so I'll wait for him to be back to respond accurately.

I believe all of our intended changes are represented in this PR.

@williamkrick
Copy link
Contributor

@ysiewappl yes a test scene with examples would be fantastic. Can provide a brief text overview of what is expected to work vs. not work as well? You don't have to include everything but just give a high level idea of what to expect.

After that I approve of this PR being merged.

@ysiewappl
Copy link
Contributor Author

@ysiewappl yes a test scene with examples would be fantastic. Can provide a brief text overview of what is expected to work vs. not work as well? You don't have to include everything but just give a high level idea of what to expect.
Hi:

I've updated the unit test for the blendshapes a tiny bit, and uploaded one of
the test scenes I use for verifying output. The scene contains various basic
test cases, which include:

  • Single base to single target, non-animated/animated
  • Single base to multiple in-betweens, non-animated/animated
  • Multiple bases to multiple targets, animated
  • A setup where there is an extra squash deformer in the stack
  • A setup with "baked" blendshape targets
  • A setup with a skinned cube with "baked" blendshape targets

… combinations of meshes with and without blendshapes at the same time.

made error messages more verbose
Copy link

@kxl-adsk kxl-adsk left a comment

Choose a reason for hiding this comment

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

@ysiewappl I tested your build against older versions of USD (the minimum version we support is 19.11) and I'm getting build failure. We don't have it yet covered by PF, so this is why you didn't see it in reports. Here is what I did locally to pass the build error (and it's what will have to be done before we can merge the change)

index 0e6b2081d..9da727ff7 100644
--- a/lib/usd/translators/meshWriter_BlendShapes.cpp
+++ b/lib/usd/translators/meshWriter_BlendShapes.cpp
@@ -397,7 +397,7 @@ MStatus mayaGetBlendShapeInfosForMesh(
                     plgInComponentsTgt, indices);
                 CHECK_MSTATUS_AND_RETURN_IT(stat);
                 for (unsigned int m = 0; m < indices.length(); ++m) {
-                    meshTargetDatum.indices.emplace_back(indices[m]);
+                    meshTargetDatum.indices.push_back(indices[m]);
                 }

                 unsigned int numComponentIndices = meshTargetDatum.indices.size();
@@ -446,7 +446,7 @@ MStatus mayaGetBlendShapeInfosForMesh(
                     MPointArray ptDeltas = fnPtArrayData.array();
                     for (unsigned int m = 0; m < numComponentIndices; ++m) {
                         MPoint pt = ptDeltas[m];
-                        meshTargetDatum.ptOffsets.emplace_back(GfVec3f(pt.x, pt.y, pt.z));
+                        meshTargetDatum.ptOffsets.push_back(GfVec3f(pt.x, pt.y, pt.z));
                     }
                 }
                 weightInfo.targets.emplace_back(meshTargetDatum);

In addition, I'm seeing the new test (testUsdExportBlendshapes) failing. I will re-trigger the PF once you fix the build error reported above to confirm.

@ysiewappl
Copy link
Contributor Author

There's several points where I call emplace_back instead of push_back. Are those really the only two points of failure? I would have expected to see some other calls fail as well if c++17 support wasn't assumed. Nevertheless I've changed them all to use push_back instead just in case.

@ysiewappl ysiewappl requested a review from kxl-adsk January 14, 2021 18:06
@ysiewappl
Copy link
Contributor Author

@kxl-adsk I'm not sure why the Windows builds failed, but I made a commit based on a guess (regarding the filename passed to MFileIO::open. If you could help confirm the actual issue (since I don't have a Windows machine here for testing the build against), I'd very much appreciate it so I can get everything resolved and finally get this PR merged. Thanks!

Copy link

@kxl-adsk kxl-adsk left a comment

Choose a reason for hiding this comment

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

Thank you, builds and tests are passing now.

@kxl-adsk
Copy link

FWIW. You didn't have to replace all emplac_back. Just the two I mentioned in my comment was enough.

@kxl-adsk
Copy link

I'm going to merge this change and pass it to our QA. I will share the files and short description you provided. If you can think of anything else to mention when testing, please don't hesitate to let me know.

Finally, thank you for your hard work on this one.

@kxl-adsk kxl-adsk merged commit 1ac15c9 into Autodesk:dev Jan 17, 2021
@dgovil
Copy link
Collaborator

dgovil commented Jan 17, 2021

Awesome! Thank you everyone for your feedback on this, and @ysiewappl for putting this all together.

@ysiewappl ysiewappl deleted the blendshapes branch January 19, 2021 17:59
mattyjams added a commit to mattyjams/maya-usd that referenced this pull request Jan 20, 2021
This repairs some minor damage from the merge of PR Autodesk#1016 where the new
testUsdExportBlendshapes test replaced testUsdExportCamera rather than just
being added.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
import-export Related to Import and/or Export
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants