BACKBONE RIG&TA EXPERTS

matrixその④~transformノードとjointの違い~

2018/06/30

BACKBONEの福本です。
matrix続きです。
まだまだ続きます。

 

お気付きの方もいらっしゃると思いますが、実はこれまで『制御される側(cubeA)』は『transformノード』でした。
次は『制御される側(cubeA)』が jointでjointOrientに値がある場合、についてご紹介します。
本題に入る前に、transformノードとjointとの違いを確認しておきましょう。

 


transformノードとjointとの違い

細かい説明は別途行うとして、大きな違いは
transformノード には、jointOrientinverseScaleのアトリビュートが存在しません
joint には、jointOrientinverseScaleのアトリビュートが存在します

 

◆jointOrient

jointに存在するアトリビュートで、rotateアトリビュートと同様に回転を制御します。
例えば、translate、rotateに値が設定されたtransformノードに対しFreezeTransformationsを実行すると、
translate、rotateのアトリビュート値は0に変わり
rotatePivot、scalePivotに値が設定されます。
軸もworld軸に変わります。

 

一方、上記transformノードと同じ位置、軸に設定したjointに対し
FreezeTransformations(jointOrientのチェックボックスはOff)を実行すると、
translateの値は0に変わらず、rotatePivot、scalePivotにも値は設定されません。
rotateの値は0に変わりますが、rotatePivot、scalePivotではなく、jointOrientに値が設定されます。
※jointOrientのチェックボックスをOnで実行すると、rotateの値は0に変わります。

 

このように、transformノードにFreezeTransformationsを実行すると、回転がワールド軸に変わってしまうのに対し、
jointでは元のrotate値をjointOrientで吸収して、ローカル軸を維持することができます。
では、transformノードでローカル軸を維持しつつtranslate、rotateの値を0にする、にはどうすればよいでしょうか?

 

『matrixその③~異なる軸のノードをmatrixで繋ぐ~』でご紹介した、アトリビュートと空間の考え方で対応できます。
同じ位置、軸のtransformノードを作成し、そのノード内に格納してtranslate、rotateの値を0にすると、
ローカル軸を維持しつつ、translate、rotateの値を0にすることができます。
私はこの親ノードを、『ローカル空間』という意味を込めて『_space』と命名しています。
コントローラなどのtransformノードに対しては、FreezeTransformationsは行わず、
必ず、親にspaceノードを作成するようにしています。

 

◆inverseScale

jointに存在するアトリビュートです。
inverseScaleアトリビュートを使用すると、親のスケールの影響を打ち消すことができます。
inverseは日本語の意味で『逆』で、直訳すると『逆スケール』です。
transformノードとjointで挙動を比較してみましょう。

 

【transformノードの階層スケール】
下図のようにtransformノード(transformA)にtransformノード(transformB)
が階層化されているデータで確認してみます。
※分かりやすくするためにCubeを使用しています。
親のtransformAをスケールすると、子のtransformBも親の位置を基点にスケールします。

 

transformBのscale値を確認してみると、デフォルト値の1で変化はありません。

 

transformBのmatrixは変化があるでしょうか?
decomposeMatrixを作成し、transformBのmatrixをdecomposeMatrixのinputMatrixに繋ぎます。
アトリビュートエディターで、decomposeMatrixのoutputScaleの値を確認してみます。

デフォルト値の1で変化はありません。
つまり、
親をスケールしても子のローカルmatrixは影響を受けていない事が分かります。

 

【jointの階層スケール】
上記transformノードと同じ位置、軸に設定したjoint階層で確認してみます。
※分かりやすくするためにjointにmeshShapeをペアレント化しています。
親のjointAをスケールすると、子のjointBは親のスケールの影響を受けていません。

 

これは、親のjointAのscaleと子のjointBのinverseScaleが繋がっており、
親のスケールの情報をinverseScaleで打ち消しているからです。

 

jointBのscaleの値を確認してみると、デフォルト値の1で変化はありません。

 

では、jointBのmatrixには変化があるでしょうか?
decomposeMatrixを作成し、jointBのmatrixをdecomposeMatrixのinputMatrixに繋ぎます。
アトリビュートエディターで、decomposeMatrixの値を確認してみます。

outputScaleの値に変化が見られますね。
つまり、
親をスケールすると子のローカルmatrixは、親のスケールを打ち消す分の影響を受けている事が分かります。
複雑なmatrixの接続を行う際、inverseScale分を考慮しないと、とてもとてもとてもとても、嵌ってしまうことがあります。
スケールの扱いには注意しましょう。


(補足)joint同士を階層化すると、自動的に、親のscaleと子のinverseScaleが繋がります。
joint階層から外すと、自動的にinverseScaleの接続が外れます。
inverseScaleの接続が外れれば、親のスケールを打ち消さないtransformノードと同様の挙動になります
また、jointの Segment Scale Compensate(SSC) のチェックボックスを外しても同様の挙動になります。
SSCのチェックボックスを外した場合、matrixはどう変化するのか、是非確認してみてください。
※ゲームエンジンへの出力時には注意が必要です。

 

【問題】
jointでは、inverseScaleアトリビュートを用いて親のスケールを相殺することができますが
transformノードで同様のことが出来るでしょうか?
少し複雑なコネクションになりますが、transformノード、scaleConstraint、pointMatrixMultのみで再現出来ます。
ご興味のある方はトライしてみてください。
(結果とヒント)

 

では、本題に戻ります。
つづく。

 

 

※免責事項※
本記事内で公開している全ての情報について、その完全性、正確性、適用性、有用性等いかなる保証も行っておりません。
これらの情報のご利用により、何らかの不都合や損害が発生したとしても、当社は何らの責任を負うものではありません。
自己責任でご使用ください。