MMD

MMM(MikuMikuMoving)でPerception Neuronを使う

※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※

MikuMikuMoving v1.2.8.0で公式にPerception Neuron対応されましたので、

現在こちらのプラグインを使用する必要はありません

※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※


Perception Neuronとは



中国Noitom社によって開発された低価格モーションキャプチャシステム。公式サイトはこちら。最大32個のNeuronと呼ばれる9軸センサモジュール(3軸ジャイロ+3軸加速度+3軸磁気)を用いて指先を含めた全身のキャプチャが可能。Axis Neuronという専用ソフトからTCP/UDPによるBVHフォーマットのモーションデータを送信することができます。システム一式(Neuron32個付属)で$1,499。Axis NeuronはこちらからFree版をダウンロードすることができます。Perception Neuronを持っていなくてもサンプルのモーションデータを再生させることができます。


MMM(MikuMikuMoving)とは

001.PNG

Mogg氏により開発されているMikuMikuDance(MMD)互換ソフト。公式サイトはこちら。MMD用のモデルやモーションデータが使用可能。プラグイン機能を持っており、ユーザーが自由に機能を追加することができます。

今回、Axis Neuronから送信されたモーションデータをMMMで受信し、MMDモデルにモーションを反映させるプラグインを作成しました。実装した内容について書きたいと思います。


MMMのプラグイン開発

MMMのプラグインの開発に必要なソフトウェアと環境は以下になります。


開発に必要なソフトウェア

・Microsoft Visual C# 2010 Express もしくはこれに準じるソフトウェア

必要環境

・Windows XP以降

・.NET Framework 2.0

・DirectX 9.0c Runtime 2010 Feb以降 (SDKは必要ありません)


※MMM公式サイト 17.プラグインより引用

プラグインには、ボタンを押したときに実行されるコマンドプラグインと、毎フレーム実行される常駐型プラグインの2種類のタイプがあります。これらのプラグインでは、モデル、アクセサリ、エフェクト、カメラやライトに対して、キーフレーム操作やモーション操作等が可能です。プラグイン開発については詳しくはMMM公式サイトの17.プラグインをご確認ください。今回は常駐型プラグインで開発しました。


モーションデータの受信


NeuronDataReaderライブラリ

Axis NeuronはTCP/UDPによるBVHフォーマットのモーションデータを送信することができます。NeuronDataReaderというC/C++用ライブラリが提供されており、これを利用することでBVHデータの受信を簡単に行うことができます。

キャプチャ.PNG

※画像は「Neuron Data Reader Runtime API Documentation」1.1. NeuronDataReader frameworkより引用


BVHデータフォーマット

毎フレームのデータにはBVHヘッダとBVHモーションデータが含まれます。BVHヘッダには、位置情報の有り無しやリファレンスデータの有り無しなどの基本的な情報が含まれます。

// Header format of BVH data

typedef struct _BvhDataHeader
{
uint16_t Token1; // Package start token: 0xDDFF
DATA_VER DataVersion; // Version of community data format. e.g.: 1.0.0.2
uint16_t DataCount; // Values count
uint8_t WithDisp; // With/out displacement
uint8_t WithReference; // With/out reference bone data at first
uint32_t AvatarIndex; // Avatar index
uint8_t AvatarName[32]; // Avatar name
uint32_t FrameIndex; // Frame data index
uint32_t Reserved; // Reserved, only enable this package has 64bytes length
uint32_t Reserved1; // Reserved, only enable this package has 64bytes length
uint32_t Reserved2; // Reserved, only enable this package has 64bytes length
uint16_t Token2; // Package end token: 0xEEFF
}BvhDataHeader;

※コードは「Neuron Data Reader Runtime API Documentation」2.1.4. Header of BVH data streamより引用

