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 14

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

Last updated at Posted at 2024-12-14

前回 反対側のvtxを取得できるようにしてみましたが、それを流れに入れ込んでみると

  • faceを形成するvtxを取得する
  • 反対側にあるvtxを取得する <- ここを前回
    • 指定したvexの位置を取得
    • 反対側の位置を取得
    • 反対側の位置のclosestなfaceを取得
    • faceを形成しているvtxを取得
    • 形成しているvtxの中から 反対側の位置に最も近いvtxがそいつだ
  • 反対側のvtxが形成するfaceを取得する
  • 全てのvtxが所属しているfaceがそいつだ

faceからvtx取得して、
反対側でfaceからまたvtx取得して、そのvtxからまたface取得してるので
なんかモヤっとしてます。

モヤっとしてるが実装

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

##ここから追加--------------------
def getOtherSideFace(sourceFaceID,tagetMesh,pivot = "world",mirrorAxis = "x"):    
    meshDagPath = getDagNode(tagetMesh)
    faceIterator = om.MItMeshPolygon(meshDagPath)
    faceIterator.setIndex(sourceFaceID)
    vtxIDs = faceIterator.getVertices()
    mirrorFaceIDs = []
    VtxIterator = om.MItMeshVertex(meshDagPath)
    
    for vtxID in vtxIDs:
        mirrorVtxID = getOtherSideVtx(vtxID,tagetMesh,pivot,mirrorAxis)                
        VtxIterator.setIndex(mirrorVtxID)
        connectedFaceID = VtxIterator.getConnectedFaces()        
        if len(mirrorFaceIDs) == 0:
            mirrorFaceIDs = connectedFaceID
        else:
            mirrorFaceIDs = list(set(mirrorFaceIDs) & set(connectedFaceID))
                
    return mirrorFaceIDs

(あれ、追加分意外に短かったぞ)

とりあえずテストしてみます。

image.png

こんなシーンでやってみます。

ids = getOtherSideFace(236,"pSphere1",pivot = "world",mirrorAxis = "x")
    
for id in ids:
    cmds.select("pSphere1.f["+str(id)+"]",add =True)

image.png

を。いけましたね。

折角なので、使用方法を考える

あっさりできてしまったので、実際の運用例を。
自分の作業時に、faceに直接マテリアルをアサインすることがあります。

その際、右半分やったけど左半分にマテリアルコピーしたいなーとかそういうときにつかいます。

例えばこんな感じで半分にマテリアルをアサインし、反対側も同じようにしたいなぁと言うときに

image.png

SGのアサイン情報からfaceだけ引っ張り出して、反対側を取得してアサインという感じですね。

assignItems = cmds.sets("lambert2SG",q=True)
assignItems = cmds.ls(assignItems,fl=True)

for assignItem in assignItems:   
    if "f[" in assignItem:        
        faceID = assignItem.split("[")[-1].replace("]","")
        targetMesh = assignItem.split(".")[0] 

        ids = getOtherSideFace(int(faceID),targetMesh,pivot = "world",mirrorAxis = "x")
    
        for id in ids:
            cmds.sets(targetMesh + ".f["+str(id)+"]",e =True,forceElement = "lambert2SG")

image.png

もう少し調整するなら、例えば 左から右にの様に方向を指定できるようにすると良さそうです。

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?