連載
» 2010年06月25日 00時00分 公開

“BREW”アプリケーション開発入門(10):MascotCapsuleによるボーンアニメーション (2/3)

[末永貴一(エイチアイ),@IT MONOist]

ボーンアニメーションの利用

 それでは、実際にプログラミングを行いたいと思います。

 なお今回は、前回「MascotCapsuleで立方体の3D描画に挑戦」のソースコードを拡張する形で実装を行いたいと思いますので、プロジェクトは前回のものを流用することとします。

 ここでの実装のポイントは、以下になります。

  • アニメーションデータ、テクスチャデータのロード
  • モデルデータへの関連付け
  • アニメーションフレームの設定

 それでは、ソースコードを確認してみましょう。プログラムの構造は、基本的に前回のものを流用し、「setup()」「drawEruption()」「cleanup()」「Applet構造体」に修正を加えます。多少混乱する部分もあるかもしれませんので、前回と同様部分も含めて関数内部を掲載します。

boolean setup(eruption1* pMe){
    hi_bool isCreate;              // 初期化判定
    hi_exception exception;        // 例外判定
    hi_sint32 WWidth;              // 画面サイズ幅
    hi_sint32 WHeight;             // 画面サイズ縦
    hi_sint32 property;            // アピアランス属性
    pMe->pIMC = NULL;              // Applet構造体の初期化
    ISHELL_CreateInstance (pMe->a.m_pIShell, AEECLSID_ERUPTION_A31, (void **)&pMe->pIMC);
    // eruptionの描画コンテキストの初期化
    isCreate = mceGraphics3D_initializeContext(&pMe->a);
    if (isCreate != HI_TRUE){
        return FALSE;
    }
    // eruptionの描画コンテキストの生成
    pMe->G3d = mceGraphics3D_create (&exception);
    if ((pMe->G3d == NULL) || (exception != hi_NoException)){
        return FALSE;
    }
    // 画面サイズの取得
    ISHELL_GetDeviceInfo(pMe->a.m_pIShell, &pMe->DeviceInfo);
    WWidth = pMe->DeviceInfo.cxScreen;
    WHeight = pMe->DeviceInfo.cyScreen;
    // フレームバッファのサイズを指定
    mceGraphics3D_setContextSize(pMe->G3d, WWidth, WHeight);
    // ビューポートの設定
    exception = mceGraphics3D_setViewport(pMe->G3d, 0, 0, WWidth, WHeight);
    if(exception != hi_NoException){
        return FALSE;
    }
    // クリッピング領域の設定
    exception = mceGraphics3D_setClip(pMe->G3d, 0, 0, WWidth, WHeight);
    if(exception != hi_NoException){
        return FALSE;
    }
    // カメラオブジェクト生成
    pMe->Camera = mceCamera_create (&exception);
    if ((pMe->Camera == NULL) || (exception != hi_NoException)){
        return FALSE;
    }
    // カメラの初期値設定(標準視野角)
    pMe->AspectRate = MCE_DIV((hi_coord)WWidth, (hi_coord)WHeight);
    pMe->ViewAngle  = MCE_F2C( 45.0f);
    pMe->NearClip    = MCE_F2C(  1.0f);
    pMe->FarClip     = MCE_F2C(100.0f);
    // データロード
    if (!dataLoad(pMe, "data\\boy.mcm")){        // mcmデータ
        return FALSE;
    }
    pMe->Figure = (mceFigure *)pMe->Obj3d [0];
    FREE (pMe->Obj3d);
    if (!dataLoad(pMe, "data\\boy.mca")){        // mcaデータ
        return FALSE;
    }
    pMe->Acttbl = (mceActionTable *)pMe->Obj3d [0];
    FREE (pMe->Obj3d);
    if (!dataLoad(pMe, "data\\boy.mct")){        // mctデータ
        return FALSE;
    }
    pMe->Textbl = (mceTextureTable *)pMe->Obj3d [0];
    FREE (pMe->Obj3d);
    // アニメーションフレームの取得
    pMe->AnimeEnd     = mceActionTable_getMaxFrame (pMe->Acttbl);
    pMe->AnimeCounter = MCE_F2C (0.0f);
    return TRUE;
} 
ソース1 setup()

 setup()内では、主に後半部分に修正を加えています。今回はモデルデータに加えてアニメーションデータ、テクスチャデータもロードしています。各データの利用については後述します。

 また、最後の部分でアニメーションデータによるボーンアニメーションを行うため、「アニメーションフレーム」の取得を行っています。アニメーションフレームとは、アニメーションの“コマ”のようなもので、コマを進めるとアニメーションが進むという考え方になります。このアニメーションの設定は、前述の3Dオーサリングツール上で行い、設定されたアニメーションをコマ割りにして再生するという考え方になります。ここでは、アニメーション再生に利用するカウンタの初期化と最終コマの取得を行っています。