BVHモーションデータは連続したfloat値になっています。リファレンスデータ有りの場合、最初の6つのfloat値はリファレンスボーンの位置と回転になります。位置情報有りの場合、すべてのボーンが6つのfloat値(位置xyzの3つと回転xyzの3つ)を持ちます。位置情報無しの場合、ルートボーンのみ6つのfloat値を持ち(位置xyzの3つと回転xyzの3つ)、それ以外のボーンは3つのfloat値を持ちます(回転xyzの3つ)。

009.PNG

※画像は「PERCEPTION NEURON UNITY HANDBOOK」APPENDIX D: BINARY DATA SEQUENCEより引用

回転の順序はYXZです(Axis Neuron側の設定で変更可能)。

また、ボーンの階層構造は「Neuron Data Reader Runtime API Documentation」Appendix B: BVH header templateに載っています。


C#でNeuronDataReaderを利用する

公式サイトからダウンロードできるNeuronDataReader SDKにはdemo_csというC#で開発されたサンプルプロジェクトがついてきます。このサンプルプロジェクトにはNeuronDataReaderWraperというC#からNeuronDataReaderを使うためのラッパクラスが含まれています。C#でNeuronDataReaderを利用する場合はこちらを使わせてもらいましょう。

また、公式サイトからダウンロードできるUnity IntegrationというUnity向けのパッケージに含まれているNeuronActor.csやNeuronTransformsInstance.cs、NeuronAnimatorInstance.csに、受信したデータから各ボーンの位置と回転を取り出したり、取り出した位置と回転を受信側のモデルのボーンに適用する処理が書かれています。こちらも参考になるかと思います(位置と回転はUnityの座標系に合わせて変換されているので注意してください)。


それぞれの座標系


Perception Neuronで使用される座標系

xの正方向が右、yの正方向が上、zの正方向が手前の右手系です。

キャプチャ.PNG

※画像は「Neuron Data Reader Runtime API Documentation」Appendix D: Skelton Graphより引用


MMMで使用される座標系

xの正方向が右、yの正方向が上、zの正方向が奥の左手系です。

MMMの画面上の座標軸はzが手前に伸びてますがマイナス方向なので注意です。

005.PNG


座標系の変換

以上より、位置に関してはzの値をマイナスに、回転に関してはxとyの回転を逆に回転させることで、Perception Neuron側の値をMMM側の座標系に合わせる事ができます。


Perception NeuronとMMMのボーンの対応

Perception NeuronとMMMのボーンは以下のように対応させました。MMDモデルのボーン構造はモデルによって違いがあったりしますが、標準モデルをベースに対応付けています。Perception Neuronからは各ボーンの位置と回転が得られますが、Hipsの位置をセンターの位置に使用している以外は、位置は使わず回転のみ使っています。上半身については、Perception Neuron側のSpine、Spine1、Spine2、Spine3の四つのボーンの回転を合計した値をMMM側の上半身ボーンに使っています。上半身2を持っているモデルの場合は、Spineを上半身、Spine1、Spine2、Spine3の合計を上半身2に使う等すると良いかと思います。また、RightHandIndex1とRightInHandIndexの回転を合計した値を右人指1ボーンに使っています。他の指も同様です。(このあたりはUnity IntegrationのNeuronAnimatorInstance.csのやり方を参考にしました)

Perception Neuronのボーン
MMMのボーン

Hips(位置)
センター(位置)

Hips
下半身

RightUpLeg
右足

RightLeg
右ひざ

RightFoot
右足首

LeftUpLeg
左足

LeftLeg
左ひざ

LeftFoot
左足首

Spine+Spine1+Spine2+Spine3
上半身

Neck

Head

RightShoulder
右肩

RightArm
右腕

RightForeArm
右ひじ

RightHand
右手首

RightHandThumb1
右親指1

RightHandThumb2+RightHandThumb3
右親指2

RightHandIndex1+RightInHandIndex
右人指1

RightHandIndex2
右人指2

RightHandIndex3
右人指3

RightHandMiddle1+RightInHandMiddle
右中指1

RightHandMiddle2
右中指2

RightHandMiddle3
右中指3

RightHandRing1+RightInHandRing
右薬指1

