2009年7月16日木曜日

頂点ブレンディング

ボーンアニメーションのために、もう1つ出力しないといけない情報が残っていました。
頂点ブレンディングです。頂点ブレンディングとは簡単に言ってしまうと、面の曲がりを滑らかにするための手法ということでしょうか。
頂点ブレンディングを使わずに単純に各頂点をボーンに割り当てると、ボーンとボーンの間の頂点が回転によってお互いに行き違いになって見た目がくしゃっとなってしまいます。(上の画像の左側) 実際、ボーンとボーンの間の頂点は、どちらか一方のボーンだけじゃなく両方のボーンの影響を加味して変換してやる必要があるのです。
そのために、頂点ブレンディングを使います。例えば、A、B2つのボーンがあるとした場合、A、Bの間にあるような頂点は、A、B両方のそれぞれから影響を受けるような設定にします。具体的には
Aの変換 x 0.5 + Bの変換 x 0.5
というふうに、どのボーンからどれだけ影響を受けるかという重みを各頂点に設定することになります。また0.5ずつじゃなく、
Aの変換 x 0.7 + Bの変換 x 0.3
などとすることもできます。各重みの合計が1.0(=100%)になるようにする必要があります。また、A、B、Cの3つのボーンの影響を受ける頂点は、
Aの変換 x 0.6 + Bの変換 x 0.3 + Cの変換 x 0.1
などとします。影響を受けるボーンが4つ以上でも同様です。重みを加味してやると上の画像の右側のような曲がり方になります。曲がり方は各ボーンへの重みを変えることで調整することができます。

重みを出力する行は次のようなフォーマットです。
W 頂点番号1 重み1 頂点番号2 重み2 頂点番号3 重み3

識別子のWはWeightのWです。ボーン単位でそのボーンに重みが設定されている頂点の番号と重みを出力します。
以前つくったボーンの情報(B行)を出力するwriteBone()関数の中で以下のようにW行を出力するようにしました。

def writeBone(out, mesh, bone, level):
:
grp = mesh.getVertsFromGroup(bone.name, True)
if len(grp) > 0:
out.write("W")
for i in grp:
out.write(" %d %f" % (i[0], i[1]))
out.write("\n")
if bone.hasChildren():
for b in bone.children:
writeBone(out, mesh, b, level+1)

meshのgetVertsFromGoup()で頂点と重みのリストを取得して出力しています。

これでひとまず必要な情報は全てファイルに出力したので、次はC++での読み込みになります。

0 件のコメント: