0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MayaAdvent Calendar 2024

Day 13

Mayaで反対側のfaceを取得したい1

Posted at

反対側のfaceを取りたい場面に出くわしました。

selectionをシンメトリーにして取得ってのも考えたのですが、
なんかもっとダイレクトにとりたいなーと。

どうすれば?

faceそのものの位置ってのは存在しないので、

  • faceを形成するvtxを取得する
  • 反対側にあるvtxを取得する
  • 反対側のvtxが形成するfaceを取得する
  • 全てのvtxが所属しているfaceがそいつだ

という感じですかね。

反対側のvtxを取りたい

まずは反対側のvtxを取る処理単体を考えます。

OpenMaya.MFnMesh Class Reference を眺めつつ

これなんか使えそう・・・

OpenMaya.MFnMesh.getClosestPoint

Returns a tuple containing the closest point on the mesh to the
given point and the ID of the face in which that closest point lies.

えー faceID返ってくるんですかー
とりあえず試してみます。

import maya.cmds as cmds
import maya.api.OpenMaya as om

targetMesh = "pSphere1"

sellist = om.MGlobal.getSelectionListByName(targetMesh)
meshDagPath = sellist.getDagPath(0)
shapeFn = om.MFnMesh(meshDagPath)

target = cmds.ls(sl =True)[0]
position = cmds.xform(target , q =True , ws = True, t =True)
space =  om.MSpace.kWorld
otherSidePoint,faceID = shapeFn.getClosestPoint(om.MPoint(position),space)
print(faceID)

こんなシーンで試してみます。

image.png

実行結果

196

該当のfaceはこれですね。
image.png

1個かー まぁclosestですからー

となると

  • 指定したvexの位置を取得
  • 反対側の位置を取得
  • 反対側の位置のclosestなfaceを取得
  • faceを形成しているvtxを取得
  • 形成しているvtxの中から 反対側の位置に最も近いvtxがそいつだ

うーん faceの取得案と並べると、なんか2度手間っぽくなってきましたね。
とりあえずやるだけやってみます。

import maya.cmds as cmds
import maya.api.OpenMaya as om

def getPosition(target):
    nodeType = cmds.nodeType(target)
    
    if nodeType == "joint" or nodeType == "transform" or nodeType == "ikHandle" or nodeType == "place3dTexture":
        return cmds.xform(target , q =True , ws = True, rotatePivot =True)

    elif nodeType == "mesh" or nodeType == "nurbsCurve" or nodeType == "nurbsSurface" or nodeType == "lattice":
        return cmds.xform(target , q =True , ws = True, t =True)

def getDagNode(target):    
    try:
        sellist = om.MGlobal.getSelectionListByName(target)
        return sellist.getDagPath(0)
    except:
        return None

def mirrorMatrix(source,pivot,mirrorAxis):        

    nodeType = cmds.nodeType(source)
    
    if nodeType == "joint" or nodeType == "transform" or nodeType == "ikHandle" or nodeType == "place3dTexture":
        curMatrix = om.MMatrix(cmds.xform(source , q =True , ws = True, matrix =True))
    elif nodeType == "mesh" or nodeType == "nurbsCurve" or nodeType == "nurbsSurface" or nodeType == "lattice":
        position = getPosition(source)
        curMatrix = om.MTransformationMatrix(om.MMatrix.kIdentity).setTranslation(om.MVector(position),om.MSpace.kWorld).asMatrix()
    
    if mirrorAxis == "x":
        mirrorScale = [-1.0,1.0,1.0]
    elif mirrorAxis == "y":
        mirrorScale = [1.0,-1.0,1.0]
    elif mirrorAxis == "z":
        mirrorScale = [1.0,1.0,-1.0]

    mirrorScaleMatrix = om.MTransformationMatrix(om.MMatrix.kIdentity).setScale(mirrorScale,om.MSpace.kWorld).asMatrix()

    if pivot == "world" or pivot == None:
        pivotMatrix = om.MMatrix.kIdentity
    else:
        pivotMatrix = om.MMatrix(cmds.xform(pivot , q =True , ws = True, matrix =True))
    
    pivotMatrix_inverse = pivotMatrix.inverse()
    dist_matrix = curMatrix * pivotMatrix_inverse * mirrorScaleMatrix * pivotMatrix

    dist_matrix = om.MTransformationMatrix(dist_matrix).setScale([1.0,1.0,1.0],om.MSpace.kWorld).asMatrix()    
    dist_matrix = om.MTransformationMatrix(dist_matrix).setScale([-1.0,-1.0,-1.0],om.MSpace.kObject).asMatrix()    
    dist_matrix = om.MTransformationMatrix(dist_matrix).setScale([1.0,1.0,1.0],om.MSpace.kWorld).asMatrix()    
    dist_matrix = om.MTransformationMatrix(dist_matrix).setShear([0.0,0.0,0.0],om.MSpace.kWorld).asMatrix()

    return dist_matrix

def getMirrorPosition(source,pivot,mirrorAxis):
    setMatrix = mirrorMatrix(source,pivot,mirrorAxis)
    mirrorPosition = om.MTransformationMatrix(setMatrix).translation(om.MSpace.kWorld)    
    return mirrorPosition
    
def getMirrorPosition(source,pivot,mirrorAxis):
    setMatrix = mirrorMatrix(source,pivot,mirrorAxis)
    mirrorPosition = om.MTransformationMatrix(setMatrix).translation(om.MSpace.kWorld)    
    return mirrorPosition

def getOtherSideVtx(sourceVtxID,tagetMesh,pivot = "world",mirrorAxis = "x"):    
    mirrorPosition = getMirrorPosition(tagetMesh + ".vtx["+str(sourceVtxID)+"]",pivot,mirrorAxis)       
    mirrorPositionVector = om.MVector(mirrorPosition)

    meshDagPath = getDagNode(tagetMesh)
    shapeFn = om.MFnMesh(meshDagPath)
    
    space =  om.MSpace.kWorld    
    otherSidePoint,faceID = shapeFn.getClosestPoint(om.MPoint(mirrorPosition),space)

    faceIterator = om.MItMeshPolygon(meshDagPath)
    faceIterator.setIndex(faceID)
    vtxIDs = faceIterator.getVertices()
    faceVtxPositions = faceIterator.getPoints(om.MSpace.kWorld)

    minlength = None
    targetVtxID = None
    for faceVtxPosition,vtxID in zip(faceVtxPositions,vtxIDs):
        targetVector = om.MVector(faceVtxPosition)        
        length = (mirrorPositionVector - targetVector).length()
        
        if minlength == None:
            minlength = length
            targetVtxID = vtxID
        elif minlength > length:
            minlength = length
            targetVtxID = vtxID
            
    return targetVtxID

テストしてみます。

image.png

targetVtxID = getOtherSideVtx(217,"pSphere1",pivot = "world",mirrorAxis = "x")   
cmds.select("pSphere1.vtx["+str(targetVtxID)+"]")

お、それっぽい位置に行きましたね。

image.png

シンメトリーをonにして

cmds.ls(sl =True)
# Result: ['pSphere1.vtx[211]', 'pSphere1.vtx[217]'] # 

どうやらとれていそうですね。

vtxが重なってた場合はー・・・・・どうなるんだ?

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?