ステージの読み込み。
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]
つぎに、ポリゴンを構成してグラフィック表示してみます。
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]
ナニカヘン・・・。ト音記号が逆ですね。実はMathematicaの3Dグラフィックは右手座標系なのですが、DirectXは左手座標系なのです。なので座標系の変換をしなければなりません。
下記コードで頂点座標のZ座標を-1倍します。
Mathematica
vertex = {1, 1, -1} # & /@ f["VertexVectors"];
ListPointPlot3D[vertex, ViewPoint -> Above]
次に下記コードでポリゴンの頂点の並びを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]
最後にテクスチャとマテリアルカラーを指定して色を塗ります。
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]
かわいらしいステージが表示されました。
4 他関連記事へのリンク
- MathematicaでMikuMikuDance 1 PMDファイルの読み込み
- MathematicaでMikuMikuDance 4 ダンスの計算