ヘアースタイリングツールを作ってみました。
初めに断っておきますが、このツールは、スクリプテッドオペレータを使用しています。
で、そのスクリプテッドオペレータが存在している状態で、保存すると二度とデータは復帰出来ません。
という超危険な仕様なので、使い方は気をつけてくださいw
保存するときは、ヘアについてる、Hair2Curveをすべて消してからにしましょう。
使い方は、下記画像さんしょ。
ヘアを選択して実行するやつ
Hair2Curve.pys
#---------------------------------------------------
app=Application;log=app.LogMessage;sel=app.Selection
import win32com.client
#---------------------------------------------------
if sel.Count==0 or sel(0).type!="hair":
raise
sCode = """from win32com.client.dynamic import Dispatch as d
def Hair2Curve_Update(ctx,OutPrim,InPrim):
oCrvCol = InPrim.Value.Geometry.Curves
lHairPos = [[],[],[]]
for oCrv in oCrvCol:
for fHairPer in [f/13.000*99.999+0.001 for f in range(14)]:
vPos = d(oCrv.EvaluatePositionFromPercentage(fHairPer)[0])
lHairPos[0].append(vPos(0))
lHairPos[1].append(vPos(1))
lHairPos[2].append(vPos(2))
OutPrim.Value.GetGeometry2(ctx.CurrentFrame).Points.PositionArray = lHairPos
"""
oCrvCol = win32com.client.Dispatch("XSI.Collection")
for oHair in sel:
oHair.AllowStretch.Value = True
lPos=[[f for f in l] for l in oHair.ActivePrimitive.Geometry.Points.PositionArray]
iStrNmb=len(lPos[0])/14
lPos.append(list([1])*len(lPos[0]))
oCrv = oHair.Parent.AddNurbsCurveList()
for i in range(iStrNmb):
oCrv.ActivePrimitive.Geometry.AddCurve(
[ lPos[0][i*14:i*14+14],
lPos[1][i*14:i*14+14],
lPos[2][i*14:i*14+14],
lPos[3][i*14:i*14+14] ],
range(14),
False,
1,
1
)
oFitCrvOp = app.ApplyGenOp("CrvFit", "", oCrv, 3, "siPersistentOperation", "siKeepGenOpInputs", "")(0)
oFitCrvOp.points.Value = 3
log(oFitCrvOp.Parent3DObject)
oFitCrv = oFitCrvOp.Parent3DObject
oHair.Parent.AddChild(oFitCrv)
oTransfo = oHair.Kinematics.Global.Transform
oFitCrv.Kinematics.Global.Transform = oTransfo
app.FreezeModeling(oFitCrv)
app.DeleteObj(oCrv)
#app.ToggleVisibility(oFitCrv)
oCrvCol.Add(oFitCrv)
app.Refresh()
oOpr = oHair.ActivePrimitive.AddScriptedOp(sCode,oFitCrv.ActivePrimitive,"Hair2Curve","Python",1)
sel.SetAsText(oCrvCol.GetAsText())
そんでもって、Hair2CurveOpを消すスクリプトは、これです。
FreezeHair2Curve.pys
#---------------------------------------------------
app=Application;log=app.LogMessage;sel=app.Selection
import win32com.client
from win32com.client import constants as c
from win32com.client.dynamic import Dispatch as d
#---------------------------------------------------
app.ActivateObjectSelTool()
oHairPrimCol = app.FindObjects("","{D5C3CDBA-B361-4A11-9582-91DBA0ECBB49}")
for oPrim in oHairPrimCol:
oOp = oPrim.NestedObjects("Hair2Curve")
if oOp:
log(oOp)
oCrv = d(oOp).InputPorts(0).target2.Parent3DObject
app.FreezeObj(oPrim.Parent3DObject)
app.DeleteObj(oCrv)
いやいや、おっかねぇスクリプトですね。
会社でなんて使わせられません。
そもそも、Hairにスクリプテッドオペレータが適用出来ないXSI様が悪いんですけどね。
HairにICE適用出来ないのも悪いですね。
そいや、Softimage2010を使い始めましたわ。
2010になって、HairにICE適用出来るようになったのかしら。
後でやってみよーっと。
FaceRobotは、なかなか素晴らしいものがありますね。
顎とか、口まわりとか、目まわりとか。
顔は、モーションキャプチャの場合、Envelopeのほうが断然楽ですな。
ただし、後付け修正したいので、Shapeで加えるとかですかね。
もちろん、移動差分の骨のクリップを並べて、MixerのNormalizeをオフって加算でやるのもいいですね。
どっちも得手不得手があるので、それぞれ選ぶべきですなー。
データは軽く作れよっ。
初めに断っておきますが、このツールは、スクリプテッドオペレータを使用しています。
で、そのスクリプテッドオペレータが存在している状態で、保存すると二度とデータは復帰出来ません。
という超危険な仕様なので、使い方は気をつけてくださいw
保存するときは、ヘアについてる、Hair2Curveをすべて消してからにしましょう。
使い方は、下記画像さんしょ。
ヘアを選択して実行するやつ
Hair2Curve.pys
#---------------------------------------------------
app=Application;log=app.LogMessage;sel=app.Selection
import win32com.client
#---------------------------------------------------
if sel.Count==0 or sel(0).type!="hair":
raise
sCode = """from win32com.client.dynamic import Dispatch as d
def Hair2Curve_Update(ctx,OutPrim,InPrim):
oCrvCol = InPrim.Value.Geometry.Curves
lHairPos = [[],[],[]]
for oCrv in oCrvCol:
for fHairPer in [f/13.000*99.999+0.001 for f in range(14)]:
vPos = d(oCrv.EvaluatePositionFromPercentage(fHairPer)[0])
lHairPos[0].append(vPos(0))
lHairPos[1].append(vPos(1))
lHairPos[2].append(vPos(2))
OutPrim.Value.GetGeometry2(ctx.CurrentFrame).Points.PositionArray = lHairPos
"""
oCrvCol = win32com.client.Dispatch("XSI.Collection")
for oHair in sel:
oHair.AllowStretch.Value = True
lPos=[[f for f in l] for l in oHair.ActivePrimitive.Geometry.Points.PositionArray]
iStrNmb=len(lPos[0])/14
lPos.append(list([1])*len(lPos[0]))
oCrv = oHair.Parent.AddNurbsCurveList()
for i in range(iStrNmb):
oCrv.ActivePrimitive.Geometry.AddCurve(
[ lPos[0][i*14:i*14+14],
lPos[1][i*14:i*14+14],
lPos[2][i*14:i*14+14],
lPos[3][i*14:i*14+14] ],
range(14),
False,
1,
1
)
oFitCrvOp = app.ApplyGenOp("CrvFit", "", oCrv, 3, "siPersistentOperation", "siKeepGenOpInputs", "")(0)
oFitCrvOp.points.Value = 3
log(oFitCrvOp.Parent3DObject)
oFitCrv = oFitCrvOp.Parent3DObject
oHair.Parent.AddChild(oFitCrv)
oTransfo = oHair.Kinematics.Global.Transform
oFitCrv.Kinematics.Global.Transform = oTransfo
app.FreezeModeling(oFitCrv)
app.DeleteObj(oCrv)
#app.ToggleVisibility(oFitCrv)
oCrvCol.Add(oFitCrv)
app.Refresh()
oOpr = oHair.ActivePrimitive.AddScriptedOp(sCode,oFitCrv.ActivePrimitive,"Hair2Curve","Python",1)
sel.SetAsText(oCrvCol.GetAsText())
そんでもって、Hair2CurveOpを消すスクリプトは、これです。
FreezeHair2Curve.pys
#---------------------------------------------------
app=Application;log=app.LogMessage;sel=app.Selection
import win32com.client
from win32com.client import constants as c
from win32com.client.dynamic import Dispatch as d
#---------------------------------------------------
app.ActivateObjectSelTool()
oHairPrimCol = app.FindObjects("","{D5C3CDBA-B361-4A11-9582-91DBA0ECBB49}")
for oPrim in oHairPrimCol:
oOp = oPrim.NestedObjects("Hair2Curve")
if oOp:
log(oOp)
oCrv = d(oOp).InputPorts(0).target2.Parent3DObject
app.FreezeObj(oPrim.Parent3DObject)
app.DeleteObj(oCrv)
いやいや、おっかねぇスクリプトですね。
会社でなんて使わせられません。
そもそも、Hairにスクリプテッドオペレータが適用出来ないXSI様が悪いんですけどね。
HairにICE適用出来ないのも悪いですね。
そいや、Softimage2010を使い始めましたわ。
2010になって、HairにICE適用出来るようになったのかしら。
後でやってみよーっと。
FaceRobotは、なかなか素晴らしいものがありますね。
顎とか、口まわりとか、目まわりとか。
顔は、モーションキャプチャの場合、Envelopeのほうが断然楽ですな。
ただし、後付け修正したいので、Shapeで加えるとかですかね。
もちろん、移動差分の骨のクリップを並べて、MixerのNormalizeをオフって加算でやるのもいいですね。
どっちも得手不得手があるので、それぞれ選ぶべきですなー。
データは軽く作れよっ。
コメント
いつもブログを拝見させて頂いて、参考にさせて頂いています。
自分はインゲームのモーションデザイナーなのですが、自分でスクリプトを組んだりもしています。
いくつかツールを作ったのですが、GUIが無いため不便に感じるツールがあります。
そこでPPGに関して勉強しようと思いネットなどの情報を参考に簡単なものを組んでみたのですが、うまくいきません。
何処かにシンプルなコードが記載されているようなページなどをご存知ないでしょうか?
Pythonでプログラミングを始めて半年くらいになるのですが、GUI無し小規模の簡単なツールは作れても、GUIに関してはプルダウンメニューすらろくに作れていない状態です。
見てくれてありがとうございます。
ひさびさのコメントだぁ!
いやはやうれしいですね。
さて、PPGのシンプルコードですが、ずばり言うとマニュアルですかねぇ・・・。
マニュアルとお友達になれば、ネットの海を泳ぐ必要はありませんよ。
にらめっこして、頑張って分かりあえるようにしてみてください。
手前味噌ですが、sukio-sukio-sukio-python IVを参考にしてみてください。
プルダウンは、ちょっとだけ難しいものがありますね。
ヒントを差し上げると
Items = ["Item1","0", "Item2","1","Item3","2"]
oLayout.AddEnumControl("pru", Items, "Label", "siControlCombo")
という書式です。
AddEnumControlのUIItemsArrayには、リストを入れます。
このリストはちょっと特殊ですが
[表示1,値1,表示2,値2,・・・]
という書き方です。
あとは、[UIType]に"siControlCombo"を入れればOKです。
プルダウンを変えるには
PPG.pru.Value = 1
とか、2とか、値を入れれば変わります。
いけるかな?
コメントへのお返事ありがとうございました。
自分はなんでも答えを急ぐほうで、Pythonを勉強し始めた際にも自分の使う項目だけ覚えてあとはほったらかし状態なので、基本が微妙にみについていない所があります。 なのでSDKとにらめっこしてもなかなか理解が深まらなかったりしてます・・・ちゃんとプログラミングってものを基本から体に叩き込んだほうが良いと言うのがよくわかりました。
自分はモーション屋なので仕事中にプログラミングに没頭することは出来ませんが、PythonとC++は基本からキッチリ勉強していこうかと思います。(元ガテン系の体力仕事してた転職組みなんで脳ミソつかうのはなかなかしんどいですがw)
ちなみに、お返事いただく前にプルダウンの表示はできました。from win32com.client import constants as c を記入するのを忘れていました。例によってこれを記入するって事は知っていても、これがなんなのかを理解していないので、このへんも勉強せねばなりませんね!あぁ未熟なりです。
pythonを使うには、いろいろあるんで、その部分を体に染み込ませればいけますよ。
物事を理解するには経験から!
まだ、半年で、PPG入るレベルなら結構出来る方なんじゃないでしょうかね。
元ガテン系なら尚更です。素晴らしいですね。
モーション屋って、意外とスクリプト使うんですよね。
plotだとか、ヌル追加したいだけとか、細かいマクロ的なものが沢山あるんで、気づけたのは、大いに意味がありますよ。
今後の成長に期待大ですね。