MikuMikuDanceの3次元CGモデルデータであるPMDファイルをMathematicaで可視化します。Mathematica8以降なら実行できると思います。RaspberryPiのMathematicaでも実行可能ですがとても重いです。
素材のキャラクターは初音ミクです。
「初音ミク」はクリプトン・フューチャー・メディア株式会社の著作物です。
© Crypton Future Media, INC. www.piapro.net
1.PMDファイルをMathematicaで読み込めるファイルを準備する。
PMDファイルはバイナリ形式なのでMathematicaで直接読み込むのは難しいです。なのでC言語で変換プログラムを作成し、Mathematicaで読み込めるテキスト形式に変換しました。
今回はこのテキストファイルをMathematicaにImportして3D CGモデルを可視化していきます。
テクスチャデータはbmpファイルなので、そのまま画像ファイルとしてMathematicaに読み込む事ができます。
下記のGoogle DriveのURLリンクからhatsune2.mとeyeM2.bmpをダウンロードしてMathematicaの作業ディレクトりに置いてください。
Google Drive
変換元の3D CGデータのPMDファイルはMikuMikuDanceのデフォルトモデルである、あにまさ式ミクさんを使用しました。
あにまさ式ミク
2. Importする。
まずMathematicaの作業フォルダを*Directory[]*で確認します。作業フォルダを変えたい時は、*SetDirectory["作業フォルダ"];*を実行します。
In[2]:= Directory[]
次に漢字コードを確認します。
In[33]:= $CharacterEncoding
Out[33]= "ShiftJIS"
ShiftJISで無かった場合は、ShiftJISに設定してください。(MMDはMS-Windowsのアプリケーションなので・・・。)
In[34]:= $CharacterEncoding = "ShiftJIS";
先ほどダウンロードしたhatsune2.mをImportします。
In[35]:= Pmd = Import["hatsune2.m"];
PMDのデータにアクセスする関数fを定義します。
In[36]:= f[s_] := Pmd[[Position[Pmd[[All, 1]], s][[1]][[1]], 2]];
PMDデータがImport出来たか確認します。
In[37]:= Pmd[[1]]
Out[37]= {"Header", {{"Magic", "Pmd"}, {"Version", 1.}, {"ModelName",
"初音ミク"}, {"Comment", "PolyMo用モデルデータ:初音ミク ver.2.3
(物理演算対応モデル)
モデリング :あにまさ氏
データ変換 :あにまさ氏
Copyright :CRYPTON FUTURE MEDIA, INC"}}}
3.とりあえず頂点データをプロットする。
3D CGモデルはポリゴンという単純な図形を組み合わせて構成されています。
PMDデータは三角形ポリゴンで構成されています。その三角形の頂点リストをListPointPlot3Dでプロットしてみます。
In[38]:= ListPointPlot3D[f["VertexVectors"]]
頂点リストのx,y,z座標を10点ほど見たい時はPart ( [[...]] )を使います。
In[39]:= f["VertexVectors"][[1;;10]]
Out[39]= {{-6.9072, 11.4279, -0.4254}, {-6.8439, 11.4035, -0.4289}, {-6.8689,
11.4285, -0.4475}, {-6.9102, 11.4319, -0.3639}, {-6.8759,
11.4352, -0.3439}, {-6.85, 11.4096, -0.358}, {-6.8992,
11.4757, -0.3624}, {-6.8979, 11.4742, -0.4303}, {-7.0481,
11.3895, -0.2397}, {-6.9938, 11.3629, -0.2471}}
4.ポリゴンで可視化する。
先ほどの頂点リスト3組で三角形ポリゴンを構成しGraphics3Dで可視化してみます。
どの3組を使うかはFaceIndicesに番号で格納されています。
In[38]:= f["FaceIndices"][[1]]
Out[38]= {647, 649, 648}
この3点で3角形ポリゴンの頂点を構成するには、このインデックス情報を頂点リストにMap( /@)すれば良いです。但しPMDデータ(C言語の配列)は0オリジンでMathematicaのリストは1オリジンなので#+1とします。
In[39]:= f["VertexVectors"][[# + 1]] & /@ f["FaceIndices"][[1]]
Out[39]= {{-1.3489, 0.2482, 0.3302}, {-1.2294, 0.1478,
0.0412}, {-1.2595, 0.1478, 0.2643}}
Graphics3DコマンドでPolygonを可視化します。
Graphics3D[
Polygon /@ (f["VertexVectors"][[# + 1]] & /@ f["FaceIndices"])
]
ポリゴンのエッジを消して表示してみます。
Graphics3D[
Prepend[
Polygon /@ (f["VertexVectors"][[# + 1]] & /@ f["FaceIndices"]),
EdgeForm[]
]
]
面法線で陰影付けされたポリポリした(角ばった)ミクさんが表示されました。
5.各頂点に法線ベクトルを追加する。
各頂点に法線ベクトルのリストを追加します。これにより、グーローシェーディングで滑らかにミクさんを表示する事ができます。
Graphics3D[
Prepend[
Polygon[#[[1]], #[[2]]] & /@
({
f["VertexVectors"][[# + 1]],
VertexNormals -> f["NormalVectors"][[# + 1]]
}
& /@ f["FaceIndices"]),
EdgeForm[]
]
]
6.各ポリゴンにテクスチャとマテリアルカラーを追加する。
各ポリゴンのプリミティブの前で色(マテリアルカラー)と模様(テクスチャ)を設定し、各ポリゴンの頂点にテクスチャ座標を設定します。
Graphics3D[
Prepend[
Flatten[#, 1] & /@
Partition[
Riffle[
f["TextureList"][[# + 1]] & /@ f["MaterialIndices"],
Polygon[#[[1]], #[[2]], #[[3]]] & /@
(
{
f["VertexVectors"][[# + 1]],
VertexNormals -> f["NormalVectors"][[# + 1]],
VertexTextureCoordinates -> f["UVVectors"][[# + 1]]
}
& /@ f["FaceIndices"]
)
]
, 2],
EdgeForm[]
]
]
7. 今後の予定?
クォータニオン演算、VMDファイルを使ってBoneによるポーズ付け、表情モ―フィングに続けて行きたいと思いますが、インバースキネマティクスと、クルっとターンした時の演算誤差の問題がまだ解決できていないので、その辺りを一緒に考えてくださる方がいらっしゃいそうなら順次、こちらで知っている事を公開していきたいと思います。それとC言語の話しになりますが、PMD,VMDファイルの変換についても書きたいと思います。
8. わからないこと
-
WolframCloudでファイル共有って出来るのかな。。。今回はGoogleDriveを使用しました。
-
【解決】Mathematicaで3Dプロットした時にマウスでViewPointなどを調整した時、そのViewPointの情報を得る方法があったと思いましたが、どうやったか忘れてしまいました。。。
【解決法】[入門Mathematica]
(https://books.google.cl/books?id=8twPGgpf2EAC "入門Matematica")P71より。
Options[#,{ViewPoint}]& で回転したグラフィックスのViewPointが得られます。
9. 関連リンク
- MathematicaでMikuMikuDance 2 表情モーフィング