Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
1
Help us understand the problem. What is going on with this article?
@I_HaL

MathematicaでMikuMikuDance 4

More than 3 years have passed since last update.

ダンスをさせる計算。

1. ボーンの可視化

3D CGモデルのダンスはボーン(骨)を回転したり移動させたりする計算が必要です。まず、前回のPMDモデルのボーンを可視化してみます。

Mathematica
In[100]:=f["Bones"][[1]]
Out[100]={"センター", 65535, 116, 1, 0, {0., 8., 0.}}

ボーンは、{ボーン名、親のボーンID、子のボーンID、ボーンの種類、IK影響化フラグ、ボーンの位置}のリストで構成されています。
PMDファイルの詳細については、MMDのモデルデータ(PMD)形式 めも (まとめ)を参照ください。

あにまさ式初音ミクの場合、ボーンは下記140個ほどあります。

Mathematica
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という名前で作成します。

bone.m
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のボーンを変換します。

Mathematica
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}}

Graphics3DBone2lineを使ってボーンを可視化します。

Mathematica
In[681]:= Graphics3D[Line[Bone2line[bone]], ViewPoint -> Right];

bone1.png

ミクさんのボーンが表示できました!
でも、髪の毛やネクタイ、スカートにボーンが入っているので人間の骨と違ってイメージしづらいですね。なので、Pmdモデルを重ねて可視化してみます。

Mathematica
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]

bone3.png

指先まで綺麗にボーンが入っている事が分かります。MMDモデルって細かくて丁寧で凄くアートですね!

n 他関連記事へのリンク

つづく

1
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
I_HaL

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
1
Help us understand the problem. What is going on with this article?