检查模型点是否重合

  今天弄了个检查模型点是否有重合的command,好久不用API都陌生了;带有一个flag——shreshold,简写sr,设置需要检查两点之间的最小距离,再小于这个距离就算是重合的点了,command会将这两个点同时返回。源代码如下:

checkOverlapPoint.h

#ifndef _CHECK_OVERLAP_POINT
#define _CHECK_OVERLAP_POINT
#include <maya/MSelectionList.h>
#include <maya/MDagPath.h>
#include <maya/MPxCommand.h>
#include <maya/MSyntax.h>

using namespace std;

class CheckOverlapPoint: MPxCommand
{
public:
    CheckOverlapPoint();
    virtual ~CheckOverlapPoint();
    virtual MStatus doIt( const MArgList& );
    static void *creator(){return new CheckOverlapPoint();}
    static MSyntax newSyntax();
private:
    double shreshold;

};
#endif

checkOverLapPointCmd.cpp

#include "checkOverlapPoint.h"
#include <maya/MArgDatabase.h>
#include <maya/MGlobal.h>
#include <maya/MItSelectionList.h>
#include <maya/MFnPlugin.h>
#include <maya/MFnMesh.h>
#include <maya/MPointArray.h>
#include <maya/MIntArray.h>
#include <maya/MString.h>

const char *shresholdFlag = "-sr", *shresholdLongFlag = "shreshold";

CheckOverlapPoint::CheckOverlapPoint()
{
    shreshold = 0.003;
}

CheckOverlapPoint::~CheckOverlapPoint()
{
    shreshold = 0;
}

MSyntax CheckOverlapPoint::newSyntax()
{
    MSyntax syntax;
    syntax.addFlag( shresholdFlag, shresholdLongFlag, MSyntax::kDouble );
    return syntax;
}

MStatus CheckOverlapPoint::doIt(const MArgList &args)
{
    MStatus stat;
    MArgDatabase argData( syntax(), args, &stat );
    if( !stat )
        return stat;
    if( argData.isFlagSet( shresholdFlag ) ){
        argData.getFlagArgument( shresholdFlag, 0,  shreshold);
    }

    MSelectionList selection;
    MDagPath objectPath;
    MGlobal::getActiveSelectionList(selection);
    MItSelectionList iter(selection);
    MPointArray meshPoints, copyPoints;
    double pointDistance;
    MIntArray overlapPointIDs;
    MStringArray meshOverlapPoints;

    for(unsigned int j = 0; j < selection.length(); j++)
    {
        unsigned int index = 1;
        meshPoints.clear();
        copyPoints.clear();
        overlapPointIDs.clear();
        selection.getDagPath(j, objectPath);
        MFnMesh objectMesh(objectPath);

        objectMesh.getPoints(meshPoints, MSpace::kWorld);
        CHECK_MSTATUS_AND_RETURN_IT(copyPoints.copy(meshPoints));
        for (unsigned int k = 0; k < meshPoints.length(); k ++){
            copyPoints.remove(0);
            for (unsigned int l = 0; l < copyPoints.length(); l ++){
                if (k == l){
                    continue;
                }
                pointDistance = meshPoints[k].distanceTo(copyPoints[l]);
                if (pointDistance < shreshold){
                    overlapPointIDs.append(k);
                    overlapPointIDs.append(l + index);

                }
            }
            index ++;
        }
        MString modelName = objectMesh.partialPathName();
        for (unsigned int m = 0; m < overlapPointIDs.length(); m++){
            MString pointName;
            pointName = pointName + modelName.asChar() + ".vtx[" + overlapPointIDs[m] + "]";
            meshOverlapPoints.append(pointName);
        }
    }
    setResult(meshOverlapPoints);
    return stat;
}

MStatus initializePlugin( MObject obj )
{
    MFnPlugin plugin( obj, "Lulongfei", "1.0" );
    MStatus stat;
    stat = plugin.registerCommand( "checkOverlapPoint", CheckOverlapPoint::creator, CheckOverlapPoint::newSyntax );
    if ( !stat )
        stat.perror( "registerCommand failed" );
    return stat;
}

MStatus uninitializePlugin( MObject obj )
{
    MFnPlugin plugin( obj );
    MStatus stat;
    stat = plugin.deregisterCommand( "checkOverlapPoint" );
    if ( !stat )
        stat.perror( "deregisterCommand failed" );
    return stat;
}

最开始采用的是这种遍历,计算的次数为n的n次方;

for (unsigned int k = 0; k < meshPoints.length(); k ++){
      for (unsigned int l = 0; l < meshPoints.length(); l ++){
          if (k == l){
              continue;
          }
          pointDistance = meshPoints[k].distanceTo(meshPoints[l]);
          if (pointDistance < shreshold){
              overlapPointIDs.append(k);
          }
      }
}

发现这样的计算速度太慢于是改进了下,这样计算的次数是n的阶乘,不过内存开销是原来的两倍,以内存换速度了;

for (unsigned int k = 0; k < meshPoints.length(); k ++){
     copyPoints.remove(0);
     for (unsigned int l = 0; l < copyPoints.length(); l ++){
         if (k == l){
             continue;
         }
         pointDistance = meshPoints[k].distanceTo(copyPoints[l]);
         if (pointDistance < shreshold){
             overlapPointIDs.append(k);
             overlapPointIDs.append(l + index);

         }
     }
     index ++;
 }

  最后在maya里返回的是个列表或数组,用户可以根据这个结果做进一步的操作,是merge还是选择都行,性能上来说还可以,比python版的API能快至少100倍。
  使用如下:

cmds.checkOverlapPoint(sr=0.003)  # python
checkOverlapPoint -sr 0.003  // Mel

  效果如下图:

这里写图片描述

这里写图片描述

猜你喜欢

转载自blog.csdn.net/lulongfei172006/article/details/78658293