FC2ブログ

myara CG blog

CG Design Blog. Thoughts, experiments and experiences.

SI | Normal + Inmed モードでもウェイトが消えない方法

Softimage でInmedモード(ヒストリーが残らないモード)のままでウェイトが付いているオブジェクトにNormal(法線)ツールを使うと、ウェイトが消えてしまう。

Inmedモードで法線いじらなければ済む問題ですが、ついやってしまいます。

Inmedモードを切って、
法線をいじって、
Freeze M を掛けて
Inmedモードに戻す

という手順になりますが、これは自動に出来ないのかと今更思いついて書いてみました。

答えは、コマンドイベントを作って、以上の手順を自動にすればいいだけです。
なんで早くこれをやらなかったのかな!

以下のコードをPythonファイルに保存して

例:NormalsEvent.py



プラグインフォルダに入れる:

例: C:\Users\myara\Autodesk\Softimage_2015_SP1\Application\Plugins


ワークグループの場合は:

C:\Workgroup\Application\Plugins


それだけです。あとはSoftimageに任せてください。


from win32com.client import constants as c
xsi = Application

def XSILoadPlugin( in_reg ):
in_reg.Author = "myara"
in_reg.Name = "NormalsEvent Plug-in"
in_reg.Major = 1
in_reg.Minor = 0

in_reg.RegisterEvent("Normal_BeginCommand", c.siOnBeginCommand)
in_reg.RegisterEvent("Normal_EndCommand", c.siOnEndCommand)
#RegistrationInsertionPoint - do not remove this line

return True

def XSIUnloadPlugin( in_reg ):
strPluginName = in_reg.Name
Application.LogMessage(str(strPluginName) + str(" has been unloaded."), c.siVerbose)
return True

def Normal_BeginCommand_OnEvent( in_ctxt ):
Application.LogMessage("BeginCommand_OnEvent called", c.siVerbose)
Application.LogMessage("Command: " + str(in_ctxt.GetAttribute("Command")), c.siVerbose)

coms = ['Tweak Normal Tool', 'Average User Normals', 'Set User Normal Values', 'Set Vertex User Normals', 'Set Polygon User Normals', 'Invert User Normals', 'Normalize User Normals', 'Paste User Normals', 'Create User Normals']

if str(in_ctxt.GetAttribute("Command")) in coms:
UserImmed = xsi.GetUserPref("OperationMode")
if UserImmed == True :
xsi.SetGlobal('Normal_Immed', 1)
xsi.SetUserPref("OperationMode", False )

return False

def Normal_EndCommand_OnEvent( in_ctxt ):
Application.LogMessage("EndCommand_OnEvent called", c.siVerbose)
Application.LogMessage("Command: " + str(in_ctxt.GetAttribute("Command")), c.siVerbose)

coms = ['Tweak Normal Tool', 'Average User Normals', 'Set User Normal Values', 'Set Vertex User Normals', 'Set Polygon User Normals', 'Invert User Normals', 'Normalize User Normals', 'Paste User Normals', 'Create User Normals']

if str(in_ctxt.GetAttribute("Command")) in coms:
UserImmed = xsi.GetUserPref("OperationMode")
if xsi.GetGlobal('Normal_Immed') == 1 :
sel = xsi.Selection
for obj in sel:
if obj.Type.find('Component')!=-1:
obj = obj.SubComponent.Parent3DObject
xsi.FreezeModeling(obj)
xsi.SetUserPref("OperationMode", True )

return False


元から書いてある部分
Application.LogMessage("Command: " + str(in_ctxt.GetAttribute("Command")), c.siVerbose)

をあえて残しています。
このコマンドイベントは全てのコマンドを感知して、この行で使われたコマンドのログを残してくれる。
スクリプトエディターのプリファレンスにVerboseもログするようにしない限りログには出てこないけど、似たようなコマンドイベントを作りたい場合は便利だと思ったので、念のため残しておきます。

では、 続きを読む
スポンサーサイト



SI | mTextureEditor

現プロジェクトとその前のプロジェクトでUVの細かい作業が多くて、少しずつUVツールを作っていました。
今更ですが、SoftimageのUV周りのスクリプトの書き方が分かってきて、色々書いて出来たものはこのmTextureEditorです。

