よし、ハードエッジの設定が終わったぞ。
あー・・・右側もか・・・・・ってなった場合に、
パッと思いつくやり方は
- 左のオブジェクトを複製して、反転させてリネーム
- 右のオブジェクトも左と同じになるように設定
あれ?ハードエッジ情報って転送できないんだっけ?
標準機能でできないか?
とりあえずできそうなのは、transfer Attributes かなぁ
ん?ん?
何をどうやっても転送できねぇ
他に出きそうな機能も見当たらないので、一旦切り替え。
※標準機能で転送する方法ご存じの方いらっしゃったら是非教えてください。
ハードエッジ情報
ハードエッジ情報はどこに格納されているのかなぁー
先述のテストで転送出来たってことはvertexNormalと関係してるとは思うのですが、それは完全ではない。
つまりハードエッジ情報は別途どこかに格納されとるんではなかろうか。
と仮定。
エッジは、所有する 2 つのフェース間の角度が、スムージング角度より鋭角(大きい)の場合にハードになります。
所有する 2 つのファセット間の角度が、スムージング角度より鈍角(小さい)場合はソフトになります。
そっかーフェースかー
フェースノーマルはvtxノーマルで定義されるしなぁ・・・
失敗したケースは平面だったから???
OpenMaya.MFnMesh.isEdgeSmooth()
あ、こんなのもありますね。
ということはエッジ毎に ハードorソフト が確認できるようですね。
エッジからエッジへ
ならば、こうだ。
- 転送元オブジェクトのハードなエッジIDを取得
- 転送先オブジェクトのハードエッジを全部ソフト化
- 転送先オブジェクトでエッジIDを元にハードを設定
こんな流れで。
- ハードなエッジIDの取得
まぁとりあえず総当たりで
import maya.api.OpenMaya as om
import maya.cmds as cmds
def getDagNode(target):
try:
sellist = om.MGlobal.getSelectionListByName(target)
return sellist.getDagPath(0)
except:
return None
def getShapeFn(dagPath):
FnShape = None
if dagPath.hasFn(om.MFn.kMesh):
FnShape = om.MFnMesh(dagPath)
elif dagPath.hasFn(om.MFn.kNurbsSurface):
FnShape = om.MFnNurbsSurface(dagPath)
elif dagPath.hasFn(om.MFn.kNurbsCurve):
FnShape = om.MFnNurbsCurve(dagPath)
return FnShape
def getHardEdges(target):
dagPath = getDagNode(target)
FnShape = getShapeFn(dagPath)
edgeNum = FnShape.numEdges
hardIDs = []
for edgeID in range(0,edgeNum):
if FnShape.isEdgeSmooth(edgeID)==False:
hardIDs.append(edgeID)
return hardIDs
- ハードエッジを全部ソフト化
まぁ全部ソフトエッジ化すればいいんですわよね
とおもったけど、transformノード指定してpolySoftEdgeで行けますね。
cmds.polySoftEdge(target, ch = False,angle =180)
- エッジIDを元にハードを設定
import maya.cmds as cmds
def setHardEdge(target,edgeIDs):
targetEdges = []
for edgeID in edgeIDs:
targetEdges.append(target + ".e["+str(edgeID)+"]")
cmds.polySoftEdge(targetEdges, ch = False,angle =0)
これらを組み合わせて
import maya.api.OpenMaya as om
import maya.cmds as cmds
def getDagNode(target):
try:
sellist = om.MGlobal.getSelectionListByName(target)
return sellist.getDagPath(0)
except:
return None
def getShapeFn(dagPath):
FnShape = None
if dagPath.hasFn(om.MFn.kMesh):
FnShape = om.MFnMesh(dagPath)
elif dagPath.hasFn(om.MFn.kNurbsSurface):
FnShape = om.MFnNurbsSurface(dagPath)
elif dagPath.hasFn(om.MFn.kNurbsCurve):
FnShape = om.MFnNurbsCurve(dagPath)
return FnShape
def getHardEdges(target):
dagPath = getDagNode(target)
FnShape = getShapeFn(dagPath)
edgeNum = FnShape.numEdges
hardIDs = []
for edgeID in range(0,edgeNum):
if FnShape.isEdgeSmooth(edgeID)==False:
hardIDs.append(edgeID)
return hardIDs
def setHardEdge(target,edgeIDs):
targetEdges = []
for edgeID in edgeIDs:
targetEdges.append(target + ".e["+str(edgeID)+"]")
cmds.polySoftEdge(targetEdges, ch = False,angle =0)
def transferHardEdge(source, target):
edgeIDs = getHardEdges(source)
cmds.polySoftEdge(target, ch = False,angle =180)
setHardEdge(target,edgeIDs)
問題なく転送出来た様子。
そういえば
終わりじゃない。
1つここで思い出したことが
見た目が完全に一緒でも faceのIDが異なる場合がある
vtxIDが完全に一致しててもfaceのIDが異なる場合がある
これedgeでもあり得るのかな?
はい あり得ました。
1本エッジを削除して、connectComponentでつなぎ直してみたところ
edgeIDはずれました。
エッジをvtxにして、vtxからエッジに
edge貼り直しても幸い vtxIDは変わらないので、
vtxIDのorderは一致しているというのを最低限の条件として再考。
- 転送元オブジェクトのハードなedgeを取得
- エッジを構成しているvtxIDを取得
- 転送先オブジェクトでvtxIDで構成されるedgeIDを取得
- 転送先オブジェクトのハードエッジを全部ソフト化
- 転送先オブジェクトでedgeIDをハードを設定
こんなところでしょうか。
- エッジを構成しているvtxIDを取得
こんな感じで
def getEdgeContainVtx(target,edgeIDs):
dagPath = getDagNode(target)
FnShape = getShapeFn(dagPath)
edgeVtxDict = {}
for edgeID in edgeIDs:
vtexIds = FnShape.getEdgeVertices(edgeID)
edgeVtxDict[edgeID] = vtexIds
return edgeVtxDict
- 転送先オブジェクトでvtxIDで構成されるedgeIDを取得
vtxに接続しているedgeは複数本あるので、
それらのうちで 指定したvtxすべてに接続されているedgeを探せばいいかしら?
def convertVtexToEdge(target,edgeVtxDict):
dagPath = getDagNode(target)
FnShape = getShapeFn(dagPath)
it = om.MItMeshVertex(dagPath)
convertedDict = {}
for key in list(edgeVtxDict.keys()):
shareEdges = []
for vtexID in edgeVtxDict[key]:
it.setIndex(vtexID)
edges = it.getConnectedEdges()
if len(shareEdges) == 0:
shareEdges = edges
else:
shareEdges = list(set(shareEdges) & set(edges))
if len(shareEdges) == 0:
continue
for shareEdge in shareEdges:
convertedDict[shareEdge] = edgeVtxDict[key]
return convertedDict
まとめる
まとめるとこんな感じ
import maya.api.OpenMaya as om
import maya.cmds as cmds
def getDagNode(target):
try:
sellist = om.MGlobal.getSelectionListByName(target)
return sellist.getDagPath(0)
except:
return None
def getShapeFn(dagPath):
FnShape = None
if dagPath.hasFn(om.MFn.kMesh):
FnShape = om.MFnMesh(dagPath)
elif dagPath.hasFn(om.MFn.kNurbsSurface):
FnShape = om.MFnNurbsSurface(dagPath)
elif dagPath.hasFn(om.MFn.kNurbsCurve):
FnShape = om.MFnNurbsCurve(dagPath)
return FnShape
def getHardEdges(target):
dagPath = getDagNode(target)
FnShape = getShapeFn(dagPath)
edgeNum = FnShape.numEdges
hardIDs = []
for edgeID in range(0,edgeNum):
if FnShape.isEdgeSmooth(edgeID)==False:
hardIDs.append(edgeID)
return hardIDs
def setHardEdge(target,edgeIDs):
targetEdges = []
for edgeID in edgeIDs:
targetEdges.append(target + ".e["+str(edgeID)+"]")
cmds.polySoftEdge(targetEdges, ch = False,angle =0)
def getEdgeContainVtx(target,edgeIDs):
dagPath = getDagNode(target)
FnShape = getShapeFn(dagPath)
edgeVtxDict = {}
for edgeID in edgeIDs:
vtexIds = FnShape.getEdgeVertices(edgeID)
edgeVtxDict[edgeID] = vtexIds
return edgeVtxDict
def convertVtexToEdge(target,edgeVtxDict):
dagPath = getDagNode(target)
FnShape = getShapeFn(dagPath)
it = om.MItMeshVertex(dagPath)
convertedDict = {}
for key in list(edgeVtxDict.keys()):
shareEdges = []
for vtexID in edgeVtxDict[key]:
it.setIndex(vtexID)
edges = it.getConnectedEdges()
if len(shareEdges) == 0:
shareEdges = edges
else:
shareEdges = list(set(shareEdges) & set(edges))
if len(shareEdges) == 0:
continue
for shareEdge in shareEdges:
convertedDict[shareEdge] = edgeVtxDict[key]
return convertedDict
def transferHardEdge(source, target):
edgeIDs = getHardEdges(source)
edgeVtxDict = getEdgeContainVtx(source,edgeIDs)
cmds.polySoftEdge(target, ch = False,angle =180)
convertedDict = convertVtexToEdge(target,edgeVtxDict)
setHardEdge(target,list(convertedDict.keys()))
sel = cmds.ls(sl =True)
transferHardEdge(sel[0], sel[1])