RightHandRing2
右薬指2

RightHandRing3
右薬指3

RightHandPinky1+RightInHandPinky
右小指1

RightHandPinky2
右小指2

RightHandPinky3
右小指3

LeftShoulder
左肩

LeftArm
左腕

LeftForeArm
左ひじ

LeftHand
左手首

LeftHandThumb1
左親指1

LeftHandThumb2+LeftHandThumb3
左親指2

LeftHandIndex1+LeftInHandIndex
左人指1

LeftHandIndex2
左人指2

LeftHandIndex3
左人指3

LeftHandMiddle1+LeftInHandMiddle
左中指1

LeftHandMiddle2
左中指2

LeftHandMiddle3
左中指3

LeftHandRing1+LeftInHandRing
左薬指1

LeftHandRing2
左薬指2

LeftHandRing3
左薬指3

LeftHandPinky1+LeftInHandPinky
左小指1

LeftHandPinky2
左小指2

LeftHandPinky3
左小指3


Perception NeuronのモーションをMMMに適用させる

Perceoption NeuronのモーションをMMMに適用させるために、プラグイン内で以下のような処理を行っています。


デフォルトポーズの違い

Perception NeuronのデフォルトポーズはTスタンスですが、MMMのデフォルトポーズはAスタンスです。MMM側でTスタンス用のモーションデータを使えるように、モデルのポーズをAスタンスからTスタンスに変換します。肩、腕のボーンが地面と平行になるようにz軸回転させます。

はじめに、肩ボーンの、グローバル座標系のx軸に対する角度を求めます。次に、腕ボーンの、肩ボーンに対する角度を求めます。肩と腕それぞれ求めた角度分戻すとTスタンスになります。

006.PNG

007.PNG

また、親指が、Perception Neuron側では閉じているのに対し、MMM側では開いています。

032.PNG

Tスタンスに変換後、グローバル座標系のx軸に沿うように親指1ボーンをY軸回転させて、親指を閉じさせます。

033.PNG


ボーンの回転軸の違い

Axis Neuronから送信されるモーションデータの回転角はボーンのローカル座標系における回転角ですが、MMM側で回転を指定する際にはデフォルトポーズ時におけるMMMのグローバル座標系に一致したローカル座標系で指定することになります。

010.PNG

そのため、肩、腕、ひじ、手首、指についてはAxis Neuron側の回転をかける際に、Axis Neuron側とMMM側で回転軸が合うようにボーンを回転させておく必要があります。Tスタンスへの変換と合わせると、行列の計算は以下のようになります。

Tスタンスへの回転行列×「回転軸を合わせるための回転行列」の逆行列×肩、腕、ひじ、手首、指ボーンの回転行列×回転軸を合わせるための回転行列

親指1ボーンの場合は、上記計算に親指を閉じさせる回転を加えます。

親指を閉じる回転×Tスタンスへの回転行列×「回転軸を合わせるための回転行列」の逆行列×親指1ボーンの回転行列×回転軸を合わせるための回転行列


Perception NeuronのSpineボーンとMMMの上半身ボーンの違い

Perception NeuronのSpineボーンはHipsボーンの子ですが、MMMの上半身ボーンは下半身ボーンと親子関係にありません。MMM側で、Hipsボーンの回転を上半身ボーンにも適用させる必要があります。行列の計算は以下のようになります。

Hipsボーンの回転行列×上半身ボーンの回転行列


センター位置のリセット

直立時にセンターボーンのY座標が0になるように、直立時のPerception NeuronのHipsボーンのY座標の値をオフセット値として使っています。


プラグインの使い方

今回作成したプラグイン(NeuronReceiver.dll)をこちらで配布しています。Perception Neuronの公式サイトからAxis NeuronとNeuronDataReader SDKをダウンロードしてください。MMMはこちらからダウンロードできます。(上で説明した内容をプラグインの内部で処理しています。このプラグインを使うにあたって、モデルのTスタンスへの修正などは必要ありません)


