2009年から仕事でMAYAを勉強。MAYAはデフォルトでは使い勝手が悪い。逆にスクリプトを覚えてカスタマイズするとかなり強力なツールになることがわかってきた。

物覚えが悪いので勉強したことはリマインダとしてココに書き留めるようにする。

2009年5月20日水曜日

【MEL】頂点ウェイトの値から端数を取る

今日から暫くのお題は「頂点ウェイトの値から端数を取る」
ゲームでは特に端数が困る場合があるのと、MAYAでウェイト値を修正しようとするととんでもない労力がかかるのでボタン一発で端数が消えるようにしたい。

モデルは専門外なので基本的なところを調査。まずpCube1を出してジョイントにスムースバインド。

任意のモデルの任意の頂点を選択するコマンド
select -r pCube1.vtx[0]

その頂点のウェイト値を変更すると以下のコマンドが履歴に出る
skinPercent -tv joint2 0.3 skinCluster1 pCube1.vtx[0];

頂点0番のウェイト情報を調べるには以下
skinPercent -query -value skinCluster1 pCube1.vtx[0];
// 結果: 0.5 0.448465 0.0515349 // ←こんな感じで出る

自動で頂点ウェイトが正規化されてしまうと操作できないのでノーマライズを一旦オフ
skinPercent -nrm false -tv joint1 0.5 skinCluster1 pCube1.vtx[0];
//-nrm = -normarize デフォルトはtrue

--------------------------------------------
とにかく1個の頂点でやりたい事ができれば、あとはループで全部回すだけのはず。


$testval = `skinPercent -query -value skinCluster1 pCube1.vtx[0]`;
こうすると$testvalにウェイトの値が入る。

for ( $val in $testval)
{
print ($val + "\n");
}
0.4586304275
0.4586304275
0.08273914506

おお、配列として格納されている。これを四捨五入して書き戻すだけで合計1のきれいな数値になるはずだんが。

ネットで調べた、俺レベルで一番理解しやすかったのは
”0.005を足して、100倍してfloorで小数点以下を切り捨てて100で割る”
これいってみよう。例によってまずベタ書きする。

{
$testval = `skinPercent -query -value skinCluster1 pCube1.vtx[0]`;
float $wgtvalue;

for ( $val2 in $testval)
{
$wgtvalue = $val2;
print ($wgtvalue + "\n");
$wgtvalue += 0.005;
$wgtvalue = $wgtvalue *100;
$wgtvalue = `floor $wgtvalue`;
$wgtvalue = $wgtvalue /100;
print ($wgtvalue + "\n");
}

}

★★★結果↓★★★
0.4025395377
0.4
0.4025395377
0.4
0.1949209247
0.19

ってオイ!合計が1にならんよ!! 合計が1なら四捨五入しても1になると思ってたorz 
というわけで1にならない場合の処理か、必ず1になる処理を考えないとイカン.
 ちなみに要素数が3個とは限らないので底も考慮しなくてはならない。個数はsizeで調べればわかるので、最後の1個は四捨五入せずに(1-それまでの計算結果の合計)としないといけない。


★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
//ウェイト値を引っ張ってきて小数点以下1位までに丸める処理

{
$testval = `skinPercent -query -value skinCluster1 pCube1.vtx[1]`;

//ウェイトを”値”として操作するのに一時代入する変数を作る
float $wgtvalue;
//最後の1回の例外処理を回すための条件判断用変数
int $numloop = `size $testval`;
//最後の1回はこの値から今までの値を引き算して求める
float $wgtamount = 10; //小数点以下2位まで残すならここが100
//最後に書き戻す用配列
float $pointwgt[];
$count = 0;

for ( $val2 in $testval)
{
$numloop--;

//print $count;
if ( $numloop >0)
{
$wgtvalue = $val2;
//print ($wgtvalue + "\n");
$wgtvalue += 0.05; //小数点以下2位まで残すならここが0.005
$wgtvalue = $wgtvalue *10; //小数点以下2位まで残すならここが100
$wgtvalue = `floor $wgtvalue`;
//
$wgtamount = ($wgtamount - $wgtvalue);
//
$wgtvalue = $wgtvalue /10; //小数点以下2位まで残すならここが100 。ここの値が現在の頂点のウェイト値になる
$pointwgt[ $count ] = $wgtvalue;
print ("\n配列の中身"+ $count + "\n" + $pointwgt[ $count ] + "\n");
$count++;
}
else
{
//print ($wgtamount + "\n");
$wgtamount = $wgtamount /10;//小数点以下2位まで残すならここが100。ここの値が現在の頂点の最後のウェイト値になる
//print $wgtamount;
$pointwgt[ $count ] = $wgtvalue;
print ("\n配列の中身"+ $count + "\n" + $pointwgt[ $count ] + "\n");
}
print "\n\n配列の中身\n";
print ($pointwgt[0] + "\n");
print ($pointwgt[1]+ "\n");
print ($pointwgt[2]+ "\n");
print `size $pointwgt`;


//配列をウェイトに書き戻す処理

//これじゃだめ。3つのウェイトの1番目に3回代入してるだけになってる
int $val;
$count = 1;
$jname = "joint" + $count;

for ( $val in $pointwgt )
{
skinPercent -nrm false -tv $jname $pointwgt[$val] skinCluster1 pCube1.vtx[4];
$count++;
}

}
}

$testval = `skinPercent -query -value skinCluster1 pCube1.vtx[4]`;

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
これでウェイトを丸めて配列に格納するところまでDONE
しかし頂点に戻せない!


続く






0 件のコメント: