您的位置:首页 > 编程语言

检查模型点是否重合

2017-11-28 19:40 701 查看
  今天弄了个检查模型点是否有重合的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


  效果如下图:



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