前回 反対側の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
(あれ、追加分意外に短かったぞ)
とりあえずテストしてみます。
こんなシーンでやってみます。
ids = getOtherSideFace(236,"pSphere1",pivot = "world",mirrorAxis = "x")
for id in ids:
cmds.select("pSphere1.f["+str(id)+"]",add =True)
を。いけましたね。
折角なので、使用方法を考える
あっさりできてしまったので、実際の運用例を。
自分の作業時に、faceに直接マテリアルをアサインすることがあります。
その際、右半分やったけど左半分にマテリアルコピーしたいなーとかそういうときにつかいます。
例えばこんな感じで半分にマテリアルをアサインし、反対側も同じようにしたいなぁと言うときに
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")
もう少し調整するなら、例えば 左から右にの様に方向を指定できるようにすると良さそうです。