2016-11-04 64 views
1

我有一个问题,我需要选择一个预选脸部旁边的脸部。在玛雅找到脸部邻居

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

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

我试着用:

  1. pickWalk -cmds.pickWalk() - 这个问题是,它的行为是无法预测的,因为它走从摄像机的角度的网格。

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

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

  4. conectedFaces()方法,我呼吁选定的面孔,它返回的面孔连接到第一张脸,但它仍然是同样的问题,我不知道这张脸是否面临着这种方式。

要清楚我不使用面的预选名单,并检查他们,但我需要知道的脸不知道,或保持他们的名字somewere。有人知道一种可以选择面孔的方法吗?

这样来阐述我的问题我做了一个图像,使其明确: example

因为你可以看到的例子,如果有选择的脸,我需要选择任何尖锐faces.but必须是精确的我想选择其他方法。其他方法选择所有邻居的面孔,但我需要的方法,我可以说“选择正确”,并将从第一次选择的脸部选择正确的一个。

+0

所以不喜欢的种植选择?什么决定了他们的“方向”?他们的立场? –

+0

我更新了与我的问题的图像示例问题,所以问题可以更好地理解。 – Dimitar

+1

你需要考虑的是你用什么标准来确定什么是左/右/上/下。除非你的网格预定有4条边并且在一个公共轴上对齐,否则你需要提供“up”的定义。这个问题缺少这个关键要求来提供有用的答案。 – scottiedoo

回答

0

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

我要做的第一件事是使用网格变换的平均面顶点位置,面法线和世界空​​间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) 

用数字为你想要得到的脸是“向上”从表面看来指数。

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

+0

我测试了它,它的工作原理,但它的一个问题。如果我有相同的Y坐标(例如平坦表面)的面孔,它不工作。它好主意,但这就是为什么我之前没有使用坐标,因为我不能预测物体如何定位在空间或面部会面向一些轴,以便我可以检查它们。 – Dimitar

+0

来澄清more.if我做立方体,并开始从脸上它的作品well.when当我到达边缘,我得到exacly脸从极端的立方体像我想要get.But然后当我打电话getUpFace在返回的脸上,不会继续沿着路径走,但它会给出其他的面部(左或右)。这并不是指出问题,因为我没有预料到它,但这个解决方案仍然可以100%用于单面发现。 – Dimitar

+0

是的,如果面朝上,这将不起作用,您可以在构建坐标系时设置一个新的向上矢量而不是Y.因此,可以处理这些转角情况。你只需得到正常和向上矢量的点积,如果它对-1和1的容差很小,就把它设置成你觉得有意义的其他东西,例如Z.我会更新我的答案以包含此内容。 – scottiedoo

-1

polyListComponentConversion

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)) 
+0

voteDown没有任何反馈或评论 –