Skip to content

Commit

Permalink
Merge pull request #3954 from Autodesk/barbalt/EMSUSD-1712/reimport-b…
Browse files Browse the repository at this point in the history
…lendshape-fix

EMSUSD-1712 Reimport blendshape issues
  • Loading branch information
seando-adsk authored Oct 10, 2024
2 parents b8b343c + cc082a0 commit 6c0060c
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 26 deletions.
4 changes: 4 additions & 0 deletions lib/mayaUsd/fileio/translators/translatorBlendShape.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ bool UsdMayaTranslatorBlendShape::Read(const UsdPrim& meshPrim, UsdMayaPrimReade
const auto blendShapeObj
= blendFn.create(objToBlendShape, MFnBlendShapeDeformer::kLocalOrigin, &status);
CHECK_MSTATUS_AND_RETURN(status, false)
MFnDependencyNode blendShapeDepNodeFn;
blendShapeDepNodeFn.setObject(blendShapeObj);
blendShapeDepNodeFn.setName(MString(
TfStringPrintf("%s_Deformer", meshPrim.GetPath().GetElementString().c_str()).c_str()));

MObject deformedMeshObject;
VtVec3fArray deltaPoints, deltaNormals;
Expand Down
27 changes: 22 additions & 5 deletions lib/mayaUsd/fileio/translators/translatorSkel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include <mayaUsd/fileio/translators/translatorUtil.h>
#include <mayaUsd/fileio/translators/translatorXformable.h>
#include <mayaUsd/fileio/utils/meshWriteUtils.h>
#include <mayaUsd/undo/OpUndoItems.h>
#include <mayaUsd/utils/util.h>

Expand All @@ -28,21 +29,18 @@
#include <pxr/usd/usdSkel/topology.h>

#include <maya/MDGModifier.h>
#include <maya/MDagModifier.h>
#include <maya/MDoubleArray.h>
#include <maya/MEulerRotation.h>
#include <maya/MFnAnimCurve.h>
#include <maya/MFnBlendShapeDeformer.h>
#include <maya/MFnComponentListData.h>
#include <maya/MFnDependencyNode.h>
#include <maya/MFnDoubleArrayData.h>
#include <maya/MFnMatrixData.h>
#include <maya/MFnMesh.h>
#include <maya/MFnNumericAttribute.h>
#include <maya/MFnSingleIndexedComponent.h>
#include <maya/MFnSkinCluster.h>
#include <maya/MFnTransform.h>
#include <maya/MMatrix.h>
#include <maya/MObjectHandle.h>
#include <maya/MPlug.h>
#include <maya/MPlugArray.h>

Expand Down Expand Up @@ -1317,8 +1315,27 @@ bool UsdMayaTranslatorSkel::CreateSkinCluster(

const auto skinSrc = shapeToSkinInMesh.source();
if (!skinSrc.isNull()) {
MObjectArray blendShapeDeformers;
UsdMayaMeshWriteUtils::getBlendShapesOfMesh(
shapeToSkin, blendShapeDeformers, &status);

dgMod.disconnect(skinSrc, shapeToSkinInMesh);
status = dgMod.connect(skinSrc, groupPartsInputGeometry);

// If the mesh has blendShapes, it has already been created prior to this step.
// When that's the case, we need to disconnect the blendShape outputGeometry
// and connect it to the groupParts.inputGeometry which drives the skel/skinCluster.
// Then, the output of the groupParts will be connected to the end mesh.
if (blendShapeDeformers.length() > 0) {
MFnBlendShapeDeformer blendShapeFn(blendShapeDeformers[0], &status);
MPlug blenshapeOutputPlug
= blendShapeFn.findPlug(_MayaTokens->outputGeometry, &status);
MPlug blenshapeOutputPlug0
= blenshapeOutputPlug.elementByLogicalIndex(0, &status);

status = dgMod.connect(blenshapeOutputPlug0, groupPartsInputGeometry);
} else {
status = dgMod.connect(skinSrc, groupPartsInputGeometry);
}
CHECK_MSTATUS_AND_RETURN(status, false);
} else {
// For the case where there were no blendShapes attached to the mesh, create a rest
Expand Down
30 changes: 30 additions & 0 deletions lib/mayaUsd/fileio/utils/meshWriteUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,36 @@ MStatus UsdMayaMeshWriteUtils::getSkinClustersUpstreamOfMesh(
return stat;
}

void UsdMayaMeshWriteUtils::getBlendShapesOfMesh(
const MObject& mesh,
MObjectArray& blendShapes,
MStatus* stat)
{
if (mesh.isNull() || !mesh.hasFn(MFn::kMesh)) {
if (stat) {
*stat = MStatus::kInvalidParameter;
}
return;
}

blendShapes.clear();
MObject searchObj = MObject(mesh);
MItDependencyGraph itDg(
searchObj,
MFn::kInvalid,
MItDependencyGraph::kUpstream,
MItDependencyGraph::kDepthFirst,
MItDependencyGraph::kNodeLevel,
stat);
while (!itDg.isDone()) {
MObject curNode = itDg.currentItem();
if (curNode.hasFn(MFn::kBlendShape)) {
blendShapes.append(curNode);
}
itDg.next();
}
}

MBoundingBox UsdMayaMeshWriteUtils::calcBBoxOfMeshes(const MObjectArray& meshes)
{
unsigned int numMeshes = meshes.length();
Expand Down
6 changes: 4 additions & 2 deletions lib/mayaUsd/fileio/utils/meshWriteUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,17 @@ MStatus getSkinClusterConnectedToMesh(const MObject& mesh, MObject& skinCluster)
MAYAUSD_CORE_PUBLIC
MStatus getSkinClustersUpstreamOfMesh(const MObject& mesh, MObjectArray& skinClusters);

MAYAUSD_CORE_PUBLIC
void getBlendShapesOfMesh(const MObject& mesh, MObjectArray& blendShapes, MStatus* stat);

/**
* Calculates the union bounding box of a given array of meshes.
*
* @param meshes The meshes to calculate the union bounding box of.
*
* @return The union bounding box.
*/
MAYAUSD_CORE_PUBLIC
MBoundingBox calcBBoxOfMeshes(const MObjectArray& meshes);
MAYAUSD_CORE_PUBLIC MBoundingBox calcBBoxOfMeshes(const MObjectArray& meshes);

/// Helper method for getting Maya mesh normals as a VtVec3fArray.
MAYAUSD_CORE_PUBLIC
Expand Down
13 changes: 3 additions & 10 deletions lib/usd/translators/meshWriterBlendShapes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -666,16 +666,9 @@ MObject PxrUsdTranslators_MeshWriter::writeBlendShapeData(UsdGeomMesh& primSchem
MString curTargetLongNameMStr;
if (!targetMesh.isNull()) {
MFnDagNode dagNode(targetMesh);
MString nodeName;
if (dagNode.parentCount() > 0) {
MFnDagNode parentDagNode(dagNode.parent(0));
curTargetNameMStr
= UsdMayaUtil::GetUniqueNameOfDagNode(parentDagNode.object());
curTargetLongNameMStr = curTargetNameMStr;
} else {
curTargetNameMStr = UsdMayaUtil::GetUniqueNameOfDagNode(targetMesh);
curTargetLongNameMStr = curTargetNameMStr;
}
curTargetNameMStr = UsdMayaUtil::GetUniqueNameOfDagNode(targetMesh);
curTargetLongNameMStr = curTargetNameMStr;

// NOTE: (yliangsiew) Because UsdSkelBlendShape does not
// support animated targets (the `normalOffsets` and
// `offsets` attributes are defined as uniforms), we cannot
Expand Down
4 changes: 2 additions & 2 deletions test/lib/usd/translators/testUsdExportBlendshapes.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def testBlendShapesExport(self):
cmds.mayaUSDExport(f=temp_file, v=True, sl=True, ebs=True, skl="auto")

stage = Usd.Stage.Open(temp_file)
prim = stage.GetPrimAtPath("/root/base/blend")
prim = stage.GetPrimAtPath("/root/base/blendShape")
offsets = prim.GetAttribute("offsets").Get()

for i, coords in enumerate(offsets):
Expand All @@ -68,7 +68,7 @@ def testBlendShapesExport(self):
"""
Sample BlendShape prim:
def BlendShape "blend"
def BlendShape "blendShape"
{
uniform vector3f[] normalOffsets = [(0, 0, 0), (0, 0, 0), (0, 0, 0)]
uniform vector3f[] offsets = [(0, -0.25, 0), (0, -0.25, 0), (0, 0.25, 0)]
Expand Down
14 changes: 7 additions & 7 deletions test/lib/usd/translators/testUsdImportBlendShapes.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,28 +66,28 @@ def test_BlendShapesImport(self):
skinningQuery = skelCache.GetSkinningQuery(meshPrim)
self.assertTrue(skinningQuery)

self.assertEqual(cmds.nodeType("blendShape1"), "blendShape")
self.assertEqual(cmds.nodeType("b1_Deformer"), "blendShape")

regularShape = sorted(
cmds.listConnections(
"blendShape1.inputTarget[0].inputTargetGroup[0].inputTargetItem[6000].inputGeomTarget",
"b1_Deformer.inputTarget[0].inputTargetGroup[0].inputTargetItem[6000].inputGeomTarget",
destination=False, source=True, plugs=True))
self.assertEqual(regularShape, ['Box0002.worldMesh'])

inBetween = sorted(
cmds.listConnections(
"blendShape1.inputTarget[0].inputTargetGroup[0].inputTargetItem[4000].inputGeomTarget",
"b1_Deformer.inputTarget[0].inputTargetGroup[0].inputTargetItem[4000].inputGeomTarget",
destination=False, source=True, plugs=True))
self.assertEqual(inBetween, ['IBT_1.worldMesh'])

cmds.currentTime(0)
self.assertEqual(sorted(cmds.getAttr("blendShape1.weight")[0]), [-1.0])
self.assertEqual(sorted(cmds.getAttr("b1_Deformer.weight")[0]), [-1.0])
cmds.currentTime(3)
self.assertEqual(sorted(cmds.getAttr("blendShape1.weight")[0]), [-0.14404296875])
self.assertEqual(sorted(cmds.getAttr("b1_Deformer.weight")[0]), [-0.14404296875])
cmds.currentTime(5)
self.assertEqual(sorted(cmds.getAttr("blendShape1.weight")[0]), [0.13427734375])
self.assertEqual(sorted(cmds.getAttr("b1_Deformer.weight")[0]), [0.13427734375])
cmds.currentTime(8)
self.assertEqual(sorted(cmds.getAttr("blendShape1.weight")[0]), [1.0])
self.assertEqual(sorted(cmds.getAttr("b1_Deformer.weight")[0]), [1.0])


if __name__ == '__main__':
Expand Down

0 comments on commit 6c0060c

Please sign in to comment.