反対側の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)
こんなシーンで試してみます。
実行結果
196
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
テストしてみます。
targetVtxID = getOtherSideVtx(217,"pSphere1",pivot = "world",mirrorAxis = "x")
cmds.select("pSphere1.vtx["+str(targetVtxID)+"]")
お、それっぽい位置に行きましたね。
シンメトリーをonにして
cmds.ls(sl =True)
# Result: ['pSphere1.vtx[211]', 'pSphere1.vtx[217]'] #
どうやらとれていそうですね。
vtxが重なってた場合はー・・・・・どうなるんだ?