まだ調整が必要な部分があるけど・・・もう良いっか。EOLじゃなかったらもうちょっと頑張れたけどな。

Softimageまだ使っている人がいるのかな?
弊社ではまだSoftimageプロジェクトは2つが走っています。もちろん少なくなってきているけど、あと2年ぐらいSoftimageの案件があるのかな?

以下はmTextureEditorのマニュアル・ウェブサイト
http://skymill.co.jp/tools/Softimage/mTextureEditor/mTE_help.html



SI | mGridUV

UVツールを書き続けている。

今度は以前リクエストされたスクリプトです。

「CG自習部屋さんの Maya用 AriUVGridding」の Softimage パクリ版です。

パクったとは言っても、機能だけですよ。コードはパクってません。MayatとSoftimageが違いすぎて、そしてコメントのないmelは読みにくくてパクれませんでした。

実は自分もこういう機能が昔から欲しかったけど、どう作れば良いのかは全く分からなくて放置していました。
そしてある日、あまり関係ないツールのコードを見ていたら、アイデアが浮かんできた。ちょうど2週間前に時間があったから書き始めたら、できました!

やー面倒くさい! Softimage の サンプル(UV) は全てバラバラでマージという概念がないせいで、どれがどこと繋がっているのかは取得出来ない!
そしてループのループのループの永遠ループの確認はしんどい・・・。疲れた。

いろんなアプローチを試して、駄目なスクリプト20個ぐらい書いて、空いている時間だけだけどほぼ2週間掛かってしまいました。

AriUVGridding と少し操作が違います。

こちらはUVの島ではなく、選択されているUVだけを整列します。同じようにはしたかったけど、SoftimageでUV島の取得方法もないから、遅いループ処理になってしまう為、失敗スクリプト#10辺りでこういうアプローチはやめました。

ということで、ずっと欲しかったツールがSoftimageの開発がなくなって3年後にやっとできました!わーい!わーい!

俺みたいにまだSoftimageを使っている人のため、紹介します。

■使い方
・ 整列したいサンプルをテクスチャエディターで選択します。
・ スクリプト実行
・ オブジェクトのデータを取得して(ハイポリの場合は数秒が掛かります)、 カーソルがピックに変わります。
・ 整列の基になるサンプルを選ぶ ( 4エッジと繋がっているサンプルが条件 )
・ このサンプルの縦と横のループを直線化してから、このループの位置に合わせて残りのサンプルを整列します。
・ Fix Ratio オプションが有効になっている場合は、エッジの比率に合わせまて整列します。

■インストール方法
スクリプトなので、スクリプトファイルは好きなところに保存してから、
スクリプトエディターにドラッグ&ドロップして実行するか、ツールバーやシェルフにドラッグ&ドロップでボタンを作る。

■DOWNLOAD
https://www.dropbox.com/s/o8b10x9eaap1o5j/mGridUV.js?dl=0


下の動画のツールはまだPPG作っていなかった時のベータ版です。あれから少しバグを直して、簡単なPPGを作りました。

mGridUV beta from myara on Vimeo.

SI | MirrorUV

最近またSoftimageのUVツールを作っています。

今更ですねw

もうSoftimageツールなんか作らないと思っていたが、まだ仕事でSoftimageを使っていて、今のプロジェクトも再来年末の発売予定なので、しばらくSoftimageは使い続けます。もっとSoftimageの仕事を増やしましょう!!

で、今日は手が空いていたので実験的にUVのミラーツールを作ってみました。
UVなので、コンポーネントのループはめっちゃ多くなると予測して、久しぶりにPythonではなく、JScriptで書くことにしました。

選択されたUVのポリゴンを探して、そして反対側のポリゴンを探して、サンプルの位置を反対にするというアイデアから書き始めました。 ま、難しくはないと思いますが、ここにたどり着くにはそこそこ時間が掛かっちゃいました。

ループはたくさん使うので、出きるだけ処理を軽くする為に、オブジェクトコレクションを直接にループするのではなく、出きるだけ配列化してからループすることにしました。

例えば、XSI男の頭のサンプルを選択して、選択したサンプルをフェイスに変換したい。
2つの方法は思いつきます。

①コンポーネントのコレクションのループ。
オブジェクトのポリゴンを全てループして、ポリゴンのサンプルをループして、選択したサンプルと同じIDでしたら、そのポリゴンをポリゴンクラスターに入れておく

