ダンスをさせる計算。
1. ボーンの可視化
3D CGモデルのダンスはボーン(骨)を回転したり移動させたりする計算が必要です。まず、前回のPMDモデルのボーンを可視化してみます。
In[100]:=f["Bones"][[1]]
Out[100]={"センター", 65535, 116, 1, 0, {0., 8., 0.}}
ボーンは、{ボーン名、親のボーンID、子のボーンID、ボーンの種類、IK影響化フラグ、ボーンの位置}のリストで構成されています。
PMDファイルの詳細については、MMDのモデルデータ(PMD)形式 めも (まとめ)を参照ください。
あにまさ式初音ミクの場合、ボーンは下記140個ほどあります。
In[101]:= #[[1]] & /@ f["Bones"]
Out[101]= {"センター", "上半身", "首", "頭", "左目", "右目", "ネクタイ1", \
"ネクタイ2", "ネクタイ3", "下半身", "腰飾り", "左髪1", "左髪2", "左髪3", "左髪4", \
"左髪5", "左髪6", "左肩", "左腕", "左腕捩", "左ひじ", "左手捩", "左手首", "左袖", \
"左親指1", "左親指2", "左人指1", "左人指2", "左人指3", "左中指1", "左中指2", \
"左中指3", "左薬指1", "左薬指2", "左薬指3", "左小指1", "左小指2", "左小指3", \
"左スカート前", "左スカート後", "左足", "左ひざ", "左足首", "右髪1", "右髪2", "右髪3", \
"右髪4", "右髪5", "右髪6", "右肩", "右腕", "右腕捩", "右ひじ", "右手捩", "右手首", \
"右袖", "右親指1", "右親指2", "右人指1", "右人指2", "右人指3", "右中指1", "右中指2", \
"右中指3", "右薬指1", "右薬指2", "右薬指3", "右小指1", "右小指2", "右小指3", \
"右スカート前", "右スカート後", "右足", "右ひざ", "右足首", "両目", "前髪1", "前髪2", \
"前髪3", "左目光", "右目光", "ネクタイ4", "左髪7", "右髪7", "左つま先", "右つま先", \
"ネクタイIK", "左髪IK", "右髪IK", "左足IK", "右足IK", "左つま先IK", "右つま先IK", \
"下半身先", "頭先", "左目先", "右目先", "腰飾り先", "左袖先", "左手先", "左親指先", \
"左人差指先", "左中指先", "左薬指先", "左小指先", "左スカート前先", "左スカート後先", "右袖先", \
"右手先", "右親指先", "右人差指先", "右中指先", "右薬指先", "右小指先", "右スカート前先", \
"右スカート後先", "センター先", "両目先", "ネクタイIK先", "左髪IK先", "右髪IK先", \
"左足IK先", "右足IK先", "左つま先IK先", "右つま先IK先", "前髪1先", "前髪2先", \
"前髪3先", "左目光先", "右目光先", "左腕捩先", "左手捩先", "右腕捩先", "右手捩先", \
"左腕捩1", "左腕捩2", "左腕捩3", "右腕捩1", "右腕捩2", "右腕捩3"}
ボーンは親は1つなのですが、ぶら下がる子は複数あります。またボーン種類はIDのままですと分かりづらいです。さらに踊らせる事を考えてボーンを回転させる時の移動先やIK(インバースキネマティクス)計算用の情報を含んだ形にしておきたいです。そこでPMDのボーンを作業用のボーン形式へ変換する為の関数Pmd2boneを作成します。
またボーンの可視化をする際に、親と子をLineで結ぶ為、親と子の3D座標のペアがあると便利です。これを求める関数をBone2Lineという名前で作成します。
Pmd2bone[pmdbone_] :=
(* PMDファイルのボーンを扱い易いように変換する。 *)
(* \
ボーン名 親 子 種類 IK影響下 座標 *)
Module[{i, s, result},
result = {};
For[i = 1, i <= Length[pmdbone], i++,
s = {};
s = Append[s, pmdbone[[i, 1]]];
s = Append[s,
If[pmdbone[[i, 2]] == 65535, Null, pmdbone[[i, 2]] + 1]
];
s = Append[s,
Flatten[Position[pmdbone[[All, 2]], i - 1]]
];
s = Append[s,
{"回転", "回転と移動", "IK", "不明", "IK影響下", "回転影響下", "IK接続先", "非表示",
"捻り", "回転運動"}
[[pmdbone[[i, 4]] + 1]]
];
s = Append[s,
If[pmdbone[[i, 5]] == 0, Null, pmdbone[[i, 5]] + 1]
];
(* ボーン名 親 子 種類 IK影響下 *)
s = Append[s, pmdbone[[i, 6]]]; (*ボーン位置 *)
s = Append[s, {0, 0, 0, 1}]; (*ボーン角度 絶対角*)
s = Append[s, {0, 0, 0}]; (*移動位置 初期姿勢相対 *)
s = Append[s, {0, 0, 0, 1}];(*ボーン角度 初期姿勢相対 *)
s = Append[s, pmdbone[[i, 6]]];(* ボーン初期姿勢 位置 *)
s = Append[s, {0, 0, 0}]; (*移動位置 IK用*)
s = Append[s, {0, 0, 0, 1}]; (*移動角 IK用*)
result = Append[result, s];
];
Return[result];
];
Bone2line[bone_] :=
Module[{i, s, result},
result = {};
For[i = 1, i < Length[bone], i++,
s = bone[[i, 4]];
If[s == "IK" || s == "非表示", Continue[]];
s = bone[[i, 2]];
If[s == Null, Continue[]];
s = {bone[[i, 6]], bone[[bone[[i, 2]], 6]]};
result = Append[result, s];
];
Return[result];
];
下記コマンドでPMDのボーンを変換します。
In[681]:= bone = Pmd2bone[f["Bones"]];
bone[[1]]
Out[682]= {"センター", Null, {2, 10, 87, 88, 89,
117}, "回転と移動", Null, {0., 8., 0.}, {0, 0, 0, 1}, {0, 0, 0}, {0, 0,
0, 1}, {0., 8., 0.}, {0, 0, 0}, {0, 0, 0, 1}}
Graphics3DとBone2lineを使ってボーンを可視化します。
In[681]:= Graphics3D[Line[Bone2line[bone]], ViewPoint -> Right];
ミクさんのボーンが表示できました!
でも、髪の毛やネクタイ、スカートにボーンが入っているので人間の骨と違ってイメージしづらいですね。なので、Pmdモデルを重ねて可視化してみます。
In[682]:= vertex = f["VertexVectors"];
vv[s_, i_] := f[s][[i + 1]];
poly = Append[
Append[{vertex[[# + 1]]},
VertexNormals -> f["NormalVectors"][[# + 1]]] ,
VertexTextureCoordinates -> vv["UVVectors", #]
] & /@ f["FaceIndices"];
pl[i_] := Polygon[i[[1]], i[[2]], i[[3]]];
dl = Prepend[
Flatten[#, 1] & /@
Partition[Riffle[vv["TextureList", #] & /@ f["MaterialIndices"],
pl /@ poly], 2], EdgeForm[]];
Graphics3D[{
Opacity[0.3],
dl,
Opacity[1.0],
Glow[Red],
Red,
Thickness[0.01],
Line[Bone2line[bone]]
}, ViewPoint -> Right, ViewAngle -> Automatic]
指先まで綺麗にボーンが入っている事が分かります。MMDモデルって細かくて丁寧で凄くアートですね!
n 他関連記事へのリンク
- MathematicaでMikuMikuDance 1 PMDファイルの読み込み