MathematicaでMikuMikuDance 1


MikuMikuDanceの３次元CGモデルデータであるPMDファイルをMathematicaで可視化します。Mathematica8以降なら実行できると思います。RaspberryPiのMathematicaでも実行可能ですがとても重いです。
![Bone7.png](https://qiita-image-store.s3.amazonaws.com/0/119510/5242234a-2ffb-4e65-65d9-49802f670d35.png)
 素材のキャラクターは初音ミクです。
「初音ミク」はクリプトン・フューチャー・メディア株式会社の著作物です。
© 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](https://drive.google.com/folderview?id=0B7KXYwj_KirSLUFEM09hTXFXbHc&usp=sharing  "Google Drive")
 
  変換元の3D CGデータのPMDファイルはMikuMikuDanceのデフォルトモデルである、あにまさ式ミクさんを使用しました。
[あにまさ式ミク](http://dic.nicovideo.jp/a/%E3%81%82%E3%81%AB%E3%81%BE%E3%81%95%E5%BC%8F%E3%83%9F%E3%82%AF   "あにまさ式ミク")

 
# 2. Importする。
 
  まずMathematicaの作業フォルダを*Directory[]*で確認します。作業フォルダを変えたい時は、*SetDirectory["作業フォルダ"];*を実行します。
  
 ```Mathematica
In[2]:= Directory[]
```

  次に漢字コードを確認します。
  
 ```Mathematica
In[33]:= $CharacterEncoding
Out[33]= "ShiftJIS"
```
  ShiftJISで無かった場合は、ShiftJISに設定してください。(MMDはMS-Windowsのアプリケーションなので・・・。)
  
 ```Mathematica
In[34]:= $CharacterEncoding = "ShiftJIS";
```

  先ほどダウンロードしたhatsune2.mを*Import*します。  
  
```Mathematica
In[35]:= Pmd = Import["hatsune2.m"];
```
  PMDのデータにアクセスする関数*f*を定義します。
  
```Mathematica
In[36]:=  f[s_] := Pmd[[Position[Pmd[[All, 1]], s][[1]][[1]], 2]];
```
  
  PMDデータが*Import*出来たか確認します。
  
```Mathematica
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*でプロットしてみます。
 
```Mathematica
In[38]:= ListPointPlot3D[f["VertexVectors"]]
```
![名称未定義-1.png](https://qiita-image-store.s3.amazonaws.com/0/119510/6d7b694e-86c5-eaab-ae60-dc8f705ef63c.png)

  頂点リストのx,y,z座標を10点ほど見たい時は*Part* ( [[...]] )を使います。

```Mathematica
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に番号で格納されています。

```Mathematica
In[38]:= f["FaceIndices"][[1]]
Out[38]= {647, 649, 648}
```
  この3点で3角形ポリゴンの頂点を構成するには、このインデックス情報を頂点リストに*Map*( /@)すれば良いです。但しPMDデータ(C言語の配列)は0オリジンでMathematicaのリストは1オリジンなので#+1とします。

```Mathematica
 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を可視化します。

```Mathematica
Graphics3D[
 Polygon /@ (f["VertexVectors"][[# + 1]] & /@ f["FaceIndices"])
 ]
```

![名称未定義-2.png](https://qiita-image-store.s3.amazonaws.com/0/119510/de7e0245-4c4f-239d-7190-1fe170a2f06a.png)

  ポリゴンのエッジを消して表示してみます。

```Mathematica
Graphics3D[
 Prepend[
  Polygon /@ (f["VertexVectors"][[# + 1]] & /@ f["FaceIndices"]),
  EdgeForm[]
  ]
 ]
```
![名称未定義-3.png](https://qiita-image-store.s3.amazonaws.com/0/119510/7215ec18-8bfa-aebd-2ead-bd726d3183a5.png)

  面法線で陰影付けされたポリポリした(角ばった)ミクさんが表示されました。
 

# 5.各頂点に法線ベクトルを追加する。

  各頂点に法線ベクトルのリストを追加します。これにより、グーローシェーディングで滑らかにミクさんを表示する事ができます。

```Mathematica
Graphics3D[
 Prepend[
  Polygon[#[[1]], #[[2]]] & /@ 
   ({
       f["VertexVectors"][[# + 1]],
       VertexNormals -> f["NormalVectors"][[# + 1]]
       }
       & /@ f["FaceIndices"]),
  EdgeForm[]
  ]
 ]
```

![名称未定義-4.png](https://qiita-image-store.s3.amazonaws.com/0/119510/4a0a830f-979a-23ae-dc2b-063e1751e90c.png)

# 6.各ポリゴンにテクスチャとマテリアルカラーを追加する。

  各ポリゴンのプリミティブの前で色(マテリアルカラー)と模様(テクスチャ)を設定し、各ポリゴンの頂点にテクスチャ座標を設定します。
 
```Mathematica
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[]
  ]
 ]
```
  ![名称未定義-5.png](https://qiita-image-store.s3.amazonaws.com/0/119510/d834490d-093b-4da2-338e-5a8d654e2fd4.png)
  いわゆるペンギンポーズをしたミクさんが表示されました。
  
# 7. 今後の予定？

  クォータニオン演算、VMDファイルを使ってBoneによるポーズ付け、表情モ―フィングに続けて行きたいと思いますが、インバースキネマティクスと、クルっとターンした時の演算誤差の問題がまだ解決できていないので、その辺りを一緒に考えてくださる方がいらっしゃいそうなら順次、こちらで知っている事を公開していきたいと思います。それとC言語の話しになりますが、PMD,VMDファイルの変換についても書きたいと思います。
  
# 8. わからないこと

1.  WolframCloudでファイル共有って出来るのかな。。。今回はGoogleDriveを使用しました。

2.  【解決】Mathematicaで3Dプロットした時にマウスでViewPointなどを調整した時、そのViewPointの情報を得る方法があったと思いましたが、どうやったか忘れてしまいました。。。
【解決法】[入門Mathematica]
(https://books.google.cl/books?id=8twPGgpf2EAC "入門Matematica")P71より。
> *Options[#,{ViewPoint}]&* で回転したグラフィックスのViewPointが得られます。
>

# 9. 関連リンク
* [MathematicaでMikuMikuDance 2](http://qiita.com/I_HaL/items/077db322a6e036b2a109) 表情モーフィング