1

我有一个问题,我需要选择一个预先选择的面孔旁边的面孔。

这可能很容易完成,但问题是当我得到邻居的脸时,我需要知道它面对的方向。

所以现在我可以选择与边缘连接的面,但我无法从第一个选定的面中获取例如左侧或右侧的面。我尝试了多种方法,但找不到解决方案。

我试过:

  1. pickWalk - cmds.pickWalk() - 问题在于它的行为无法预测,因为它从相机的角度走动网格。

  2. polyInfo - cmds.polyInfo() - 这是一个非常有用的功能,最接近答案。在这种方法中,我尝试从人脸中提取边缘,然后查看哪些是该人脸的邻居edgeToFace()。这很好用,但不能解决我的问题。详细地说,当polyInfo返回共享边的面时,它不会以我总是知道edgesList[0](例如)指向左或右的边的方式返回它们。因此,如果我在不同的面上使用它,那么在每种情况下,生成的面可能会面向不同的方向。

  3. 从顶点到边然后到面等的许多转换的艰难方式。但仍然是同样的问题,我不知道哪条边是顶部或左侧。

  4. conectedFaces()我在选定的脸上调用谁的方法,它返回与第一张脸相连的脸,但仍然是同样的问题,我不知道哪个脸面向哪个方向。

需要明确的是,我没有使用预先选择的面孔列表并检查它们,但我需要知道这些面孔而不知道它们的名字或将它们的名字保存在某处。有人知道选择面孔的方法吗?

为了详细说明我的问题,我制作了一张图片以使其清楚:

例子

从示例中可以看出,如果有选定的面,我需要选择任何尖面,但那必须是我要选择的准确面。其他方法选择所有相邻面,但我需要可以说“选择正确”并从第一个选择的面中选择正确的方法。

4

3 回答 3

1

这是一种在上/下/左/右与网格的变换(局部空间)对齐的规则下相当一致的解决方案,尽管也可能是世界空间。

我要做的第一件事是使用网格变换的平均面顶点位置、面法线和世界空​​间 Y 轴为每个网格面建立一个面相对坐标系。这涉及到一点向量数学,所以我将使用 API 来简化它。第一部分将为每个人脸创建一个坐标系,我们将其存储到列表中以供将来查询。见下文。

from maya import OpenMaya, cmds

meshTransform = 'polySphere'
meshShape = cmds.listRelatives(meshTransform, c=True)[0]

meshMatrix = cmds.xform(meshTransform, q=True, ws=True, matrix=True)
primaryUp = OpenMaya.MVector(*meshMatrix[4:7])
# have a secondary up vector for faces that are facing the same way as the original up
secondaryUp = OpenMaya.MVector(*meshMatrix[8:11])

sel = OpenMaya.MSelectionList()
sel.add(meshShape)

meshObj = OpenMaya.MObject()
sel.getDependNode(0, meshObj)

meshPolyIt = OpenMaya.MItMeshPolygon(meshObj)
faceNeighbors = []
faceCoordinates = []

while not meshPolyIt.isDone():

    normal = OpenMaya.MVector()
    meshPolyIt.getNormal(normal)

    # use the seconary up if the normal is facing the same direction as the object Y
    up = primaryUp if (1 - abs(primaryUp * normal)) > 0.001 else secondaryUp

    center = meshPolyIt.center()

    faceArray = OpenMaya.MIntArray()
    meshPolyIt.getConnectedFaces(faceArray)

    meshPolyIt.next()

    faceNeighbors.append([faceArray[i] for i in range(faceArray.length())])

    xAxis = up ^ normal
    yAxis = normal ^ xAxis

    matrixList = [xAxis.x, xAxis.y, xAxis.z, 0,
                  yAxis.x, yAxis.y, yAxis.z, 0,
                  normal.x, normal.y, normal.z, 0,
                  center.x, center.y, center.z, 1]

    faceMatrix = OpenMaya.MMatrix()
    OpenMaya.MScriptUtil.createMatrixFromList(matrixList, faceMatrix)

    faceCoordinates.append(faceMatrix)

这些函数将查找并返回相对于面部在特定方向(X 和 Y)上给定的面部旁边的面部。这使用点积来查看哪个面在该特定方向上更多。这应该适用于任意数量的面,但它只会返回一个最接近该方向的面。

def getUpFace(faceIndex):
    return getDirectionalFace(faceIndex, OpenMaya.MVector(0,1,0))

def getDownFace(faceIndex):
    return getDirectionalFace(faceIndex, OpenMaya.MVector(0,-1,0))

def getRightFace(faceIndex):
    return getDirectionalFace(faceIndex, OpenMaya.MVector(1,0,0))

def getLeftFace(faceIndex):
    return getDirectionalFace(faceIndex, OpenMaya.MVector(-1,0,0))

def getDirectionalFace(faceIndex, axis):
    faceMatrix = faceCoordinates[faceIndex]

    closestDotProd = -1.0
    nextFace = -1

    for n in faceNeighbors[faceIndex]:
        nMatrix = faceCoordinates[n] * faceMatrix.inverse()
        nVector = OpenMaya.MVector(nMatrix(3,0), nMatrix(3,1), nMatrix(3,2))

        dp = nVector * axis

        if dp > closestDotProd:
            closestDotProd = dp
            nextFace = n

    return nextFace

所以你会这样称呼它:

getUpFace(123) 

数字是面部索引,您希望从中获得“向上”的面部。

试一试,看看它是否满足您的需求。

于 2016-11-06T01:42:39.617 回答
0

polyListComponent 转换

import pprint
init_face = cmds.ls(sl=True)

#get edges
edges = cmds.polyListComponentConversion(init_face, ff=True, te=True)
#get neighbour faces
faces = cmds.polyListComponentConversion(edges, fe=True, tf=True, bo=True)
# show neighbour faces
cmds.select(faces)
# print face normal of each neighbour face
pprint.pprint(cmds.ployInfo(faces,fn=True))
于 2016-11-07T09:55:48.757 回答
0

最简单的方法是在 MeshFace 上使用 Pymel 的 connectedFaces():

http://download.autodesk.com/us/maya/2011help/pymel/generated/classes/pymel.core.general/pymel.core.general.MeshFace.html

import pymel.core as pm

sel = pm.ls(sl=True)[0]
pm.select(sel.connectedFaces())
于 2016-11-10T12:09:27.707 回答