ホームへ戻る

 3d.05 MMDのモーションデータで走らせてみよう

 本節ではMMDのモーションデータを使ってモデルを走らせてみましょう。
DXライブラリは非常にMMDと親和性が高く作られているため、MMDで作ったモーションデータを簡単に利用できます。
実は既に3d.01節でダウンロードされているプロジェクトにモーションデータが同梱されています。
プロジェクトの「dat/Lat式ミク」の中身をご覧ください。

「Lat式ミクVer2.3_Normal.pmd」というファイルがモデルのファイルです。
それと同じ名前+3桁の数字L.vmdという名前のファイルが4つありますね。



vmdというファイルはMMDで生成可能なモーションデータです。
MMDの使い方についてはここでは省略します。
MMDで作ったモーションデータを連番で上記のように記述すると、いちいちモーションデータを個別にロードせずとも、
モデルをロードするときに勝手に連番のファイルを探して一緒にロードしてくれます。
末尾の「L」はループするモーションかどうかを示します。ループしないモーションであればこの「L」はつけないでください。
詳細は本家のリファレンスをご覧ください。

本節のコードを実行すると以下のようになります。

実行結果


ソースコードは以下のようになります。。


/***** main.cpp *****/

#include <DxLib.h>

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
    ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK );

    int ModelHandle, AttachIndex ;
    float TotalTime, PlayTime ;

    // 3Dモデルの読み込み
    ModelHandle = MV1LoadModel( "dat/Lat式ミク/Lat式ミクVer2.3_Normal.pmd" ) ;

    //奥行0.1~1000までをカメラの描画範囲とする
    SetCameraNearFar( 0.1f, 1000.0f ) ;

    //(0,10,-20)の視点から(0,10,0)のターゲットを見る角度にカメラを設置
    SetCameraPositionAndTarget_UpVecY( VGet( 0, 10, -20 ), VGet( 0.0f, 10.0f, 0.0f ) ) ;

    // 3Dモデルの1番目のアニメーションをアタッチする
    AttachIndex = MV1AttachAnim( ModelHandle, 1, -1, FALSE ) ;

    // アタッチしたアニメーションの総再生時間を取得する
    TotalTime = MV1GetAttachAnimTotalTime( ModelHandle, AttachIndex ) ;

    // 再生時間の初期化
    PlayTime = 0.0f ;

    // 何かキーが押されるかウインドウが閉じられるまでループ
    while( !ScreenFlip() && !ProcessMessage() && !ClearDrawScreen() ){
    
        // 再生時間を進める
        PlayTime += 0.2f ;

        // 再生時間がアニメーションの総再生時間に達したら再生時間を0に戻す
        if( PlayTime >= TotalTime ){
            PlayTime = 0.0f ;
        }

        // 再生時間をセットする
        MV1SetAttachAnimTime( ModelHandle, AttachIndex, PlayTime ) ;

        // 3Dモデルの描画
        MV1DrawModel( ModelHandle ) ;
    }

    // DXライブラリの後始末
    DxLib_End() ;

    // ソフトの終了
    return 0 ;
}     


今回新しく使う関数の一つ目は MV1AttachAnim関数です。

宣言 int MV1AttachAnim( int MHandle, int AnimIndex, int AnimSrcMHandle, int NameCheck ) ;

概略 アニメーションをアタッチする

引数 int MHandle      : アニメーションをアタッチするモデルのハンドル
int AnimIndex     : アタッチするアニメーション番号
int AnimSrcMHandle : アタッチするアニメーションを持っているモデルのハンドル
               ( -1 を渡すと MHandle と同じモデルハンドルが使用されます )
int NameCheck    : AnimSrcMHandle が -1 以外の場合にアタッチするアニメーションの
              フレームの名前とアタッチされる側のモデルのフレームの名前が
              一致していない場合アタッチしないかどうか
              ( TRUE:アタッチしない FALSE:アタッチする )
              この引数は AnimSrcMHandle が -1 の場合は無視されます
戻り値 -1以外:アニメーションアタッチ番号
  -1:エラー発生


詳しくは本家のリファレンスをご覧ください。
モーションはアタッチ→再生という手順を踏む必要があります。
例えば
Lat式ミクVer2.3_Normal001L.vmd
のモーションデータをアタッチしたければ
MV1AttachAnim( ModelHandle, 1, -1, FALSE ) ;
のようになります。

指定時間のモーションの再生にはMV1SetAttachAnimTime関数を使います。

宣言 int MV1SetAttachAnimTime( int MHandle, int AttachIndex, float Time ) ;

概略 アタッチしているアニメーションの再生時間を設定する

引数 int MHandle : モデルのハンドル
int AttachIndex : 再生時間を設定するアニメーションのアタッチ番号
float Time : 再生時間
戻り値  0:成功
  -1:エラー発生

解説  MHandle のモデルハンドルが示すモデルにアタッチしたアニメーションの再生時間を設定します。

 DXライブラリのアニメーション機能には自動的にアニメーションを再生する機能はありませんので、 この関数を使用してアニメーションの再生時間を設定します。

 アニメーションのキーが存在しない時間が指定された場合は、 指定された時間の前後にあるキーからの補間値がモデルに反映されます。


モーションを再生するスピードは自分で管理します。
MV1SetAttachAnimTimeの引数Timeに渡す値をどの程度の勢いで増加させるかでモーションのスピードが変わります。
上のサンプルプログラムの例で言うと

// 再生時間を進める
PlayTime += 0.2f ;

この「0.2f」です。これを少なくしたり多くしたりすると遅くなったり速くなったりします。

※ファイル名末尾Lの記載についてジュンヤ様よりご指摘いただきました。ありがとうございます。

→分からないことがあれば掲示板で質問して下さい


- Remical Soft -