three.jsで遊んでみる(4)

 プログラム,
 公開日:2012年9月20日 / 更新日:2013年10月24日

前回で書いたように、
MMDなデータをBlender経由でthree.jsで扱えるjsonへ変換するのは
どうもうまく行かない感じです。

そこで自前で変換ツールを作ることにしました。
Blenderのimporterやexporterは参考になるので、
pythonで作ってみることにしました。
ちなみにpython使うのは初めてだったりします(^_^;)

BoneによるSkeletalなアニメーションは、
こんな感じにthree.jsで動いているので
どうやってるのかを調べることから始めました。

データファイルはthree.jsで扱いやすいようなjsonになっており、
テキストエディタなどで中身を見ることができます。
内容は以下の様な感じ。

1)マテリアルの配列
2)頂点の配列(x,y,z,x,y,z,…)
3)法線の配列(x,y,z,x,y,z,…)
4)UVの配列(u,v,u,v,…)
5)面データの配列
6)Bone情報の配列
7)頂点に対するBoneインデクスの配列
8)頂点に対するBone重みの配列
9)アニメーション情報(Bone毎のキーフレームの配列)

面データは、まずフラグ値があり、
それによって続く値が決まるようになっています。
詳しくは”JSONLoader.js”を参照してみてください。
7)と8)は常に2個セットで扱われるようになっています。
つまり,一つの頂点に対するBoneは2個までとなっています。
例えば、ある頂点に影響するBoneが#2,#7だったとすると、
インデクス=[2,7] 重み=[0.25,0.75]とかになります。
重みの合計は基本的に1.0になります。
頂点に影響するBoneが一つだけの場合は、
インデクス=[3,0] 重み=[1,0]とかになり、
2つ目の値はゼロになるようになっています。
これだと重みゼロで積和することになるので
無駄な計算となるはずですが、
シェーダーで扱いやすいように、この構成なのだと思います。
アニメのキーは位置、回転(クオータニオン)、拡縮の3要素から成っており、
変化のある要素のみが記述されるようになっています。

ということで、どういうjsonを作れば良いか大体わかったので、
MMDなデータファイルから変換する作業へ進みます。

MMDなモデルファイルであるPMDの仕様は公式には公開されていないようですが
ググってみると解析された結果が見つかります。
ところでモデルファイルにはもう一つPMXというのがあります。
PmxEditorに同梱されているファイルに詳しい仕様が記述されています。
さいわいPMDはPMXへ変換することが出来ますので、
変換ツールではPMXファイルを扱うことにしました。
モーションファイルであるVMDの仕様も非公開のようですが、
解析情報は検索したら見つかりました。

さて、
そんなこんなで紆余曲折を経て、
ある一定の成果を得ることが出来ました。
変換時の留意点をまとめてみます。

  • PMXにおけるBoneの位置はルートからの積算になっているので、
    three.jsで扱うには親からの相対値へ変換する必要がある。
  • 左手座標系から右手系への変換が必要。
    位置や法線はZ値の符号を反転させるだけ。
    回転(クオータニオン)の場合はXとYを反転させるとうまくいく感じ。
    あるいはZとWを反転でもいいっぽい。
    面の頂点並びはA->B->CからC->B->Aに反転。
  • PMXにおける Bone Deformation は BDEF1(ボーン1つ)、BDEF2(ボーン2つ)、BDEF4(ボーン4つ)、SDEF(ボーン2つでspherical)の4種類がサポートされているが、three.jsで扱えるように全てBDEF2相当に変換する。ただ、PMDにはBDEF1かBDEF2しかないはず。
  • VMDのBoneキーフレームのposには、
    相対化したPMXでのBoneの位置を加算する必要がある。
  • three.jsにおけるアニメのキーは最低2つ必要で、
    なおかつ最初と最後にはpos(位置),rot(回転),scl(拡縮)が揃って無いとダメ。
  • Boneキーの補間はMMDでは4つの制御点による3次ベジェですが、現状のthree.jsではリニア補間しかない。ただ、4つのキーを使ったCutmull-Romな補間をサポートしている。

あと、
「頭」と「首」のBoneはそれぞれ個別に回転できるわけですが、
実際に再生させると「傾き過ぎる」ような感じになるので、
「頭」の回転量は強制的にゼロにして変換するようにしました。
なぜこういう現象になるのかよくわからないのですが、
とりあえず暫定処置としておきます。

ということで、
表情モーフ無し、IK無し、物理演算無し、toonシェード無し、エッジ処理無し、
Boneによるskeletalなアニメーションだけな再現なので
特に足のIKが無くて変なことになってますが、
とりあえずthree.jsで再現したミックミクな感じのモーションはこれです。
諸般の事情でちょっとローディングに時間がかかりますが、
しばらく待ってみてください。なお、ChromeなどのWebGL対応のブラウザで見てください。PCパワーもそれなりに必要となるかもしれません。

あと、何か変な線が見えてますが、
これはスポットライトの範囲を可視化したものです。

一応、影も出せるようになったのですが、
現状のthree.jsではマテリアル単位で影の濃さを調整できないので、
床影のみにしています。
ライト毎にしか影の濃さを調整できないので、
床影が認識できるような濃さにした上でミクさんにセルフ影を導入すると、
なんか「やり過ぎな影」になっちゃうんです(^_^;)

次は表情モーフあたりをやってみたいかな。

mytest7


※9月28日追記。
「傾き過ぎる」件ですが、変換ツールがバグっていたようです(^_^;)
隣接するキーの内容に同じのがあったら、
端折るようにして最適化したつもりがうまくいってなかったようです。
VMDのキーを素直に出力するようにしました。

タグ: ,

コメント投稿