myara CG blog

CG Design Blog. Thoughts, experiments and experiences.

SI | 使われてないデフォーマーをゲットする

使われていないデフォーマーを選択するスクリプトです。

以前Twitterで出た話題ですが、何週間後に気付き今日は書いてみました。

メッシュを選んで、スクリプト実行すると、使われていない骨を選択してくれます。

それだけです。


ウェイト系のスクリプトの場合は Python や JScript に比べて VBS は圧倒的に速いと前から分かってはいるのですが、ちょっとだけ実験してみました。

まずは、Biped Nulls をだして、Local Subdivision で 3.8万ポリにしてみます。
そして、骨の数を4倍にします(308本)(メッシュを選択し、Set Envelopeにクリックして、複製した骨に中クリック)

これで良くあるキャラクターのスペックになったかな。下準備完了。

次は以下のコードを実行すると:

VBS 578 miliseconds
JScript 1239 milliseconds
Python 2210.0 miliseconds

メッシュを更にサブディビジョンかけると(15万ポリ):
VBS 2328 miliseconds
JScript 4965 milliseconds
Python 8812.0 miliseconds


やっぱり、VBS の勝利でした。
書くのは面倒だけど、ウェイト系のスクリプトはやっぱりVBSでやったほうが良いかも。

今までの実験だと、どうやらウェイトを取得するだけでVBSよりJSとPython がかなり時間が掛かってしまいます。
JSの場合は toArray() にしないといけないというところもあるけど、Pythonはそのまま使えるのになんでこんなに遅いのかまだ良く分かりません。

Pythonの方が書きやすいのに、なんか良い方法ないかな?
ないみたいね、割り切ってPythonの遅さを我慢するか、VBSの面倒くささを我慢する。それかtoArray()にしなきゃいけない面倒なJScriptでやるのか。


え? C 覚えろって?・・・いつかね。



では、また。



'VBS
Dim StartTime, EndTime, TimeIt
StartTime = Timer

set obj = selection(0)
set env = obj.envelopes(0)
set defs = env.deformers
set emptyDefs = XSIFactory.CreateObject( "XSI.Collection" )

for each def in defs
weights = env.GetDeformerWeights(def)
totalw = 0
for each weight in weights
totalw = totalw+ weight
next
if totalw = 0 then emptyDefs.Add(def)
next

EndTime = Timer
TimeIt = EndTime - StartTime
Logmessage Round(TimeIt*1000) & " miliseconds"


//JScript
var startDate = new Date();

var obj = selection(0)
var env = obj.envelopes(0)
var defs = env.deformers
var emptyDefs = XSIFactory.CreateObject( "XSI.Collection" )

for ( var i=0, a = defs.Count; i < a; i++ ) {
weights = new VBArray( env.GetDeformerWeights(defs(i))).toArray()
totalw = 0
for ( var j=0, b=weights.length; j < b ; j++ ) {
totalw = totalw+ weights[j]
}
if (totalw == 0) emptyDefs.Add(defs(i))
}

var endDate = new Date();
var timeTaken = endDate.getTime() - startDate.getTime();

LogMessage(timeTaken+' milliseconds');
SelectObj (emptyDefs)

#Python

app = Application
log = app.logmessage
from time import time

startTime = time()

obj = app.selection(0)
env = obj.envelopes(0)
defs = env.deformers
emptyDefs = XSIFactory.CreateObject( "XSI.Collection" )

for odef in defs:
weights = env.GetDeformerWeights(odef)
totalw = 0
for weight in weights:
totalw = totalw+ weight
if totalw == 0:
emptyDefs.Add(odef)

finishTime = time()
log(str(round((finishTime - startTime) * 1000))+ " miliseconds")

app.SelectObj(emptyDefs)