2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

maya latticeのdivを幅維持したまま増やしたい

Posted at

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のみ対応。

2
1
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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?