您的位置:首页 > 其它

用六种算法实现maya动画曲线光滑

2016-05-24 20:29 411 查看
在使用动补数据的时候,经常会有手脚等部位的抖动,特意写了个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>

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 );
//MItDependencyNodes getAllObjectsAnimCurves();
//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/MSelectionList.h>
#include <maya/MItSelectionList.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";

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);
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 );

pAnimCache = new MAnimCurveChange();
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);
}
}
}
MGlobal::displayInfo(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.reset(); 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[j];
//
//                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”。

结果如下:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: