Wiki Menu

最近の更新 (Recent Changes)

2020-05-31
2015-11-08
2015-11-07
2015-11-05
2015-09-11

Últimos archivo liberados

MID2Motion (1.2.1)2015-11-07 15:31
MMDIKSolver (1.2)2015-06-13 19:45
MMDMotion (1.5.1)2015-11-05 17:38

Wikiガイド

MMDIKSolver (MMD Precalculated Inverse Kinematics Solver)

MikuMikuDance のIK (インバース・キネマティクス)を事前計算して、 モーションファイルに書き戻します。

何これ

MMD で腕とか足とかあるモデル(人型とは限らない)を使っていて、 腕先をまっすぐ直線に動かしたい(ストレートパンチとか)とか、 壁や棒の表面をなぞりたい(雑巾がけとか)と思ったことないでしょうか。

でも、モデルって根元から回転させて姿勢を決めるので、円弧は簡単にできるけど、 直線とか難しいですよね。そういう時は、人間ががんばるのではなくて、 当然コンピューターに腕の角度などを計算させるのです。 それが、IK (インバース・キネマティクス)です。

MMD にも、IK をする機能は当然ありますが、はじめからモデルに組み込んでないとつかえなかったり、 IK で出した回転角は全く記録されないとか、IK で動かしたボーンの子ボーンは付いてこないなど、 限定的です。自分でモデルに改造して、動画作るだけならまだしも、 モーションの配布を予定しているひとは、IK ボーン改造をユーザーに強要することになります。 やったことある人は分かると思いますが、この改造はかなり複雑でしんどいもので、 誰でも簡単にできるものじゃありません。 さらに、IK を使用しないモーションを同時に適用できなくなるデメリットがあります。 また MMD の人型モデルは、大抵どこかの企業が著作権を持つキャラなので、 IK ボーン改造をしたモデルを再配布することは、ほぼ無理です。

じゃあ、どうすればいいか。IK の計算は本来ただのモーションなので、 MMD の外で IK 問題を解いて、腕の角度とかをちゃんとモーションファイルに書き出せばいいのです。 モデルのボーン構造だけ分かれば、結構簡単にできます。

必要なもの

  1. Java Runtime Environment SE 1.6 以降 (Sun でも, Oracle でも, OpenJDKでも可)
  2. MikuMikuDance (以後 MMDとよばれる.)
  3. MMD用のモデル(PMD, PMX, PMX Editor が作るCSV形式)

ダウンロード

MMD IK Solver リリースリスト 最新 Version 1.2.

インストール

  1. Java Runtime Environment (JRE), Java Development Kit (JDK) があるなら、*.jar がコーヒーカップのアイコンで表示されてます。 なければ、JREかJDK をインストールしてください。
  2. 基本はそれだけです。*.jarはどこにおいてあってもかまいませんが、全部同じ場所において置いてください。

利用法

  • 簡単な利用ができる GUI が付いてます。MMDIKSolver-1.2.jar をダブルクリックしてみてください。 コマンドラインからの利用は、
        java -jar MMDIKSolver-1.2.jar
    
  • これはライブラリーなので、自分で java のプログラムを書いてリンクしてください。コンパイル例はこうです。
       javac -cp MMDIKSolver-1.2.jar;MMDMotion-1.3.jar;togagem-3.n3.jar (あなたの作ったjavaソース)
    
  • 一応Maven で管理しているので、Maven 2以降に対応している IDE (NetBeanseclipse) を使うと楽です。

仕様などの文章

アプリケーション・プログラム例

その1 ダミーボーン利用

beforeIK.gif
星型の頂点にターゲットになるダミーボーンと、その前に立たせた人モデル。
たとえば人差し指で、黒板をなぞるようなものをやるとします。MMDIKSolver_sample.zip

  1. 黒板とかステージとかに、ダミーボーンというやつが表面に張り付いていると思います。 もともとは平たい何かをつけるためのやつですが、 それをなぞりたい軌跡に合わせて、ダミーボーンの MMD モーション VMD (target.vmd) を作ります。 (右図,ちなみにステージモデルは コーヒーブレーク企画教室で、 nazo が良く jamバンドの舞台にしてるもの。)
  2. なぞらせるモデルの手を人差し指を伸ばして、黒板の前に立たせます。足の形とかまで作ってしまいます。 これのモーションファイル VMD (kanon.vmd) も作ります。(右図のモデルは jam バンドのキーボード「鼓カノン」ですが、普通の人物モデルなので、別に誰でもいいです。)
  3. ここからは簡易GUIでもできますが、ここではプログラム例で説明します。まずは、クラスファイルをこんな感じで作ります。
    1. public class SurfaceDrawingTest {
    2. private IKSolver iksolver;
    3. private Motion targetMotion;
    4. private Motion ikMotion;
    5. private Model targetModel;
    6. private Model ikModel;
    7. static public void main(String [] argv) {
    8. SurfaceDrawingTest test=null;
    9. System.out.println("Model Loading..");
    10. try{
    11. test=new SurfaceDrawingTest();
    12. }catch(FileNotFoundException e){
    13. System.err.println("ファイルが見つかりません: "+e);
    14. }catch(IOException e){
    15. System.err.println("IOエラー: "+e);
    16. }catch(MmdFormatException e){
    17. System.err.println("MMD ファイルとして異常: "+e);
    18. }
    19. if(test==null)
    20. System.exit(-1);
    21. System.out.println("All loaded!");
    22. test.setBones();
    23. test.solve();
    24. }
    25. }
  4. Model クラスにモデルを読み込み、 Motion クラスにモーションを読みます。 IK モデル, ターゲットのステージモデルともに用意します。
    1. public SurfaceDrawingTest()
    2. throws FileNotFoundException, IOException, MmdFormatException{
    3. FileInputStream fis=new FileInputStream("test/教室.pmd");
    4. targetModel=Model.fromPMD(fis);
    5. fis.close();
    6. System.out.println("Model: "+targetModel.getName()+" Done!");
    7. fis=new FileInputStream("test/鼓カノン.pmd");
    8. ikModel=Model.fromPMD(fis);
    9. fis.close();
    10. System.out.println("Model: "+ikModel.getName()+" Done!");
    11. fis=new FileInputStream("test/target.vmd");
    12. targetMotion=new Motion().fromVMD(fis);
    13. fis.close();
    14. iksolver=new IKSolver();
    15. fis=new FileInputStream("test/kanon.vmd");
    16. ikMotion=new Motion().fromVMD(fis);
    17. fis.close();
    18. }
  5. bones[0]に「左人指3先」を指定し、動かすボーンに[1] 左人指1・[2] 左手首・[3] 左ひじ・・・[6] 上半身を指定して、setBones します。
    1. private void setBones(){
    2. String [] nameOfBones=new String[] {
    3. "左人指3先","左人指1","左手首","左ひじ","左腕","左肩","上半身"};
    4. Bone [] bones=new Bone[nameOfBones.length];
    5. for(int i=0;i<nameOfBones.length;i++){
    6. bones[i]=ikModel.get(nameOfBones[i]);
    7. }
    8. iksolver.setBones(bones);
  6. 次にへんな方向に関節が回らないように、回転の制限をします。
    1. iksolver.setLimits(1,IKSolver.RLIMIT_NOX|IKSolver.RLIMIT_NOY);
    2. iksolver.setLimits(3,IKSolver.RLIMIT_NOX|IKSolver.RLIMIT_NOZ);
    3. iksolver.setLimits(5,IKSolver.RLIMIT_NOX|IKSolver.RLIMIT_NOY);
    4. }
  7. ターゲットに黒板ダミーボーンの座標を getPos で入手して、solve。
    1. public void solve(){
    2. Bone target=targetModel.get("右黒板DB3");
    3. Pose [] poses=targetMotion.get(target.getName());
    4. int frame;
    5. double distance;
    6. Motion results=new Motion(ikMotion.getModelName());
    7. for(Pose p:poses){
    8. frame=p.frame;
    9. // そのフレームの状態にする。
    10. ikModel.setPoses(ikMotion.getInterporate(frame));
    11. targetModel.setPoses(targetMotion.getInterporate(frame));
    12. // 変更フラグをリセットして変更したボーンだけを記録する.
    13. ikModel.resetChanged();
    14. distance=iksolver.solve(target.getPos());
    15. System.out.println("frame: "+frame+" distance: "+distance);
    16. results.putAll(ikModel.getChanged(), frame);
    17. }
  8. あとは、MMD モーションに書き戻してください。
    1. FileOutputStream fos=null;
    2. try {
    3. fos = new FileOutputStream("test/solution.vmd");
    4. results.toVMD(fos);
    5. fos.close();
    6. } catch (FileNotFoundException ex) {
    7. System.err.println("ファイルが見つかりません: "+ ex);
    8. } catch (IOException ex) {
    9. System.err.println("ファイルが書けません: "+ ex);
    10. }
    11. }
    after1.gif
    上半身まで動かして、ダミーボーンを指している。
  9. MMD で元のモデルに、新しい VMD (solution.vmd)を適用しましょう。なぞってるでしょ? ちょっとおかしい? それはダミーボンの移動間隔の 10 フレームの間で、 回転ボーンモーションの補間が回転の補間なので、腕が回転して弧を描くからですね。 目標の点を通過するのが目的ならこれでもいいですが、平面に図を書くのが目的ならこれではいけませんね。 解決法は、すべてのフレームでダミーボーンの位置を補間して、全てのフレームで IK を解けばいいです。 ただし、さっきより10倍時間がかかるし、solution.vmd も 10 倍大きくなるから注意してください。 (いまどきパソコンなら数 k byte が100倍くらいでも、たかが知れていますが) solve() メソッドのfor 文を次のように書き換えます。
    1. Motion results=new Motion(ikMotion.getModelName());
    2. - for(Pose p:poses){
    3. - frame=p.frame;
    4. + int end=targetMotion.getMaxFrame();
    5. + for(frame=0;frame<end;frame++){
    6. // そのフレームの状態にする。
    after2.gif
    途中もちゃんと補間してみると、表面をすべるように指を動かす。
  10. どうですか? 指が動きすぎ? そういうときは、動く setBones から、指をはずしたらいいですよ。 後は初期体勢 (kanon.vmd) を、どの点からも近いところまで持っていったほうが、無理な角度を取らなくなります。

著作権・ライセンス(使用許諾)

すべてMIT License です。これは、

  • 著作権表示を保持するかぎり、自由に転載・改変してもいい。 (商用利用も可だが、このライブラリーを使用していることを必ず明記。)
  • 著作者はこのプログラムによって発生する損益に完全に無責任。

ということだけ、覚えて置いてください。

togagem-3.n3.jar

Copyright(c) 2010 olyutorskii, nazo. http://mikutoga.osdn.jp/

TogaGem は、3D動画制作ツール、MikuMikuDance(MMD)で用いられる 各種データファイルを読み込むためのJavaライブラリです。 著作者は、olyutorskii です。MIT License で転載・改変が認められております。 nazoが、PMX読み込みとMMD Ver. 9 用の補間関係で書き換えてます。 Ver. 3.n 系列のサポートページは、 http://osdn.jp/users/naz_o/pf/TogaGem/wiki/ です。 MMD Motion は、このライブラリーに強く依存しております。

MMDMotion-1.3.jar

Copyright (c) 2015 nazo http://mmdmotion-java.osdn.jp/wiki/MMDMotion

MMD のモーションを計算で生成するために作った Java ライブラリです。(これです。) 著作者は、nazo (ときどき Naz.) です。MMDIKSolver は、 ほとんどこれのおかげでできています。 MIT License で転載・改変が認められております。

MMDIKSolver-1.2.jar

Copyright (c) 2015 nazo http://mmdmotion-java.osdn.jp/wiki/MMDIKSolver

MMD のIK問題を計算で解くために作ったJavaライブラリです。(これ) MMD Motion for Java の初目的のライブラリーです。 著作者は、nazo (ときどき Naz.) です。 MIT License で転載・改変が認められております。

注意事項

※ MMD開発者の樋口M氏とは、これらは無関係です。樋口M氏に問い合わせても 迷惑なだけなので、やめましょう。

MMD IK Solver 変更履歴

  • 1.2 (2015-06-13)
    • (MMDMotion の更新によるもの)
      • PMX対応,PMDモデルの腕関連の軸が正しくなった
    • GUIの整備
    • 無駄な計算を省いて、速くなった?
  • 1.1 (2015-04-04)
    • About Dialog の自動化
  • 1.0 (2015-03-26)
    • GUI が完成
  • 0.9 (2015-03-20)
    • sourceforge.jp SVN公開バージョン.
    • bones[0] の平行移動が実装された. (ギターの指板上の動きのため)
  • 0.2 (2015-02-22) 非公開
    • IK Solver から MMDMotion を分離.
  • 0.1 (2015-01-29) 非公開
    • IK Solver が動くようになったの日付
    • オイラー角では精度に問題があるので、VMD を直接読み書きするようにしたもの.

謝辞

MMD開発者の樋口M 氏:

言うまでもないですが、これがないとそもそもこんなライブラリー作る 意味がないです。楽しいプログラムです。

http://www.geocities.jp/higuchuu4/index.htm

私設研究所 Neo-Tech-Lab.com 上田智章 氏:

Javascript + HTML5 で MMD Player を作ってしまった、私よりよっぽど とんでもない人です。特に次のはいい資料です。

MikuMikuDanceのモデルデータ(PMD)構造について: 『IK(Inverse Kinematics) bone』(その5)

この中で、述べられていることに対してちょっと意見。

「でもこの処理、方程式解けば反復法使わなくてもいいような気もするが、」

一応その通りで、動かすボーンが n 個なら、n 次方程式になります。 一般に 4次方程式以上は一般解の公式は存在しません。 よって結局、方程式を反復計算によって解くことになりますので、作業が大体同じになります。

「もしかして、local minimum問題を抱えている?」

評価関数が距離ではなく内積なので、local minimum はない (local maximumはある)はずですが、IK 問題は答えが1点(0次元)じゃなくて n-1 次の自由度があるので、常にターゲットまでの距離が 0 になっても、 いつでも同じ答えにならないことが普通におきます。この IK Solver と MMD の IK の答えが合わないことはざらにありますが、もともと答えはたくさんある問題なので、 バグとかじゃないです。何を言っているかというと、手首をある点に完全に合わせて、 ひじと腕のボーンだけを動かせるだけ動かそうとすると、 ひじが自由に円弧を描きます。自分の体で試したらすぐ分かると思います。