latticeの格子の幅を調整したわいいけど、もう少し全体を大きくしたい。
けれどもlatticeのスケールを変えると、格子の幅を再度調整し直し。
面倒なので、同じ幅の格子を追加できるようなスクリプトを書いてしまおう。
設計
順序としては
- 全体の幅を取得
- 格子1個あたりの幅を取得
- 格子n個分の幅を全体幅に追加し、スケール値を算出
- latticeに格子n個追加
こんな感じでしょうか。
全体の幅を取得
latticeの縦・横・奥行の各長さを取りたい。
バウンディングボックスでも取れるが、latticeのコントロールポイントは規則正しく並んでいるので
一番最初 lattice.pt[0][0][0] と
一番最後 lattice.pt[-1][-1][-1] の
コントロールポイント位置を取得してやってみる。
一番最後のindexを取るためにまず各方向のdivisionsを取得
divS = cmds.getAttr(lattice + ".sDivisions")
divT = cmds.getAttr(lattice + ".tDivisions")
divU = cmds.getAttr(lattice + ".uDivisions")
これを使って、最初と最後のコントロールポイントの位置を取得する。
minPoint = cmds.xform(lattice + ".pt[0][0][0]",q =True,ws =True,t =True)
maxPoint = cmds.xform(lattice + ".pt["+str(divS-1)+"]["+str(divT-1)+"]["+str(divU-1)+"]",q =True,ws =True,t =True)
格子1個あたりの幅を取得
格子1つあたりの幅を取得するには、軸方向の長さを軸の格子数 -1 で割ればいい。
各軸の長さは、1つ前で求めた最大・最小位置から算出。
lengthS = (maxPoint[0] - minPoint[0])/(divS-1)
lengthT = (maxPoint[1] - minPoint[1])/(divT-1)
lengthU = (maxPoint[2] - minPoint[2])/(divU-1)
格子n個分の幅を全体幅に追加し、スケール値を算出
格子+n個分の幅かな
追加格子数を
addDiv = [1,1,1]
として、追加後の格子数を算出
newDivS = divS + addDiv[0]
newDivT = divT + addDiv[1]
newDivU = divU + addDiv[2]
ただし、addDiv の値がマイナスだった場合 追加後の格子数が2以下にならないようにしなければならない。
if newDivS < 2:
newDivS = 2
if newDivT < 2:
newDivT = 2
if newDivU < 2:
newDivU = 2
その上で、各軸の追加後のスケール値を算出
scaleS = (lengthS * (newDivS-1))/ (maxPoint[0] - minPoint[0])
scaleT = (lengthT * (newDivT-1))/ (maxPoint[1] - minPoint[1])
scaleU = (lengthU * (newDivU-1))/ (maxPoint[2] - minPoint[2])
スケール値は相対値なので、現在のスケール値に対して乗算する
cmds.setAttr(lattice + ".sx", cmds.getAttr(lattice + ".sx") * scaleS)
cmds.setAttr(lattice + ".sy", cmds.getAttr(lattice + ".sy") * scaleT)
cmds.setAttr(lattice + ".sz", cmds.getAttr(lattice + ".sz") * scaleU)
この時 baseShapeも同じくスケールさせないと大変なことになるので、
ffdを経由してコネクションからbaseShapeを取得し、同一のスケールにする
ffd = cmds.listConnections(lattice + ".latticeOutput", d =True)[0]
baseShape = cmds.listConnections(ffd + ".baseLatticeMatrix", d =False, s =True)[0]
cmds.setAttr(baseShape + ".sx", cmds.getAttr(lattice + ".sx"))
cmds.setAttr(baseShape + ".sy", cmds.getAttr(lattice + ".sy"))
cmds.setAttr(baseShape + ".sz", cmds.getAttr(lattice + ".sz"))
まとめる
以上をまとめるとこんな感じ
import maya.cmds as cmds
def addFFDDiv(lattice,addDiv):
divS = cmds.getAttr(lattice + ".sDivisions")
divT = cmds.getAttr(lattice + ".tDivisions")
divU = cmds.getAttr(lattice + ".uDivisions")
minPoint = cmds.xform(lattice + ".pt[0][0][0]",q =True,ws =True,t =True)
maxPoint = cmds.xform(lattice + ".pt["+str(divS-1)+"]["+str(divT-1)+"]["+str(divU-1)+"]",q =True,ws =True,t =True)
lengthS = (maxPoint[0] - minPoint[0])/(divS-1)
lengthT = (maxPoint[1] - minPoint[1])/(divT-1)
lengthU = (maxPoint[2] - minPoint[2])/(divU-1)
newDivS = divS + addDiv[0]
newDivT = divT + addDiv[1]
newDivU = divU + addDiv[2]
if newDivS < 2:
newDivS = 2
if newDivT < 2:
newDivT = 2
if newDivU < 2:
newDivU = 2
scaleS = (lengthS * (newDivS-1))/ (maxPoint[0] - minPoint[0])
scaleT = (lengthT * (newDivT-1))/ (maxPoint[1] - minPoint[1])
scaleU = (lengthU * (newDivU-1))/ (maxPoint[2] - minPoint[2])
cmds.setAttr(lattice + ".sx", cmds.getAttr(lattice + ".sx") * scaleS)
cmds.setAttr(lattice + ".sy", cmds.getAttr(lattice + ".sy") * scaleT)
cmds.setAttr(lattice + ".sz", cmds.getAttr(lattice + ".sz") * scaleU)
cmds.setAttr(lattice + ".sDivisions",newDivS)
cmds.setAttr(lattice + ".tDivisions",newDivT)
cmds.setAttr(lattice + ".uDivisions",newDivU)
ffd = cmds.listConnections(lattice + ".latticeOutput", d =True)[0]
baseShape = cmds.listConnections(ffd + ".baseLatticeMatrix", d =False, s =True)[0]
cmds.setAttr(baseShape + ".sx", cmds.getAttr(lattice + ".sx"))
cmds.setAttr(baseShape + ".sy", cmds.getAttr(lattice + ".sy"))
cmds.setAttr(baseShape + ".sz", cmds.getAttr(lattice + ".sz"))
実行はこんな感じで。
lattice = "ffd2Lattice"
addDiv = [0,1,0]
addFFDDiv(lattice,addDiv)
ただし、コントロールポイントの位置を編集していないlatticeのみ対応。