Axis Neuronの設定

File->Settings->Broadcastingを選びます。TCPを選択し、BVHにチェックをいれてください。Portは7001にしておきます。

013.PNG

File->Settings->Output Formatを選びます。Frequency reducingは1、Block typeはBinary、RotationはYXZを選んでください。

014.PNG

動作確認用に適当なサンプルモーションを再生しておきます。

015.PNG


プラグインの導入

NeuronDataReader SDKのWindows\lib\x64\NeuronDataReader.dllをMMMの実行ファイルと同じフォルダなどパスの通っている場所にコピーしてください(32bit版のMMMを使用する場合はWindows\lib\x86\NeuronDataReader.dllを使用してください)。

011.PNG

Pulginsフォルダにプラグイン以外のdllを入れるとMMM起動時に以下のエラーになってしまうので注意してください。(対処法をサメジ部長 (@samezi)さんに教えていただきました。ありがとうございました)

キャプチャ.PNG

NeuronReceiver.dllをMMMのPluginsフォルダにコピーしてください。

011_1.PNG

MMMを起動してください。起動時に以下のエラーが出ることがあるようです。その場合は、こちらの対処方法を参考にしてください。

c0e7f37306d61dc29d020f218057df34.png

モデルを読み込みます。

016.PNG

足のIKをすべて切ります。

017.PNG

NeuronReceiverプラグインを有効化します。

018.PNG

NeuronReceiverプラグインのConnectボタンを押します。

019.PNG

Axis Neuronへの接続が成功すると以下のダイアログが表示されます。

020.PNG

接続に失敗すると以下のダイアログが表示されます。Axis Neuronが起動しているか確認してください。起動している場合は、Broadcastingの設定内容を確認してください。

021.PNG

接続直後はモデルが宙に浮いています。

022.PNG

直立時に、NeuronReceiverプラグインのセンター位置リセットボタンを押してください。モデルが接地します。

023.PNG

MMDモデルの体型によっては、移動時に足が滑ったり、しゃがんだときに地面に潜り込むことがあります。NeuronReceiverプラグインのY軸スケール係数とXZ平面スケール係数を調整することで、ある程度改善させることができます。

024.PNG

物理演算を有効化します。

026.PNG

こんな感じで動かすことができます。



モーションの記録

はじめに、0フレーム目に足のIKを切った状態をキーフレーム登録しておきます。NeuronReceiverプラグインのRecordボタンを押すと、モーションの記録を開始します。

025.PNG

Stopボタンを押すと、モーションの記録を停止します。

027.PNG

タイムラインにキーフレームが登録されます。キーフレームは全フレームに登録されます。

030.PNG

記録したモーションをMMM上で再生する場合は、NeuronReceiverのプラグインを無効化してから再生してください。また、PCの性能にもよりますが、大量にキーフレームを登録しているためか500~600フレームを超えたあたりからフレームレートが低下し、キーフレーム登録が飛び飛びになってしまうことが確認されています。


記録したモーションをMMDで使う

VMDフォーマットで保存します。

028.PNG

保存したVMDファイルを、MMDで読み込むことができます。

029.PNG


記録したモーションをUnityで使う

Noraさん(@Stereoarts)のMMD4Mechanimを使うことで、UnityでMMDモデルやMMDで作成したモーションを使うことができます。MMD4MechanimはStereoarts Homepageからダウンロードすることができます。詳しい使い方はこちらに載っています。

031.PNG


課題

腰の位置を基準として各ボーンに回転の値をセットしているだけなので、Perception Neuron側とMMM側とでモデルの体型が異なる場合、足先の位置が一致しません。そのため屈伸や前屈のような本来足先が動かない動作で、足先が動いてしまうことがあります。

また、Axis NeuronとUnity Integrationのサンプルとで比較すると、Unityの方では足先が動いてしまっているので、体型の違い以外にも何か原因があるのかもしれません。(Axis Neuronでは足の接地判定を行って足を固定している?)