Building on an earlier post. Here I show how the simple printing of vertex differences can be useful to help make tweaks of a blendshape after seeing the blendshape fully active. Hope this is helpful. The formula I used here is basically:
result = unposed - ( posed - sculpted )
Then when the result, and posed are fully on of blendhshape we get the edited sculpted pose we want.
cheers,
-Nate
/**@file makeCorrectiveCmd.cpp @note select posed,sculpted, then unposed polygon and type in mel -- makeCorrectiveCmd; currently it changes unposed to be a corrective @author Nathaniel O. Anozie (ogbonnawork at gmail dot com) @note Modify at your own risk @note date created: 07/23/2013 */ //last updated: 07/23/2013 -- added initial release result = unposed(third) - [ posed(first) - sculpted(second) ] //remove space after <, was put so didnt dissapear here #include < maya/MSimple.h> #include < maya/MGlobal.h> #include < maya/MSelectionList.h> #include < maya/MDagPath.h> #include < maya/MFnMesh.h> #include < maya/MItMeshVertex.h> #include < maya/MPoint.h> DeclareSimpleCommand( makeCorrectiveCmd, "Nathaniel Anozie", "1.0"); MStatus makeCorrectiveCmd::doIt( const MArgList& ) { MStatus stat; //------get the required polygons selected MSelectionList selList; stat = MGlobal::getActiveSelectionList(selList); MString errorMsg = "Error select posed,sculpted, then unposed polygon !!!\n"; if(MS::kSuccess != stat){ MGlobal::displayError(errorMsg); return stat; } //need certain number of things if( selList.length() != 3 ){ MGlobal::displayError(errorMsg); return stat; } //make sure selected are polygons, needed to tell the number of vertices of polygon MDagPath firstPath; //hold path stat = selList.getDagPath(0, firstPath); if(MS::kSuccess != stat){ MGlobal::displayError(errorMsg); return stat; } if( firstPath.hasFn(MFn::kMesh) ){} else{ MGlobal::displayError(errorMsg); return MS::kFailure; } MDagPath secondPath; stat = selList.getDagPath(1, secondPath); if(MS::kSuccess != stat){ MGlobal::displayError(errorMsg); return MS::kFailure; } if( secondPath.hasFn(MFn::kMesh) ){} else{ MGlobal::displayError(errorMsg); return MS::kFailure; } MDagPath thirdPath; stat = selList.getDagPath(2, thirdPath); if(MS::kSuccess != stat){ MGlobal::displayError(errorMsg); return MS::kFailure; } if( thirdPath.hasFn(MFn::kMesh) ){} else{ MGlobal::displayError(errorMsg); return MS::kFailure; } //-------- //---make sure selected have identical number of vertices, kind of like making sure they have same topology but not really //first poly data int firstNumVtx; //hold number of vertices MFnMesh firstMeshFn( firstPath ); //make and set function set used to get vertex info firstNumVtx = firstMeshFn.numVertices(); MGlobal::displayInfo(MString("Poly Number of Vertices Are:")+firstNumVtx+"\n"); //second poly data int secondNumVtx; //hold number of vertices MFnMesh secondMeshFn( secondPath ); //make and set function set used to get vertex info secondNumVtx = secondMeshFn.numVertices(); if(firstNumVtx != secondNumVtx){ MGlobal::displayError("Requires Identical Number Vtx of Selected!!!\n"); return MS::kFailure; } //third poly data int thirdNumVtx; //hold number of vertices MFnMesh thirdMeshFn( thirdPath ); //make and set function set used to get vertex info thirdNumVtx = thirdMeshFn.numVertices(); if(firstNumVtx != thirdNumVtx){ MGlobal::displayError("Requires Identical Number Vtx of Selected!!!\n"); return MS::kFailure; } //--- //---all is good so store local positions for both selected things //result data MPoint* result;//will hold the result delete [] result; result = new MPoint[firstNumVtx]; //first vertex data MPoint* firstLocalVtxPositions; delete [] firstLocalVtxPositions; firstLocalVtxPositions = new MPoint[firstNumVtx]; MObject firstVtx; //hold each vertex int i = 0; //hold index we will use soon MItMeshVertex firstVtxIter( firstPath, firstVtx, &stat); if( MS::kSuccess == stat ){ i=0; for( ; !firstVtxIter.isDone(); firstVtxIter.next() ){ firstLocalVtxPositions[i] = firstVtxIter.position( MSpace::kObject); //local space i++; } } else{ MGlobal::displayError("Vertex Iterator Error!!!\n"); return stat; } //second vertex data MPoint* secondLocalVtxPositions; delete [] secondLocalVtxPositions; secondLocalVtxPositions = new MPoint[secondNumVtx]; MObject secondVtx; MItMeshVertex secondVtxIter( secondPath, secondVtx, &stat); if( MS::kSuccess == stat ){ i=0; for( ; !secondVtxIter.isDone(); secondVtxIter.next() ){ secondLocalVtxPositions[i] = secondVtxIter.position( MSpace::kObject); //local space i++; } } else{ MGlobal::displayError("Vertex Iterator Error!!!\n"); return stat; } //----- //compute result i = 0; MPoint a; MPoint b; MPoint diff; for( i = 0; i < firstNumVtx; i++) { a = firstLocalVtxPositions[i]; b = secondLocalVtxPositions[i]; //first poly minus second poly //if used MPoint minus MPoint would get an MVector a little more to do diff.x = a.x - b.x; diff.y = a.y - b.y; diff.z = a.z - b.z; result[i] = diff; MGlobal::displayInfo(MString("Vtx Differences Are:") + diff.x + "," + diff.y + "," + diff.z + "\n"); } //compute new pose MObject thirdVtx; MItMeshVertex thirdVtxIter( thirdPath, thirdVtx, &stat); if( MS::kSuccess == stat ){ i=0; MPoint pnt; MPoint newPnt; diff.x = 0.0; diff.y = 0.0; diff.z = 0.0; for( ; !thirdVtxIter.isDone(); thirdVtxIter.next() ){ //new unposed = [ posed(first) - sculpted(second) ] + unposed(third) pnt = thirdVtxIter.position( MSpace::kObject); diff = result[i]; //newPnt.x = diff.x + pnt.x; //newPnt.y = diff.y + pnt.y; //newPnt.z = diff.z + pnt.z; newPnt.x = pnt.x - diff.x; newPnt.y = pnt.y - diff.y; newPnt.z = pnt.z - diff.z; stat = thirdVtxIter.setPosition( newPnt, MSpace::kObject); if( MS::kSuccess != stat ){ MGlobal::displayError("Error setting Vertex\n -- Exiting!!!\n"); return stat; } i++; } } else{ MGlobal::displayError("Vertex Iterator Error!!!\n"); return stat; } return stat; }
Inspired by Christian Breitling (b-ling dot com) and Chad Vernon (chadvernon dot com)