LoginSignup
5
3

More than 5 years have passed since last update.

MathematicaでMikuMikuDance 3

Last updated at Posted at 2016-05-17

ステージの読み込み。

1 MMDの背景(ステージ)を入手する。

MMDの背景ステージは色々と公開されています。
今回は恋スルVOC@LOIDステージ 遊々さん作を利用します。リンク先からKoiVoca-Stage.zipをダウンロードして解凍します。

2 .xファイルをMathematicaで読み込めるように変換する。

MicroSoftの.xファイルをMathematicaの形式に合わせて変換します。
.xファイルには様々な内部形式がありますが、KoiVoca-Stage用に合わせて作成しましたので汎用性はありません。

x_conv.awk
BEGIN {
  material_no=0;
}
// {
  if(header==1) {
    if(sl==0) printf("    {\"Major\",%d},\n",$0);
    if(sl==1) printf("    {\"Minor\",%d},\n",$0);
    if(sl==2) printf("    {\"Flag\",%d}\n",$0);
    sl=sl+1;
  }
  if(meshvertexcolors==1) {
    if(sl==0) {
      str=$0+0;
      nvertexcolor=str;
      printf("  {\"VertexColors\",{ (* %d *)\n",str);
    }
    if(sl>=1&&sl<nvertexcolor) {
      split($0,vc,";");
      printf("    RGBColor[%f,%f,%f,%f], (* %d *)\n",vc[2],vc[3],vc[4],vc[5],vc[1]);
    }
    if(sl==nvertexcolor) {
      split($0,vc,";");
      printf("    RGBColor[%f,%f,%f,%f]  (* %d *)\n",vc[2],vc[3],vc[4],vc[5],vc[1]);
      print "  }}";
    }
    sl=sl+1;
  }

  if(meshtexturecoords==1) {
    if(sl==0) {
      str=$0+0;
      nuvvectors=str;
      printf("  {\"UVVectors\",{ (* %d *)\n",str);
    }
    if(sl>=1&&sl<nuvvectors) {
      split($0,uvv,";");
      printf("    {%f,%f}, (* %d *)\n",uvv[1],uvv[2],sl);
    }
    if(sl==nuvvectors) {
      split($0,uvv,";");
      printf("    {%f,%f}  (* %d *)\n",uvv[1],uvv[2],sl);
      print "  }},";
    }
    sl=sl+1;
  }

  if(material==1) {
    if(sl==0) {
      split($0,rgba,";");
      printf("    { (* %d *)\n",material_no);
      printf("     RGBColor[%f,%f,%f,%f],\n",rgba[1],rgba[2],rgba[3],rgba[4]);
    }
    if(sl==1) {
      pow=$0+0;
    }
    if(sl==2) {
      split($0,rgba,";");
      printf("     Specularity[RGBColor[%f,%f,%f],%f],\n",rgba[1],rgba[2],rgba[3],pow);
    } 
    if(sl==3) {
      split($0,rgba,";");
      printf("     Glow[RGBColor[%f,%f,%f]]",rgba[1],rgba[2],rgba[3],rgba[4]);
    }
    if(sl==4) {
      if($0 ~ /^   TextureFilename {/) {
        texture=1;
        printf(",\n");
      } else {
        texture=0;
        printf("\n");
      }
    }
    if(sl==5 && texture==1) {
      texture=0;
      str=substr($0,index($0,"\"")+1);
      str=substr(str,1,index(str,"\"")-1);
      printf("     Texture[Import[\"%s\"]]\n",str);
    }
    if(sl==5) {
      if(material_no==nMaterialList) {
        print "    }";
        print "  }},";
      } else {
        print "    },";
      }
    }
    sl=sl+1;
  }
  if(mesh_material==1) {
    if(sl==0) {
      printf("   (* %d *)\n",$0+0);
      nMaterialList=$0+0;
    }
    if(sl==1) {
      printf("   (* %d *)\n",$0+0);
    }
    if(sl>=2&&sl<nFaces+1) {
      printf("   %d, (* %d *)\n",$0+0,sl-1);
    }
    if(sl==nFaces+1) {
      printf("   %d  (* %d *)\n",$0+0,sl-1);
      print "  }},";
      mesh_material=0;
      mesh=0;
    }
    sl=sl+1;
  }
  if(mesh==1&&mesh_material==0&&material==0) {
    str=$0;
    if(sl==0) {
      printf("    (* %d *)\n",str);
      nVertices=str+0;
    }

    if(sl>=1&&sl<=nVertices) {
      split($0,cordinate,";");
      printf("    {%f,%f,%f},(* %d *)\n",cordinate[1],cordinate[2],cordinate[3],sl);
    }
    if(sl==nVertices) {
      split($0,cordinate,";");
      printf("    {%f,%f,%f} (* %d *)\n",cordinate[1],cordinate[2],cordinate[3],sl);
    }

    if(sl==nVertices+2) {
      nFaces=$0+0;
      print "  }},";
      print "  {\"FaceIndices\",{";
      printf("    (* %d *)\n",nFaces);
    }
    if(sl>=nVertices+3&&sl<nVertices+2+nFaces) {
      split($0,element,";");
      split(element[2],faces,",");
      if(element[1]==4) {
        printf("    {%d,%d,%d,%d},(* %d *)\n",faces[1],faces[2],faces[3],faces[4],sl-nVertices-2);
      }
      if(element[1]==3) {
        printf("    {%d,%d,%d},(* %d *)\n",faces[1],faces[2],faces[3],sl-nVertices-2);
      }
    }
    if(sl==nVertices+2+nFaces) {
      split($0,element,";");
      split(element[2],faces,",");
      if(element[1]==4) {
        printf("    {%d,%d,%d,%d} (* %d *)\n",faces[1],faces[2],faces[3],faces[4],sl-nVertices-2);
      }
      if(element[1]==3) {
        printf("    {%d,%d,%d} (* %d *)\n",faces[1],faces[2],faces[3],sl-nVertices-2);
      }
      print "  }},";
      mesh=0;
    }
    sl=sl+1;
  }
}
/\}/ {
  if(header==1) {
    header=0;
    print "  }},";
  }
}
/^Header{/ {
  print "{";
  print "  {\"Header\",{";
  header=1;
  sl=0;
}
/^Mesh {/ {
  print "  {\"VertexVectors\",{";
  mesh=1;
  sl=0;
}  
/^ MeshMaterialList {/ {
  print "  {\"MaterialIndices\",{";
  mesh_material=1;
  sl=0;
}
/^ MeshVertexColors {/ {
  meshvertexcolors=1;
  meshtexturecoords=0;
  sl=0;
}
/^ MeshTextureCoords {/ {
  meshtexturecoords=1;
  mesh_material=0;
  material=0;
  sl=0;
}
/^  Material {/ {
  material_no=material_no+1;
  if(material==0) {
    printf("  {\"TextureList\",{\n");
    material=1;
  }
  material=1;
  sl=0;
}
END {
  print "}";
}

下記コマンドで変換します。

BASH
>gawk -f x_conv.awk KoiVoca-Stage.x >KoiVoca-Stage.m

3 Mathematicaで読み込む。

Mathematicaを起動して、KoiVoca-Stage.mを読み込みます。

Mathematica
Directory[]
Stage = Import["KoiVoca-Stage.m"];
f[s_] := Stage[[Position[Stage[[All, 1]], s ][[1]][[1]], 2]];

次に頂点リストを3Dプロットしてみます。

Mathematica
vertex = {1, 1, 1} # & /@ f["VertexVectors"];
ListPointPlot3D[vertex, ViewPoint -> Above]

Koivoca2.png

つぎに、ポリゴンを構成してグラフィック表示してみます。

Mathematica
poly = vertex[[# + 1]] & /@ 
     Piecewise[{
       {{#[[1]], #[[2]], #[[3]]}, Length[#] == 3},
       {{#[[1]], #[[2]], #[[3]], #[[4]]}, Length[#] == 4}
       }] & /@ f["FaceIndices"];
Graphics3D[{Prepend[Polygon /@ poly, EdgeForm[]]}, ViewPoint ->Above]

Koivoca3.png

ナニカヘン・・・。ト音記号が逆ですね。実はMathematicaの3Dグラフィックは右手座標系なのですが、DirectXは左手座標系なのです。なので座標系の変換をしなければなりません。
下記コードで頂点座標のZ座標を-1倍します。

Mathematica
vertex = {1, 1, -1} # & /@ f["VertexVectors"];
ListPointPlot3D[vertex, ViewPoint -> Above]

Koivoca1.png

次に下記コードでポリゴンの頂点の並びを1->2->3から1->3->2と並べ替えます。

Mathematica
poly = vertex[[# + 1]] & /@ 
     Piecewise[{
       {{#[[1]], #[[3]], #[[2]]}, Length[#] == 3},
       {{#[[1]], #[[4]], #[[3]], #[[2]]}, Length[#] == 4}
       }] & /@ f["FaceIndices"];
Graphics3D[{Opacity[1.0], Prepend[Polygon /@ poly, EdgeForm[]]}, 
 ViewPoint -> Above]

Koivoca4.png

最後にテクスチャとマテリアルカラーを指定して色を塗ります。

Mathematica
vv[s_, i_] := f[s][[i + 1]];
poly =
  vertex[[# + 1]] & /@
     Piecewise[{
       {{#[[1]], #[[3]], #[[2]]}, Length[#] == 3},
       {{#[[1]], #[[4]], #[[3]], #[[2]]}, Length[#] == 4}
       }] & /@ f["FaceIndices"];
uvv =
  vv["UVVectors", #] & /@
     Piecewise[{
       {{#[[1]], #[[3]], #[[2]]}, Length[#] == 3},
       {{#[[1]], #[[4]], #[[3]], #[[2]]}, Length[#] == 4}
       }] & /@ f["FaceIndices"];
p = Partition[Riffle[poly, uvv], 2];
pl[i_] := Polygon[i[[1]], VertexTextureCoordinates -> i[[2]], 
  VertexNormals -> Automatic]

dl = Prepend[
   Flatten[#, 1] & /@ 
    Partition[Riffle[vv["TextureList", #] & /@ f["MaterialIndices"],
      pl /@ p], 2], EdgeForm[]];
Graphics3D[dl, ViewPoint -> Above]

Koivoca5.png

かわいらしいステージが表示されました。

4 他関連記事へのリンク

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3