スキニング

スキニングは、ジョイントまたはその他のインフルエンス オブジェクトのトランスフォーム(変換)に従ってシェイプを変形するプロセスです。スキニングには、スムーズとリジッドの 2 つのタイプがあります。スムーズ スキニングでは、バインドするとすぐにジョイントの周囲がスムーズになるスキンが作成され、ウェイトを修正してより高いカスタマイズ効果を得ることができます。リジッド スキニングでは、最初のうちはアタッチされたジョイントにペアレント化されているかのように動作するスキンが生成されます。いずれかのフレクサを追加してジョイントの周囲にスムージングを生成したり、リジッド jointCluster ノードのウェイトを変更してカスタマイズ効果を高めることができます。スムーズ スキニングとリジッド スキニングの間の違いを次の表に示します。

詳細 スムーズ スキニング リジッド スキニング
ノード タイプ skinCluster jointCluster
API タイプ MFn::kSkinCluster MFn::kJointCluster
API 関数セット MFnSkinCluster MFnWeightGeometryFilter
インフルエンス オブジェクト すべてのトランスフォーム タイプ ジョイント
デフォーマの数 スキンごとに 1 つ ジョイントごとに 1 つ
ウェイトの数 インフルエンス/CV ごとに最大 1 つ CV ごとに 1 つ
ウェイトを編集する MEL コマンド skinPercent パーセント(Percent)

最も大きな違いは、リジッド スキニングでジョイントごとに 1 つの jointCluster が作成される点です。その後、JointCluster は、ジョイントに厳密にバインドされているすべてのスキンによって共有されます。リジッド スキニングとは異なり、スムーズ スキニングでは、スキンごとに 1 つの skinCluster が作成され、スキンに影響を与えるすべてのインフルエンスが skinCluster に接続されています。

一般的に、スムーズ スキニングの方が容易であり、ウェイトが指定されているインフルエンスの数によっては、スムーズ スキニングのアルゴリズムの方が計算が速くなります。

スムーズ スキニングでのノード構成

スムーズ スキニングでは、スキンごとに 1 つの skinCluster を割り当てます。他のデフォーマとは異なり、スキンをさらに追加するために、skinCluster のセットのメンバーシップを修正することはできません。各スキンには専用の skinCluster が必要です。skinCluster のセットのメンバーシップは、たとえば、オブジェクトの半分だけをスキンする場合などに、頂点を除去することで修正できます。

SkinCluster では、任意の数のインフルエンス オブジェクトを指定できます。インフルエンス オブジェクトの worldMatrix 出力は、skinCluster の行列アトリビュートに接続されます。この接続のアトリビュート logicalIndex は、skinCluster がインフルエンスをウェイトに関連付けるために使用します。API メソッド MFnSkinCluster::indexForInfluenceObject を使用すると、skinCluster を照会して、関連するインフルエンス オブジェクトのインデックスを決定できます。

SkinCluster のウェイトは、weightList[].weights[] と呼ばれる multi-multi アトリビュートに格納されます。1 番目の multi のインデックスは、頂点のインデックスです。2 番目は、インフルエンス オブジェクトのインデックスです。通常、ウェイトはまばらに格納されるため、50 のインフルエンス オブジェクトのうち、2 つを頂点のウェイトに指定した場合、その頂点のウェイト配列には 2 つの要素のみが存在します。例外として、データがデータ ブロック内に存在し、何らかの操作によって後でゼロに設定された場合は、ゼロ値のデータがファイルが保存されるまでデータ ブロック内に残ります。ファイルの保存時に、ファイル保存コードによって、ゼロ値は保存の必要がない既定のデータであると判断されます。次回ファイルを読み込むと、skinCluster にはゼロ以外の値の要素のみが存在します。

バインド時のジョイントのトランスフォーム(変換)は、bindPose と呼ばれます。スキニング アルゴリズムはこの情報を使用してデフォメーションを実行します。bindPose は、dagPose ノードと呼ばれるノードに格納されます。bindPose を復元するには追加のディテールが必要になるため、bindPose は、スキニング アルゴリズムによってディテールに格納されます。

dagPose ノードは、バインド時にすべてのインフルエンスの worldMatrix を格納します。また、ローカル行列を完全な変換行列(MTransformationMatrix)として格納し、ペアレント化情報を格納します。worldMatrix のみがスキニング アルゴリズムによって使用され、bindPreMatrix アトリビュートの skinCluster ノードに含まれています。bindPreMatrix は、そのマルチ インデックスを関連するインフルエンス オブジェクトに関連付けるマルチ アトリビュートです。

ジョイントの場合のみ、bindMatrix も bindPose アトリビュートに格納されます。ジョイントにはバインド関連のアトリビュートが他にもありますが、これらは Maya 4.0 ではサポートされず、下位互換性を維持する目的のみに使用されます。

アルゴリズム

各ポイント P にウェイトのセット {w1,w2,...,wn} が割り当てられます。既定のウェイト値がゼロのスキンに影響を与える n インフルエンス オブジェクトごとに 1 つのウェイトが割り当てられます。通常、次の方程式が適用されます。

w1 + w2 + ... + wn = 1.0

Ti がインフルエンス i の現在のワールド変換行列であり、Bi がバインド時の同じインフルエンスのワールド変換行列である場合。W(p) がバインド時に P のワールド位置である場合、次の方程式に示すように、Li(p) をインフルエンス i のローカル座標系のポイント P の位置として計算することができます。

Li(p) = Bi - 1 x W(p)

その後、次の方程式に示すように、トランスフォーム i でペアレント化されている場合のポイントのワールド位置を計算できます。

Ni(p) = Ti x Li(p)

次の方程式に示すように、このワールド位置と、対応するインフルエンス i のウェイトを乗算することで、Mi(p) を得ることができます。

Mi(p) = wi x Ni(p)

次の方程式に示すように、ここですべての Mi(p) を加算して、ワールド空間のポイントの変形位置を取得します。

NewWorldPos(p) = M1(p) + M2(p) + ... + Mn(p)

すべての回転はジョイント/トランスフォームピボットで発生し、リニア補間は、最終的なポイント位置を計算するために、ウェイトを使用して実行されます。