在使用动补数据的时候,经常会有手脚等部位的抖动,特意写了个command,直接将动画曲线平滑一下,不用动画师大量的进行手调,下面是代码:
smoothAnimationCurveCmd.h
#ifndef _smoothAnimationCurve_
#define _smoothAnimationCurve_
#include <maya/MPxCommand.h>
#include <maya/MObject.h>
#include <maya/MSyntax.h>
#include <maya/MFnAnimCurve.h>
#include <maya/MAnimCurveChange.h>
#include <maya/MItDependencyNodes.h>
#include <maya/MSelectionList.h>
#include <maya/MItSelectionList.h>
class SmoothAnimationCurveCmd: public MPxCommand
{
public:
SmoothAnimationCurveCmd();
virtual ~SmoothAnimationCurveCmd();
virtual MStatus doIt( const MArgList& );
virtual MStatus redoIt();
virtual MStatus undoIt();
virtual bool isUndoable() const { return true; }
static void *creator(){ return new SmoothAnimationCurveCmd; }
static MSyntax newSyntax();
MStatus compliceMethod( MFnAnimCurve &fnAnim, MAnimCurveChange *animCache );
MItSelectionList getSelectObjectsAnimCurves();
private:
MString type;
int method;
unsigned int iterations;
MAnimCurveChange* pAnimCache;
};
#endif
smoothAnimationCurveCmd.cpp
#include "smoothAnimationCurveCmd.h"
#include <maya/MGlobal.h>
#include <maya/MFnPlugin.h>
#include <maya/MDagPath.h>
#include <maya/MPlugArray.h>
#include <maya/MObjectArray.h>
#include <maya/MArgDatabase.h>
#include <maya/MAnimUtil.h>
using namespace std;
const char *typeFlag = "-t", *typeLongFlag = "-type";
const char *methodFlag = "-md", *methodLongFlag = "-method";
const char *iterationsFlag = "-it", *iterationsLongFlag = "-iterations";
const char *helpFlag = "-h", *helpLongFlag = "-help";
const char *helpText = "The smoothAnimCurve command is used to smooth animcurve."
"\nIt has three parameter."
"\nFlags:"
"\n -h -help "
"\n -it -iterations Int"
"\n -md -method Int"
"\n -t -type String"
"\nSupported Mode: sel(smooth animation curve only for selected objects)"
"\n all(smooth all animation curves which in the scene)"
"\nFor quick help use: help smoothAnimCurve";
SmoothAnimationCurveCmd::SmoothAnimationCurveCmd()
{
type = "all";
method = 1;
iterations = 1;
pAnimCache = NULL;
}
SmoothAnimationCurveCmd::~SmoothAnimationCurveCmd()
{
delete pAnimCache;
pAnimCache = NULL;
}
MSyntax SmoothAnimationCurveCmd::newSyntax()
{
MSyntax syntax;
syntax.addFlag( typeFlag, typeLongFlag, MSyntax::kString );
syntax.addFlag( methodFlag, methodLongFlag, MSyntax::kLong );
syntax.addFlag( iterationsFlag, iterationsLongFlag, MSyntax::kLong);
syntax.addFlag( helpFlag, helpLongFlag );
return syntax;
}
MStatus SmoothAnimationCurveCmd::doIt( const MArgList &args )
{
MStatus stat;
unsigned int j;
MArgDatabase argData( syntax(), args, &stat );
if( !stat )
return stat;
if ( argData.isFlagSet( typeFlag ) )
argData.getFlagArgument( typeFlag, 0, type );
if ( argData.isFlagSet( methodFlag ) )
argData.getFlagArgument( methodFlag, 0, method );
if ( argData.isFlagSet( iterationsFlag ) )
argData.getFlagArgument( iterationsFlag, 0, iterations );
if ( argData.isFlagSet(helpFlag) )
{
setResult( helpText );
return MS::kSuccess;
}
pAnimCache = new MAnimCurveChange();
if(type == "all"){
MItDependencyNodes animCurves(MFn::kAnimCurve);
for (; !animCurves.isDone(); animCurves.next())
{
MObject currentItem = animCurves.item();
if ( currentItem.isNull() )
{
continue;
}
MFnAnimCurve fnCurve (currentItem);
unsigned int numKeys = fnCurve.numKeys();
if (numKeys <= 2)
{
continue;
}
else
{
for (j = 0; j < iterations; j++)
{
compliceMethod(fnCurve, pAnimCache);
}
}
}
}
if(type == "sel"){
MObject mAnimCurveObj;
MItSelectionList animCurveTempIter = getSelectObjectsAnimCurves();
for(; animCurveTempIter.isDone() != true; animCurveTempIter.next()){
animCurveTempIter.getDependNode(mAnimCurveObj);
//cout << mAnimCurveObj.fullPathName() << endl;
if ( mAnimCurveObj.isNull() )
{
continue;
}
MFnAnimCurve fnCurve (mAnimCurveObj);
unsigned int numKeys = fnCurve.numKeys();
if (numKeys <= 2)
{
continue;
}
else
{
for (j = 0; j < iterations; j++)
{
compliceMethod(fnCurve, pAnimCache);
}
}
}
}
MGlobal::displayInfo(MString("type: ") + type + " " + MString("method: ") + method + " " + MString("interations: ") + iterations);
return stat;
}
MItSelectionList SmoothAnimationCurveCmd::getSelectObjectsAnimCurves()
{
MSelectionList selection;
MSelectionList animCurvesTemp;
/*selection.clear();
animCurvesTemp.clear();*/
MGlobal::getActiveSelectionList( selection );
MItSelectionList iter( selection );
unsigned int j, k;
for( ; !iter.isDone(); iter.next() )
{
MPlugArray mPlugArray;
MAnimUtil::findAnimatedPlugs( selection, mPlugArray );
for (j = 0; j < mPlugArray.length(); j++)
{
MObjectArray mObjArray;
MAnimUtil::findAnimation(mPlugArray[j], mObjArray);
for (k = 0; k < mObjArray.length(); k++ )
{
MObject animCurveNode = mObjArray[k];
if (!animCurveNode.hasFn (MFn::kAnimCurve))
{
continue;
}
//MFnAnimCurve animCurve (animCurveNode);
animCurvesTemp.add( animCurveNode );
//MGlobal::getSelectionListByName( animCurve.name(), animCurvesTemp);
}
}
}
MItSelectionList iterAnimCurvesTemp( animCurvesTemp);
//MItDependencyNodes iterAnimcurves( iterAnimCurvesTemp, MFn::kAnimCurve );
return iterAnimCurvesTemp;
}
MStatus SmoothAnimationCurveCmd::compliceMethod( MFnAnimCurve &fnAnim, MAnimCurveChange *pAnimCache)
{
MStatus stat;
unsigned int i;
double tempValue;
unsigned int numKeys = fnAnim.numKeys();
//pAnimCache = new MAnimCurveChange();
switch ( method )
{
case 0://三点线性
for (i = 2; i < numKeys - 2; i++)
{
tempValue = (fnAnim.value(i - 1) + fnAnim.value(i) + fnAnim.value(i + 1))/3;
fnAnim.setValue(i, tempValue, pAnimCache);
}
break;
case 1://五点二次滤波
for (i = 2; i < numKeys - 2; i++)
{
tempValue = (12*(fnAnim.value(i - 1) + fnAnim.value(i + 1)) -3*(fnAnim.value(i - 2) + fnAnim.value(i + 2)) + 17*fnAnim.value(i))/35;
fnAnim.setValue(i, tempValue, pAnimCache);
}
break;
case 2://五点钟形滤波
for (i = 2; i < numKeys - 2; i++)
{
tempValue = (0.11f*(fnAnim.value(i - 2) + fnAnim.value(i + 2)) + 0.24f*(fnAnim.value(i - 1) + fnAnim.value(i + 1)) + 0.3f*fnAnim.value(i));
fnAnim.setValue(i, tempValue, pAnimCache);
}
break;
case 3://三点汉明滤波
for (i = 2; i < numKeys - 2; i++)
{
tempValue = (0.07f*(fnAnim.value(i - 1)) + 0.86f*(fnAnim.value(i)) + 0.07f*(fnAnim.value(i + 1)));
fnAnim.setValue(i, tempValue, pAnimCache);
}
break;
case 4://三点钟形滤波
for (i = 2; i < numKeys - 2; i++)
{
tempValue = 0.212f*fnAnim.value(i - 1) + 0.576f*fnAnim.value(i) + 0.212*fnAnim.value(i + 1);
fnAnim.setValue(i, tempValue, pAnimCache);
}
break;
default://五点汉明滤波
for (i = 2; i < numKeys - 2; i++)
{
tempValue = 0.04f*(fnAnim.value(i - 2) + fnAnim.value(i + 2)) + 0.24f*(fnAnim.value(i - 1) + fnAnim.value(i + 1)) + 0.44f*(fnAnim.value(i));
fnAnim.setValue(i, tempValue, pAnimCache);
}
break;
}
return stat;
}
MStatus SmoothAnimationCurveCmd::undoIt()
{
if( pAnimCache != NULL )
pAnimCache -> undoIt();
return MS::kSuccess;
}
MStatus SmoothAnimationCurveCmd::redoIt()
{
if( pAnimCache != NULL )
pAnimCache -> redoIt();
return MS::kSuccess;
}
MStatus initializePlugin( MObject obj )
{
MFnPlugin plugin( obj, "Lulongfei", "1.0" );
MStatus stat;
stat = plugin.registerCommand( "smoothAnimCurve", SmoothAnimationCurveCmd::creator, SmoothAnimationCurveCmd::newSyntax );
if ( !stat )
stat.perror( "registerCommand failed" );
return stat;
}
MStatus uninitializePlugin( MObject obj )
{
MFnPlugin plugin( obj );
MStatus stat;
stat = plugin.deregisterCommand( "smoothAnimCurve" );
if ( !stat )
stat.perror( "deregisterCommand failed" );
return stat;
}
使用的时候mel用:smoothAnimCurve -md 0 -t “all” -it 1
python用:cmds.smoothAnimCurve(md = 0, t = “all”, it = 1)
md为使用的方法,从0到5, it为迭代的次数,也就是你想进行几次光滑处理,type是类型,是“all”, 还是“select”。
结果如下:
编译好的插件链接:
版权声明:本文为lulongfei172006原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。