boolean drawEruption(eruption1* pMe){
    uint32 now_time;            // 現在の経過時間
    hi_exception exception;     // 例外処理
    mceTransform matrix;        // 変換行列の計算用
    now_time = ISHELL_GetUpTimeMS(pMe->Applet.m_pIShell);
    if((now_time - pMe->OldTime) > UPDATE_TIME){
        pMe->OldTime = now_time;
        exception = mceGraphics3D_clear(pMe->G3d, MCE_GRAPHICS3D_CLEAR_DEPTH | 
                                        MCE_GRAPHICS3D_CLEAR_COLOR, 0x00808080);
        if (exception != hi_NoException){
            return 1;
        }
        exception = mceCamera_setPerspectiveFov(pMe->Camera, pMe->AspectRate, 
                                                pMe->ViewAngle / ANGLE,
                                                pMe->NearClip, pMe->FarClip);
        if (exception != hi_NoException){
            return 1;
        }
        // テクスチャの設定
        exception = mceFigure_bindTexture (pMe->Figure, pMe->Textbl);
        if (exception != hi_NoException){
            return 1;
        }
        // アニメーション設定
        exception = mceFigure_bindAction (pMe->Figure, pMe->Acttbl);
        if (exception != hi_NoException){
            return 1;
        }
        // モデルへのアニメーション設定
        exception = mceFigure_setFrame (pMe->Figure, pMe->AnimeCounter);
        if (exception != hi_NoException){
            return 1;
        }
        mceTransform_setTranslate(&matrix, MCE_F2C (0.0f), MCE_F2C (4.0f), MCE_F2C (20.0f));
        exception = mceGraphics3D_setCamera(pMe->G3d, pMe->Camera, &matrix); // カメラ設定
        if (exception != hi_NoException){
            return 1;
        }
        // mceFigureの描画
        exception =  mceGraphics3D_drawFigure(pMe->G3d, pMe->Figure, NULL, 0);
        if (exception != hi_NoException){
            return 1;
        }
        // 描画完了処理
        exception = mceGraphics3D_flush(pMe->G3d);
        if (exception != hi_NoException){
            return 1;
        }
        mceGraphics3D_swapContext ();
        pMe->AnimeCounter += MCE_F2C (1.0f);    // アニメーションフレームの更新
        // アニメーションフレームのリピート
        if(pMe->AnimeCounter >= pMe->AnimeEnd){
            pMe->AnimeCounter -= pMe->AnimeEnd;
        }
    }
    CALLBACK_Init(&pMe->Callback, (PFNNOTIFY)drawEruption, pMe);
    ISHELL_Resume(pMe->a.m_pIShell, &pMe->Callback);
    return TRUE;
} 
ソース2 drawEruption()

 drawEruption()内では、特にアニメーション処理の部分にポイントがあります。最初のポイントがsetup()内でロードしたモデルデータ、アニメーションデータ、テクスチャデータの関連付けです。「mceFigure_bindTexture()」「mceFigure_bindAction()」「mceFigure_setFrame()」は、それぞれもモデルデータ(Figure)に対してデータを関連付ける関数で、この設定によりモデルデータにテクスチャが張り付き、アニメーションができる状態になります。頂点情報が3Dの基本データであることを考えると、当然の設定だといえます。

 そして、後半部分でアニメーションフレームの更新とリピートを行うので、リピート設定も行っています。再生されるアニメーションのコマは、mceFigure_setFrame()によって設定されていますので、設定されたコマの状態が描画され、コマを毎フレーム進めることによりアニメーションになります。

 補足ですが、ここではキャラクタの表示位置調整のために「mceTransform_setTranslate()」「mceGraphics3D_setCamera()」の値を変更して、画面内の任意の状態に収まるような変更を行っています。

Copyright © ITmedia, Inc. All Rights Reserved.