maya中的重叠顶点

Overlapping vertices in maya

我想找到距离小于 0.0003 和 return 的所有顶点作为列表。我使用以下算法,但对于大场景来说速度很慢。你有什么提高速度的秘诀吗?

listOfAllMesh = cmds.ls(geometry=True,type="mesh")
overlapping = []
for meshToCek in listOfAllMesh:
    listOFVertex=[]
    cmds.select(meshToCek)
    mel.eval("ConvertSelectionToVertices")
    AllVertexes = cmds.ls(selection=True, flatten=True)
    listOFVertex.append(AllVertexes[0])
    Flag=False
    for VertexToCek in AllVertexes[1:]:
        c1=cmds.xform(VertexToCek, q=True, os=True, a=True, t=True)
        for cek in listOFVertex:
            c2=cmds.xform(cek, q=True, os=True, a=True, t=True)
            distance = math.sqrt(math.pow(c2[0] - c1[0], 2) + math.pow(c2[1] - c1[1], 2) + math.pow(c2[2] - c1[2], 2))
            if distance<0.0003:
                overlapping.append(VertexToCek)
                overlapping.append(cek)
                Flag=True
        if not Flag:
            listOFVertex.append(VertexToCek)
            Flag=False
return overlapping

@UnholySheep`s bb相交检查应该是第一步,但你的问题有两个主题:

  • 首先是找到所有的顶点位置,快 python api in maya
  • 第二个是比较N个点之间的距离, numpy
  • 真的很快

对于第二步,我建议编写您自己的可以调用 python 的 C 模块。创建一个沙盒 Maya 场景并通过不同的方法

测量时间
run_t = timeit.default_timer()
test_find_all_vertices_method_a()
print(timeit.default_timer() - run_t)

run_t = timeit.default_timer()
test_find_all_vertices_method_b()
print(timeit.default_timer() - run_t)

我希望我理解正确,您正在尝试针对自身测试对象的顶点!

我能想到的一些事情可能会减慢您的代码速度:

xform 可能是获取点位置的较慢方法。

distance = math.sqrt(math.pow(c2[0] - c1[0], 2) + math.pow(c2[1] - c1[1], 2) + math.pow(c2[2] - c1[2], 2)) 这可能是另一个罪魁祸首。通常在计算距离时,平方根会减慢速度。绕过它的一种方法是改为计算平方距离,这样您就可以完全避免使用 math.sqrt

cmds.select(meshToCek)
mel.eval("ConvertSelectionToVertices")

这可能不会减慢速度,但将顶点保存在内存中可能会更好。

我尝试使用最严格的 maya api 方法,性能似乎更好。也许有更好的优化方法,但我们在这里取得了一些进展!

import maya.cmds as cmds
import maya.OpenMaya as OpenMaya


def mfn_mesh_generator():
    selection_list = OpenMaya.MSelectionList()
    for mesh in cmds.ls(l=True, geometry=True,type="mesh"):
        selection_list.add(mesh)

    for i in range(selection_list.length()):    
        dag_path = OpenMaya.MDagPath()
        selection_list.getDagPath(i, dag_path)
        print dag_path.fullPathName()

        mfn_mesh = OpenMaya.MFnMesh(dag_path)
        yield mfn_mesh


def get_overlapping_vertices(mfn_mesh, threshold=0.0003):
    points_list = OpenMaya.MPointArray()
    mfn_mesh.getPoints(points_list, OpenMaya.MSpace.kWorld)

    overlapping = []

    for i in range(points_list.length()):
        for j in range(points_list.length()):
            if i == j:
                continue

            dist = points_list[i].distanceTo(points_list[j])
            if dist < threshold:
                if i not in overlapping:
                    overlapping.append(i)

                if j not in overlapping:
                    overlapping.append(j)

    return overlapping


for mfn_mesh in mfn_mesh_generator():
    get_overlapping_vertices(mfn_mesh)

mfn_mesh_generator 是一个 python 生成器,您可以循环遍历场景中的所有 MFnMesh 对象。如果您想以另一种方式收集网格,请随意更改此设置(我这样做只是为了将事物分开并使其更通用)。幸运的是 api 的 MPoint 对象有一个方法 distanceTo 来计算另一个 MPoint 的距离!另外 MFnMesh 有一种方法可以用 getPoints 一举获得所有顶点。这比一个一个地优化它。

对于 5 个多边形球体的场景,大约需要 0.667850017548 秒。使用您的方法处理同一场景大约需要 12.1129710674 秒。相当不错的速度提升!

希望对您有所帮助并给您一些想法。