2018/06/30

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

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

これまで、
『制御される側(cubeA)』が『transformノード』のケースについてご紹介しましたが、
次は、
『制御される側(cubeA)』が『jointjointOrientに値が設定されているケースについてご紹介します。

本題に入る前に、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に変わりますが、jointOrientに値が設定されます。
※jointOrientのチェックボックスをOnで実行するとrotateの値は0に変わります。

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

【補足】translate、rotateに値が設定されたtransformノード(transformA)のtranslate、rotateの値を0にするには?

matrixその③~異なる軸のノードをmatrixで繋ぐ~』でご紹介した、アトリビュートと空間の考え方で対応できます。

①transformノードを作成します。
②transformAにParentConstraint(maintainOffset:Off)を実行して、位置と軸を合わせます。
③②のParentConstraintを削除します。
④transformAを①にペアレントします。

これで、transformAのtranslate 、rotateの初期値は0になり、ローカル軸を維持した状態になります。
私はこの親ノードを『ローカル空間』という意味を込めて『_space』と命名しています。
transformノードに対してはFreezeTransformationsは行わず、必ず親にspaceノードを作成しています。

 

◆inverseScale

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

 

【transformノードの階層スケール】
下図のように、transformA(transformノード)にtransformB(transformノード)
がペアレントされているデータで確認してみます。
※分かりやすくするためにmeshShapeをペアレントしています。

親のtransformAをスケールすると、子のtransformBも親の位置を基点にスケールします。

 

transformBのscale値を確認すると、デフォルト値の1から変化はありません。
親のtransformAをスケールしたので当然の結果です。

 

では、transformBのmatrixに変化はあるでしょうか?
decomposeMatrixを作成して、transformBのmatrixをdecomposeMatrixのinputMatrixに接続します。

アトリビュートエディターで、decomposeMatrixのoutputScaleの値を確認してみます。

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

 

【jointの階層スケール】
次に、上記のtransformノードと同じ位置、軸に設定したjointで確認してみます。
※分かりやすくするためにjointにmeshShapeをペアレントしています。

親のjointAをスケールすると、子のjointBは親のスケールの影響を受けていません。

 

親のスケールを打ち消しているように見えますが、
jointBのscaleの値を確認してみると、デフォルト値の1から変化はありません。

 

では、jointBのmatrixには変化があるでしょうか?
decomposeMatrixを作成し、jointBのmatrixをdecomposeMatrixのinputMatrixに接続します。

アトリビュートエディターで、decomposeMatrixのoutputScaleの値を確認してみます。

outputScaleの値に変化が見られます。
つまり、親をスケールすると子のローカルmatrixは、親のスケールを打ち消す分の影響を受けている事が分かります。

複雑なmatrixの接続を行う際、inverseScale分を考慮しないと、
とてもとてもとてもとても嵌ってしまうことがあります。
スケールの扱いには注意しましょう。

【補足】

jointをjointにペアレントすると、親のscaleと子のinverseScaleが自動的に接続されます。

階層から外す(アンペアレント)と接続は自動的に外れます。
inverseScaleの接続が外れれば、親のスケールを打ち消さないtransformノードと同様の挙動になります

また、jointの Segment Scale Compensate(SSC) のチェックボックスを外しても同様の挙動になります。

SSCのチェックボックスを外した場合、matrixはどう変化するのか是非確認してみてください。
※ゲームエンジンへの出力時には注意が必要です。

 

【問題】

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

 

まとめ

transformノードにはjointOrient、inverseScaleアトリビュートが存在しない。
jointにはjointOrient、inverseScaleアトリビュートが存在する。

jointのmatrixを扱う場合は、jointOrientとinverseScaleの成分に十分注意する。

つづく。

 

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


ブログTOPへ戻る