2016-11-04 3 views
1

J'ai un problème lorsque je dois sélectionner des visages à côté d'une face présélectionnée.Trouver des voisins de visages dans Maya

Cela peut être fait facilement, mais le problème est que lorsque je reçois un visage voisin, je dois savoir dans quelle direction il est confronté. Donc maintenant je suis capable de sélectionner les faces qui sont connectées avec un bord mais je ne peux pas obtenir la face qui est par exemple à gauche ou à droite de la première face sélectionnée. J'ai essayé plusieurs approches mais je n'arrive pas à trouver la solution.

J'ai essayé avec:

  1. pickWalk -cmds.pickWalk() - problème est que ce comportement est ne peut pas être prédit, car il marche le maillage du point de vue de la caméra.

  2. polyInfo -cmds.polyInfo() - c'est une fonction très utile et la plus proche de la réponse. Dans cette approche, j'essaie d'extraire les bords d'un visage, puis de voir quels sont les voisins de ce visage avec edgeToFace(). Cela fonctionne bien mais ne résout pas mon problème. Pour élaborer, quand polyInfo renvoie des faces qui partagent des bords, il ne les retourne pas d'une manière que je puisse toujours savoir que edgesList[0] (par exemple) est le bord qui pointe vers la gauche ou vers la droite. Par conséquent, si je l'utilise sur différentes faces, le visage qui en résulte peut être dans une direction différente dans chaque cas.

  3. Difficile avec beaucoup de conversions de sommet à bord puis à face etc Mais encore une fois c'est le même problème où je ne sais pas quel bord est le haut ou le gauche. Méthode que j'appelle sur le visage sélectionné et il renvoie les visages qui sont connectés au premier visage, mais c'est toujours le même problème, je ne sais pas quel visage fait face à quel point.

Pour être clair, je ne suis pas en utilisant une liste présélectionnée de visages et de les vérifier, mais je dois connaître les visages sans savoir ou garder leurs noms somewere. Est-ce que quelqu'un connaît un moyen qui fonctionne avec la sélection des visages?

afin d'élaborer ma question je l'ai fait une image pour préciser: example

comme vous pouvez le voir dans l'exemple, si on choisit le visage que je dois sélectionner l'une faces.but pointue qui doit être exacte Visage je veux sélectionner.Autres méthodes sélectionner tous les visages des voisins, mais j'ai besoin de la méthode que je peux dire "sélectionner à droite" et sélectionnera un droit de la première face sélectionnée.

+0

donc pas comme une sélection de culture? Qu'est-ce qui détermine leur "direction"? Leur position? –

+0

J'ai mis à jour la question avec un exemple d'image pour mon problème afin que la question puisse être mieux comprise. – Dimitar

+1

Ce à quoi vous devez penser, c'est quels critères utilisez-vous pour déterminer ce qui est gauche/droite/haut/bas. À moins que votre maillage ne soit prédéterminé pour avoir 4 arêtes et s'aligner dans un axe commun, vous devez fournir la définition de ce qu'est le «haut». Ce problème manque cette exigence clé pour fournir une réponse utile. – scottiedoo

Répondre

0

Ceci est une solution qui serait assez cohérente selon la règle que haut/bas/gauche/droite est aligné avec la transformation du maillage (espace local), mais pourrait aussi être l'espace du monde.

La première chose que je ferais est de construire un système de coordonnées relatif de face pour chaque face de maillage en utilisant la position moyenne du sommet de la face, la normale et l'axe Y de la transformation du maillage. Cela implique un peu de calcul vectoriel, donc j'utiliserai l'API pour rendre cela plus facile. Cette première partie fera un système de coordonnées pour chaque visage que nous allons stocker dans des listes pour des requêtes futures. Voir ci-dessous.

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) 

Ces fonctions vont chercher et retour, laquelle face est à côté de celle donnée dans une direction donnée (X et Y) par rapport à la face. Cela utilise un produit scalaire pour voir quel visage est le plus dans cette direction particulière. Cela devrait fonctionner avec n'importe quel nombre de visages mais cela ne retournera qu'une face qui est dans le plus de cette direction.

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 

Vous appelleriez comme ceci:

getUpFace(123) 

Avec le nombre étant l'indice de visage que vous voulez obtenir le visage qui est de ce « haut ».

Faites un essai et voyez si cela répond à vos besoins.

+0

je l'ai testé et cela fonctionne mais c'est un problème.Si j'ai des visages qui sont dans les mêmes coordonnées Y (exemple surface plane) ça ne fonctionne pas.Son idée, mais c'est pourquoi je n'ai pas utilisé les coordonnées avant parce que je ne peux pas prédire comment l'objet sera positionné dans l'espace ou est-ce que les faces feront face à un axe pour que je puisse les vérifier. – Dimitar

+0

pour clarifier plus.if je fais du cube et commence à monter du visage cela fonctionne bien. Quand j'arrive au bord je reçois exacly le visage qui est de l'autre côté du cube comme je veux obtenir .Mais alors quand j'appelle getUpFace sur ce visage retourné, ne continue pas à suivre le chemin mais il donne un autre visage (gauche ou droite). Cela n'a pas été pointé dans la question car je ne l'avais pas anticipé mais cette solution fonctionne à 100% pour trouver un visage. – Dimitar

+0

Oui, cela ne fonctionnera pas si les visages sont directement orientés vers le haut, vous pouvez attraper ces cas lors de la construction du système de coordonnées et définir un nouveau vecteur haut au lieu de Y. Il est donc possible de gérer ces cas. Vous obtiendriez simplement le produit scalaire du vecteur normal et du vecteur haut et, si la tolérance est très faible à -1 et à 1, réglez l'incrément sur quelque chose d'autre qui vous semble logique, Z par exemple. Je mettrai à jour ma réponse pour inclure ceci. – 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 sans aucun commentaire ou commentaire –

-1

Le sur la MeshFace façon la plus simple de le faire est d'utiliser les connectedFaces de Pymel():

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

comme vous pouvez le voir dans la question que j'ai déjà essayé avec connectedFaces() et il a déclaré que ce n'est pas la résolution du problème. – Dimitar