var oSample2Poly = oObj.ActivePrimitive.Geometry.CreateSubComponent(siPolygonCluster)
it = 0
var oFacets = oObj.ActivePrimitive.Geometry.Facets
for ( var i=0; i < oFacets.Count; i++ ) {
var oFacetSamples = oFacets(i).Samples
var oFacetIdx = oFacets(i).index
theloop:
for ( var j=0; j < oFacetSamples.Count ; j++ ) {
oFacetSampleIdx = oFacetSamples(j).index
for ( var k=0; k < oSampCol.Count ; k++ ) {
if (oSampCol(k).index == oFacetSampleIdx){
oSample2Poly.AddElement( oFacetIdx )
it++
break theloop
}
}
}
}

LogMessage ( it + 'iterations' )

ループの回数: 294
処理時間: 883 ミリ秒

数年前に書いた記事のループの最適化と同じやり方にすると

for ( var i=0, a = oFacets.Count; i < a; i++ ) {
・・・などなど

ループの回数:294
処理時間: 699 ミリ秒

ま、若干早くなりますが、たいした差がない。


で、もう一つの方法は
②オブジェクトの全てのポリゴンをループして、ポリゴンのサンプルをループして、配列にそのIDを入れておく。
選択したサンプルをループして、そのサンプルのIDを使って先ほどの配列でこのサンプルのポリゴンを探して、ポリゴンIDをクラスターに入れる。


it=0
var aSample2Facets = []
var oFacets = oObj.ActivePrimitive.Geometry.Facets
for ( var i=0, a = oFacets.Count; i < a; i++ ) {
var oFacetSamples = oFacets(i).Samples
for ( var j=0, b=oFacetSamples.Count; j < b ; j++ ) {
aSample2Facets[oFacetSamples(j).Index] = oFacets(i).Index
it++
}
}

var oSample2Poly = oObj.ActivePrimitive.Geometry.CreateSubComponent(siPolygonCluster)
for ( var i=0, a = oSampCol.Count; i < a; i++ ) {
oSample2Poly.AddElement( aSample2Facets[oSampCol(i).Index] )
it++
}

LogMessage ( it + 'iterations' )

結果:
ループ回数:2304
処理時間: 30ミリ秒

コードが若干長くて、ループの回数も多いけど、処理は29.4倍も速い ! 29倍 !
期待以上だな。


えっ? 今更 Softimage  しかも JScript ?
時代は Python だと?

Python は基本的に処理が遅い方なので、MayaでPythonを書く時にもこういう風に工夫して書いたりしています。

例えば、頂点一個ずつの位置を取得するより、オブジェクトの頂点の情報を全部一回配列にとっておくと後の処理はかなり早くなります。


あっ、忘れていた、ツールですね。

今はGUIなどないですけど、スクリプトでよければここにアップしました。
https://www.dropbox.com/s/klutsonp12hp4zs/mirrorUV_script.js?dl=0


Softimage : MirrorUV from myara on Vimeo.



Maya | mSetProject 2: シーンを開く前に自動プロジェクト設定

以前作ったmSetProject の進化版です。

mSetProject 1 はシーンを開いた後にプロジェクト設定は自動に行っていました。
このままだとテクスチャのパスはフルパスになってしまうので、フルパスをローカルパスに変更するスクリプトも掛けていました。

しかし、リファレンスや同名ファイルが入っている場合は不便ですね。
欲しいのは、手動でやっていることと同じ、シーンを開く前にプロジェクト設定。

色々調べて、ちょっと諦めていたところに OpenMaya の MSceneMessage というコマンドをみつけました。
この記事(英語)はすごく参考になりました。

ブログにアップするのは忘れていましたので、今更だけど良かったら使ってみてください。

使い方:
適当にどこかに解凍してください
mSetProject.py ファイルは scripts フォルダにコピー (例:C:\Users\myara\Documents\maya\scripts)

scripts フォルダに userSetup.py が存在していない場合は:
同封されている userSetup.py をそのまま scripts フォルダにコピー

scripts フォルダに userSetup.py が存在している場合は:
そのファイルを編集して以下の2行を追加するだけです。

import mSetProject
mSetProject.main()




Download:
https://www.skymill.co.jp:5555/sharing/7jdy7SdNS
次のページ