如何在Maya找到邻居?

时间:2016-11-04 11:55:56

标签: python maya mel face

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

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

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

我尝试过:

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

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

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

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

  5. 要清楚我没有使用预先选定的面部列表并检查它们,但我需要知道面部而不知道或保留其名称。有人知道一种适用于选择面孔的方法吗?

    为了详细阐述我的问题,我制作了一张图片以表明:

    example

    从示例中可以看出,如果有选定的面,我需要选择任何一个尖面,但这必须是我想要选择的精确面。其他方法选择所有邻居面,但我需要方法,我可以说"选择正确"并将从第一个选定的脸部中选择一个。

3 个答案:

答案 0 :(得分: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) 

如果数字是面部索引,那么您希望从中获取面朝上的面部。

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

答案 1 :(得分:0)

polyListComponentConversion

let location = self.textView.firstRect(for: range)


extension NSRange {
    func toTextRange(textInput:UITextInput) -> UITextRange? {
        if let rangeStart = textInput.position(from: textInput.beginningOfDocument, offset: location),
            let rangeEnd = textInput.position(from: rangeStart, offset: length) {
            return textInput.textRange(from: rangeStart, to: rangeEnd)
        }
        return nil
    }
}

答案 2 :(得分: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())